From bb5e9fc9c654d2d65ea34e5de549908a1a257827 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 7 Feb 2025 11:39:11 +0100 Subject: [PATCH 01/27] feat(mdns): refactor stage #1 --- components/mdns/CMakeLists.txt | 7 +- components/mdns/mdns.c | 2827 ++--------------- components/mdns/mdns_browser.c | 13 + components/mdns/mdns_packet.c | 1945 ++++++++++++ components/mdns/mdns_querier.c | 13 + components/mdns/mdns_responder.c | 13 + components/mdns/mdns_service.c | 17 + components/mdns/mdns_utils.c | 299 ++ components/mdns/private_include/mdns_utils.h | 264 ++ .../mdns/tests/test_afl_fuzz_host/Makefile | 6 +- 10 files changed, 2853 insertions(+), 2551 deletions(-) create mode 100644 components/mdns/mdns_browser.c create mode 100644 components/mdns/mdns_packet.c create mode 100644 components/mdns/mdns_querier.c create mode 100644 components/mdns/mdns_responder.c create mode 100644 components/mdns/mdns_service.c create mode 100644 components/mdns/mdns_utils.c create mode 100644 components/mdns/private_include/mdns_utils.h diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 5823849b05..9ab5dc883b 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -12,15 +12,18 @@ endif() set(MDNS_MEMORY "mdns_mem_caps.c") +set(MDNS_CORE "mdns.c" "mdns_packet.c" "mdns_utils.c") +#set(MDNS_CORE "mdns.c" ) + idf_build_get_property(target IDF_TARGET) if(${target} STREQUAL "linux") set(dependencies esp_netif_linux esp_event) set(private_dependencies esp_timer console esp_system) - set(srcs "mdns.c" ${MDNS_MEMORY} ${MDNS_NETWORKING} ${MDNS_CONSOLE}) + set(srcs ${MDNS_CORE} ${MDNS_MEMORY} ${MDNS_NETWORKING} ${MDNS_CONSOLE}) else() set(dependencies lwip console esp_netif) set(private_dependencies esp_timer esp_wifi) - set(srcs "mdns.c" ${MDNS_MEMORY} ${MDNS_NETWORKING} ${MDNS_CONSOLE}) + set(srcs ${MDNS_CORE} ${MDNS_MEMORY} ${MDNS_NETWORKING} ${MDNS_CONSOLE}) endif() idf_component_register( diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 20ee5eead1..aa8352440c 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -17,10 +17,11 @@ #include "mdns_private.h" #include "mdns_networking.h" #include "mdns_mem_caps.h" +#include "mdns_utils.h" static void _mdns_browse_item_free(mdns_browse_t *browse); static esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse); -static esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync); +esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync); static void _mdns_browse_sync(mdns_browse_sync_t *browse_sync); static void _mdns_browse_finish(mdns_browse_t *browse); static void _mdns_browse_add(mdns_browse_t *browse); @@ -65,36 +66,37 @@ static volatile TaskHandle_t _mdns_service_task_handle = NULL; static SemaphoreHandle_t _mdns_service_semaphore = NULL; static StackType_t *_mdns_stack_buffer; -static void _mdns_search_finish_done(void); -static mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *search, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static mdns_browse_t *_mdns_browse_find_from(mdns_browse_t *b, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, - uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); -static void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); -static void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, - mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +//static void _mdns_search_finish_done(void); +//static mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *search, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +//static mdns_browse_t *_mdns_browse_find_from(mdns_browse_t *b, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +//static void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, +// uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +//static void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, +// mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +//static void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, +// mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, +// uint32_t ttl, mdns_browse_sync_t *out_sync_browse); #ifdef MDNS_ENABLE_DEBUG -static void debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t); -static void debug_printf_browse_result_all(mdns_result_t *r_t); +void debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t); +void debug_printf_browse_result_all(mdns_result_t *r_t); #endif // MDNS_ENABLE_DEBUG -static void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); -static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); -static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, - size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl); -static mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, - const char *service_type, const char *proto, mdns_if_t tcpip_if, - mdns_ip_protocol_t ip_protocol, uint32_t ttl); +//static void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, +// mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); +//static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, +// mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); +//static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, +// size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, +// uint32_t ttl); +//static mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, +// const char *service_type, const char *proto, mdns_if_t tcpip_if, +// mdns_ip_protocol_t ip_protocol, uint32_t ttl); static bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], size_t services_len, bool flush, bool bye); static bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye); -static void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); + static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); static void _mdns_query_results_free(mdns_result_t *results); + typedef enum { MDNS_IF_STA = 0, MDNS_IF_AP = 1, @@ -219,105 +221,84 @@ static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *esp_netif) return MDNS_MAX_INTERFACES; } +const char *mdns_utils_get_global_hostname(void) +{ + return _mdns_server ? _mdns_server->hostname : NULL; +} +mdns_srv_item_t *mdns_utils_get_services(void) +{ + return _mdns_server->services; +} -static inline bool _str_null_or_empty(const char *str) +mdns_host_item_t *mdns_utils_get_hosts(void) { - return (str == NULL || *str == 0); + return _mdns_host_list; } -/* - * @brief Appends/increments a number to name/instance in case of collision - * */ -static char *_mdns_mangle_name(char *in) +void mdns_utils_set_global_hostname(const char *hostname) { - char *p = strrchr(in, '-'); - int suffix = 0; - if (p == NULL) { - //No - in ``in`` - suffix = 2; - } else { - char *endp = NULL; - suffix = strtol(p + 1, &endp, 10); - if (*endp != 0) { - //suffix is not numerical - suffix = 2; - p = NULL; //so we append -suffix to the entire string - } - } - char *ret; - if (p == NULL) { - //need to add -2 to string - ret = mdns_mem_malloc(strlen(in) + 3); - if (ret == NULL) { - HOOK_MALLOC_FAILED; - return NULL; - } - sprintf(ret, "%s-2", in); - } else { - size_t in_len = strlen(in); - ret = mdns_mem_malloc(in_len + 2); //one extra byte in case 9-10 or 99-100 etc - if (ret == NULL) { - HOOK_MALLOC_FAILED; - return NULL; + if (_mdns_server) { + if (_mdns_server->hostname) { + mdns_mem_free((void *)_mdns_server->hostname); } - memcpy(ret, in, in_len); - int baseLen = p - in; //length of 'bla' in 'bla-123' - //overwrite suffix with new suffix - sprintf(ret + baseLen, "-%d", suffix + 1); + _mdns_server->hostname = hostname; + _mdns_self_host.hostname = hostname; } - return ret; } -static bool _mdns_service_match(const mdns_service_t *srv, const char *service, const char *proto, - const char *hostname) +const char *mdns_utils_get_instance(void) { - if (!service || !proto || !srv->hostname) { - return false; - } - return !strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && - (_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); + return _mdns_server ? _mdns_server->instance : NULL; } -/** - * @brief finds service from given service type - * @param server the server - * @param service service type to match - * @param proto proto to match - * @param hostname hostname of the service (if non-null) - * - * @return the service item if found or NULL on error - */ -static mdns_srv_item_t *_mdns_get_service_item(const char *service, const char *proto, const char *hostname) +void mdns_utils_set_instance(const char *instance) { - mdns_srv_item_t *s = _mdns_server->services; - while (s) { - if (_mdns_service_match(s->service, service, proto, hostname)) { - return s; + if (_mdns_server) { + if (_mdns_server->instance) { + mdns_mem_free((void *)_mdns_server->instance); } - s = s->next; + _mdns_server->instance = instance; } - return NULL; } -static mdns_srv_item_t *_mdns_get_service_item_subtype(const char *subtype, const char *service, const char *proto) +mdns_search_once_t *mdns_utils_get_search(void) { - mdns_srv_item_t *s = _mdns_server->services; - while (s) { - if (_mdns_service_match(s->service, service, proto, NULL)) { - mdns_subtype_t *subtype_item = s->service->subtype; - while (subtype_item) { - if (!strcasecmp(subtype_item->subtype, subtype)) { - return s; - } - subtype_item = subtype_item->next; - } - } - s = s->next; - } - return NULL; + return _mdns_server->search_once; +} + +mdns_browse_t *mdns_utils_get_browse(void) +{ + return _mdns_server->browse; +} + +static inline bool _str_null_or_empty(const char *str) +{ + return (str == NULL || *str == 0); +} + +mdns_tx_packet_t *mdns_utils_get_tx_packet(void) +{ + return _mdns_server->tx_queue_head; } +bool mdns_utils_is_probing(mdns_rx_packet_t *packet) +{ + return _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running; +} + +bool mdns_utils_after_probing(mdns_rx_packet_t *packet) +{ + return _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].state > PCB_PROBE_3; +} + +void mdns_utils_probe_failed(mdns_rx_packet_t *packet) +{ + _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; +} + + + static mdns_host_item_t *mdns_get_host_item(const char *hostname) { if (hostname == NULL || strcasecmp(hostname, _mdns_server->hostname) == 0) { @@ -370,137 +351,13 @@ esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) return ESP_OK; } -static const char *_mdns_get_default_instance_name(void) -{ - if (_mdns_server && !_str_null_or_empty(_mdns_server->instance)) { - return _mdns_server->instance; - } - - if (_mdns_server && !_str_null_or_empty(_mdns_server->hostname)) { - return _mdns_server->hostname; - } - return NULL; -} -/** - * @brief Get the service name of a service - */ -static const char *_mdns_get_service_instance_name(const mdns_service_t *service) -{ - if (service && !_str_null_or_empty(service->instance)) { - return service->instance; - } - return _mdns_get_default_instance_name(); -} -static bool _mdns_instance_name_match(const char *lhs, const char *rhs) -{ - if (lhs == NULL) { - lhs = _mdns_get_default_instance_name(); - } - if (rhs == NULL) { - rhs = _mdns_get_default_instance_name(); - } - return !strcasecmp(lhs, rhs); -} -static bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instance, const char *service, - const char *proto, const char *hostname) -{ - // service and proto must be supplied, if not this instance won't match - if (!service || !proto) { - return false; - } - // instance==NULL -> _mdns_instance_name_match() will check the default instance - // hostname==NULL -> matches if instance, service and proto matches - return !strcasecmp(srv->service, service) && _mdns_instance_name_match(srv->instance, instance) && - !strcasecmp(srv->proto, proto) && (_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); -} -static mdns_srv_item_t *_mdns_get_service_item_instance(const char *instance, const char *service, const char *proto, - const char *hostname) -{ - mdns_srv_item_t *s = _mdns_server->services; - while (s) { - if (instance) { - if (_mdns_service_match_instance(s->service, instance, service, proto, hostname)) { - return s; - } - } else { - if (_mdns_service_match(s->service, service, proto, hostname)) { - return s; - } - } - s = s->next; - } - return NULL; -} -/** - * @brief reads MDNS FQDN into mdns_name_t structure - * FQDN is in format: [hostname.|[instance.]_service._proto.]local. - * - * @param packet MDNS packet - * @param start Starting point of FQDN - * @param name mdns_name_t structure to populate - * @param buf temporary char buffer - * - * @return the address after the parsed FQDN in the packet or NULL on error - */ -static const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len) -{ - size_t index = 0; - const uint8_t *packet_end = packet + packet_len; - while (start + index < packet_end && start[index]) { - if (name->parts == 4) { - name->invalid = true; - } - uint8_t len = start[index++]; - if (len < 0xC0) { - if (len > 63) { - //length can not be more than 63 - return NULL; - } - uint8_t i; - for (i = 0; i < len; i++) { - if (start + index >= packet_end) { - return NULL; - } - buf[i] = start[index++]; - } - buf[len] = '\0'; - if (name->parts == 1 && buf[0] != '_' - && (strcasecmp(buf, MDNS_DEFAULT_DOMAIN) != 0) - && (strcasecmp(buf, "arpa") != 0) -#ifndef CONFIG_MDNS_RESPOND_REVERSE_QUERIES - && (strcasecmp(buf, "ip6") != 0) - && (strcasecmp(buf, "in-addr") != 0) -#endif - ) { - strlcat(name->host, ".", sizeof(name->host)); - strlcat(name->host, buf, sizeof(name->host)); - } else if (strcasecmp(buf, MDNS_SUB_STR) == 0) { - name->sub = 1; - } else if (!name->invalid) { - char *mdns_name_ptrs[] = {name->host, name->service, name->proto, name->domain}; - memcpy(mdns_name_ptrs[name->parts++], buf, len + 1); - } - } else { - size_t address = (((uint16_t)len & 0x3F) << 8) | start[index++]; - if ((packet + address) >= start) { - //reference address can not be after where we are - return NULL; - } - if (_mdns_read_fqdn(packet, packet + address, name, buf, packet_len)) { - return start + index; - } - return NULL; - } - } - return start + index + 1; -} /** * @brief sets uint16_t value in a packet @@ -518,169 +375,7 @@ static inline void _mdns_set_u16(uint8_t *packet, uint16_t index, uint16_t value packet[index + 1] = value & 0xFF; } -/** - * @brief appends byte in a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param value the value to set - * - * @return length of added data: 0 on error or 1 on success - */ -static inline uint8_t _mdns_append_u8(uint8_t *packet, uint16_t *index, uint8_t value) -{ - if (*index >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - packet[*index] = value; - *index += 1; - return 1; -} - -/** - * @brief appends uint16_t in a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param value the value to set - * - * @return length of added data: 0 on error or 2 on success - */ -static inline uint8_t _mdns_append_u16(uint8_t *packet, uint16_t *index, uint16_t value) -{ - if ((*index + 1) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, (value >> 8) & 0xFF); - _mdns_append_u8(packet, index, value & 0xFF); - return 2; -} - -/** - * @brief appends uint32_t in a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param value the value to set - * - * @return length of added data: 0 on error or 4 on success - */ -static inline uint8_t _mdns_append_u32(uint8_t *packet, uint16_t *index, uint32_t value) -{ - if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, (value >> 24) & 0xFF); - _mdns_append_u8(packet, index, (value >> 16) & 0xFF); - _mdns_append_u8(packet, index, (value >> 8) & 0xFF); - _mdns_append_u8(packet, index, value & 0xFF); - return 4; -} - -/** - * @brief appends answer type, class, ttl and data length to a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param type answer type - * @param ttl answer ttl - * - * @return length of added data: 0 on error or 10 on success - */ -static inline uint8_t _mdns_append_type(uint8_t *packet, uint16_t *index, uint8_t type, bool flush, uint32_t ttl) -{ - if ((*index + 10) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - uint16_t mdns_class = MDNS_CLASS_IN; - if (flush) { - mdns_class = MDNS_CLASS_IN_FLUSH_CACHE; - } - if (type == MDNS_ANSWER_PTR) { - _mdns_append_u16(packet, index, MDNS_TYPE_PTR); - _mdns_append_u16(packet, index, mdns_class); - } else if (type == MDNS_ANSWER_TXT) { - _mdns_append_u16(packet, index, MDNS_TYPE_TXT); - _mdns_append_u16(packet, index, mdns_class); - } else if (type == MDNS_ANSWER_SRV) { - _mdns_append_u16(packet, index, MDNS_TYPE_SRV); - _mdns_append_u16(packet, index, mdns_class); - } else if (type == MDNS_ANSWER_A) { - _mdns_append_u16(packet, index, MDNS_TYPE_A); - _mdns_append_u16(packet, index, mdns_class); - } else if (type == MDNS_ANSWER_AAAA) { - _mdns_append_u16(packet, index, MDNS_TYPE_AAAA); - _mdns_append_u16(packet, index, mdns_class); - } else { - return 0; - } - _mdns_append_u32(packet, index, ttl); - _mdns_append_u16(packet, index, 0); - return 10; -} - -static inline uint8_t _mdns_append_string_with_len(uint8_t *packet, uint16_t *index, const char *string, uint8_t len) -{ - if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, len); - memcpy(packet + *index, string, len); - *index += len; - return len + 1; -} - -/** - * @brief appends single string to a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param string the string to append - * - * @return length of added data: 0 on error or length of the string + 1 on success - */ -static inline uint8_t _mdns_append_string(uint8_t *packet, uint16_t *index, const char *string) -{ - uint8_t len = strlen(string); - if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, len); - memcpy(packet + *index, string, len); - *index += len; - return len + 1; -} -/** - * @brief appends one TXT record ("key=value" or "key") - * - * @param packet MDNS packet - * @param index offset in the packet - * @param txt one txt record - * - * @return length of added data: length of the added txt value + 1 on success - * 0 if data won't fit the packet - * -1 if invalid TXT entry - */ -static inline int append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt) -{ - if (txt == NULL || txt->key == NULL) { - return -1; - } - size_t key_len = strlen(txt->key); - size_t len = key_len + txt->value_len + (txt->value ? 1 : 0); - if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, len); - memcpy(packet + *index, txt->key, key_len); - if (txt->value) { - packet[*index + key_len] = '='; - memcpy(packet + *index + key_len + 1, txt->value, txt->value_len); - } - *index += len; - return len + 1; -} #ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES static inline int append_single_str(uint8_t *packet, uint16_t *index, const char *str, int len) @@ -1239,7 +934,7 @@ static uint16_t _mdns_append_question(uint8_t *packet, uint16_t *index, mdns_out * @brief Helper to get either ETH or STA if the other is provided * Used when two interfaces are on the same subnet */ -static mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if) +mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if) { if (tcpip_if < MDNS_MAX_INTERFACES) { return s_esp_netifs[tcpip_if].duplicate; @@ -1270,7 +965,7 @@ static bool _mdns_if_is_dup(mdns_if_t tcpip_if) /** * @brief Check if IPv6 address is NULL */ -static bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) +bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) { uint8_t i; uint8_t *data = (uint8_t *)ip6.addr; @@ -1664,39 +1359,6 @@ static mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_p return NULL; } -/** - * @brief Find, remove and free answer from the scheduled packets - */ -static void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service) -{ - mdns_srv_item_t s = {NULL, NULL}; - if (!service) { - service = &s; - } - mdns_tx_packet_t *q = _mdns_server->tx_queue_head; - while (q) { - if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol && q->distributed) { - mdns_out_answer_t *a = q->answers; - if (a) { - if (a->type == type && a->service == service->service) { - q->answers = q->answers->next; - mdns_mem_free(a); - } else { - while (a->next) { - if (a->next->type == type && a->next->service == service->service) { - mdns_out_answer_t *b = a->next; - a->next = b->next; - mdns_mem_free(b); - break; - } - a = a->next; - } - } - } - } - q = q->next; - } -} /** * @brief Remove and free answer from answer list (destination) @@ -1859,7 +1521,7 @@ static bool _mdns_service_match_ptr_question(const mdns_service_t *service, cons /** * @brief Create answer packet to questions from parsed packet */ -static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) +void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) { if (!parsed_packet->questions) { return; @@ -2233,7 +1895,7 @@ static mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *prob /** * @brief Send by for particular services on particular PCB */ -static void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) +void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) { mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); if (!packet) { @@ -2313,7 +1975,7 @@ static void _mdns_init_pcb_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protoco * - If pcb probing then add only non-probing services and restarts probing * - If pcb not probing, run probing for all specified services */ -static void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) +void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) { mdns_pcb_t *pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; @@ -2491,7 +2153,7 @@ static void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco /** * @brief Send probe on all active PCBs */ -static void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe) +void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe) { uint8_t i, j; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { @@ -2579,7 +2241,7 @@ static void _mdns_send_bye_all_pcbs_no_instance(bool include_ip) /** * @brief Restart the responder on all services without instance */ -static void _mdns_restart_all_pcbs_no_instance(void) +void _mdns_restart_all_pcbs_no_instance(void) { size_t srv_count = 0; mdns_srv_item_t *a = _mdns_server->services; @@ -2607,7 +2269,7 @@ static void _mdns_restart_all_pcbs_no_instance(void) /** * @brief Restart the responder on all active PCBs */ -static void _mdns_restart_all_pcbs(void) +void _mdns_restart_all_pcbs(void) { _mdns_clear_tx_queue_head(); size_t srv_count = 0; @@ -2906,107 +2568,8 @@ static void _mdns_free_service(mdns_service_t *service) * Received Packet Handling * */ -/** - * @brief Detect SRV collision - */ -static int _mdns_check_srv_collision(mdns_service_t *service, uint16_t priority, uint16_t weight, uint16_t port, const char *host, const char *domain) -{ - if (_str_null_or_empty(_mdns_server->hostname)) { - return 0; - } - - size_t our_host_len = strlen(_mdns_server->hostname); - size_t our_len = 14 + our_host_len; - - size_t their_host_len = strlen(host); - size_t their_domain_len = strlen(domain); - size_t their_len = 9 + their_host_len + their_domain_len; - - if (their_len > our_len) { - return 1;//they win - } else if (their_len < our_len) { - return -1;//we win - } - - uint16_t our_index = 0; - uint8_t our_data[our_len]; - _mdns_append_u16(our_data, &our_index, service->priority); - _mdns_append_u16(our_data, &our_index, service->weight); - _mdns_append_u16(our_data, &our_index, service->port); - our_data[our_index++] = our_host_len; - memcpy(our_data + our_index, _mdns_server->hostname, our_host_len); - our_index += our_host_len; - our_data[our_index++] = 5; - memcpy(our_data + our_index, MDNS_DEFAULT_DOMAIN, 5); - our_index += 5; - our_data[our_index++] = 0; - - uint16_t their_index = 0; - uint8_t their_data[their_len]; - _mdns_append_u16(their_data, &their_index, priority); - _mdns_append_u16(their_data, &their_index, weight); - _mdns_append_u16(their_data, &their_index, port); - their_data[their_index++] = their_host_len; - memcpy(their_data + their_index, host, their_host_len); - their_index += their_host_len; - their_data[their_index++] = their_domain_len; - memcpy(their_data + their_index, domain, their_domain_len); - their_index += their_domain_len; - their_data[their_index++] = 0; - - int ret = memcmp(our_data, their_data, our_len); - if (ret > 0) { - return -1;//we win - } else if (ret < 0) { - return 1;//they win - } - return 0;//same -} - -/** - * @brief Detect TXT collision - */ -static int _mdns_check_txt_collision(mdns_service_t *service, const uint8_t *data, size_t len) -{ - size_t data_len = 0; - if (len <= 1 && service->txt) { // len==0 means incorrect packet (and handled by the packet parser) - // but handled here again to fix clang-tidy warning on VLA "uint8_t our[0];" - return -1;//we win - } else if (len > 1 && !service->txt) { - return 1;//they win - } else if (len <= 1 && !service->txt) { - return 0;//same - } - - mdns_txt_linked_item_t *txt = service->txt; - while (txt) { - data_len += 1 /* record-len */ + strlen(txt->key) + txt->value_len + (txt->value ? 1 : 0 /* "=" */); - txt = txt->next; - } - - if (len > data_len) { - return 1;//they win - } else if (len < data_len) { - return -1;//we win - } - - uint8_t ours[len]; - uint16_t index = 0; - txt = service->txt; - while (txt) { - append_one_txt_record_entry(ours, &index, txt); - txt = txt->next; - } - int ret = memcmp(ours, data, len); - if (ret > 0) { - return -1;//we win - } else if (ret < 0) { - return 1;//they win - } - return 0;//same -} static esp_err_t mdns_pcb_deinit_local(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_proto) { @@ -3027,7 +2590,7 @@ static esp_err_t mdns_pcb_deinit_local(mdns_if_t tcpip_if, mdns_ip_protocol_t ip /** * @brief Set interface as duplicate if another is found on the same subnet */ -static void _mdns_dup_interface(mdns_if_t tcpip_if) +void _mdns_dup_interface(mdns_if_t tcpip_if) { uint8_t i; mdns_if_t other_if = _mdns_get_other_if(tcpip_if); @@ -3047,1310 +2610,136 @@ static void _mdns_dup_interface(mdns_if_t tcpip_if) } } -#ifdef CONFIG_LWIP_IPV4 + + + + /** - * @brief Detect IPv4 address collision + * @brief Adds a delegated hostname to the linked list + * @param hostname Host name pointer + * @param address_list Address list + * @return true on success + * false if the host wasn't attached (this is our hostname, or alloc failure) so we have to free the structs */ -static int _mdns_check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) +static bool _mdns_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *address_list) { - esp_netif_ip_info_t if_ip_info; - esp_netif_ip_info_t other_ip_info; - if (!ip->addr) { - return 1;//denial! they win - } - if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { - return 1;//they win - } - int ret = memcmp((uint8_t *)&if_ip_info.ip.addr, (uint8_t *)&ip->addr, sizeof(esp_ip4_addr_t)); - if (ret > 0) { - return -1;//we win - } else if (ret < 0) { - //is it the other interface? - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); - if (other_if == MDNS_MAX_INTERFACES) { - return 1;//AP interface! They win - } - if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &other_ip_info)) { - return 1;//IPv4 not active! They win - } - if (ip->addr != other_ip_info.ip.addr) { - return 1;//IPv4 not ours! They win - } - _mdns_dup_interface(tcpip_if); - return 2;//they win + if (_hostname_is_ours(hostname)) { + return false; } - return 0;//same -} -#endif /* CONFIG_LWIP_IPV4 */ - -#ifdef CONFIG_LWIP_IPV6 -/** - * @brief Detect IPv6 address collision - */ -static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) -{ - struct esp_ip6_addr if_ip6; - struct esp_ip6_addr other_ip6; - if (_ipv6_address_is_zero(*ip)) { - return 1;//denial! they win - } - if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(tcpip_if), &if_ip6)) { - return 1;//they win - } - int ret = memcmp((uint8_t *)&if_ip6.addr, (uint8_t *)ip->addr, _MDNS_SIZEOF_IP6_ADDR); - if (ret > 0) { - return -1;//we win - } else if (ret < 0) { - //is it the other interface? - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); - if (other_if == MDNS_MAX_INTERFACES) { - return 1;//AP interface! They win - } - if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &other_ip6)) { - return 1;//IPv6 not active! They win - } - if (memcmp((uint8_t *)&other_ip6.addr, (uint8_t *)ip->addr, _MDNS_SIZEOF_IP6_ADDR)) { - return 1;//IPv6 not ours! They win - } - _mdns_dup_interface(tcpip_if); - return 2;//they win - } - return 0;//same -} -#endif /* CONFIG_LWIP_IPV6 */ - -static bool _hostname_is_ours(const char *hostname) -{ - if (!_str_null_or_empty(_mdns_server->hostname) && - strcasecmp(hostname, _mdns_server->hostname) == 0) { - return true; - } - mdns_host_item_t *host = _mdns_host_list; - while (host != NULL) { - if (strcasecmp(hostname, host->hostname) == 0) { - return true; - } - host = host->next; - } - return false; -} - -/** - * @brief Adds a delegated hostname to the linked list - * @param hostname Host name pointer - * @param address_list Address list - * @return true on success - * false if the host wasn't attached (this is our hostname, or alloc failure) so we have to free the structs - */ -static bool _mdns_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *address_list) -{ - if (_hostname_is_ours(hostname)) { - return false; - } - - mdns_host_item_t *host = (mdns_host_item_t *)mdns_mem_malloc(sizeof(mdns_host_item_t)); - - if (host == NULL) { - return false; - } - host->address_list = address_list; - host->hostname = hostname; - host->next = _mdns_host_list; - _mdns_host_list = host; - return true; -} - -static void free_address_list(mdns_ip_addr_t *address_list) -{ - while (address_list != NULL) { - mdns_ip_addr_t *next = address_list->next; - mdns_mem_free(address_list); - address_list = next; - } -} - - -static bool _mdns_delegate_hostname_set_address(const char *hostname, mdns_ip_addr_t *address_list) -{ - if (!_str_null_or_empty(_mdns_server->hostname) && - strcasecmp(hostname, _mdns_server->hostname) == 0) { - return false; - } - mdns_host_item_t *host = _mdns_host_list; - while (host != NULL) { - if (strcasecmp(hostname, host->hostname) == 0) { - // free previous address list - free_address_list(host->address_list); - // set current address list to the host - host->address_list = address_list; - return true; - } - host = host->next; - } - return false; -} - -static mdns_ip_addr_t *copy_address_list(const mdns_ip_addr_t *address_list) -{ - mdns_ip_addr_t *head = NULL; - mdns_ip_addr_t *tail = NULL; - while (address_list != NULL) { - mdns_ip_addr_t *addr = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); - if (addr == NULL) { - free_address_list(head); - return NULL; - } - addr->addr = address_list->addr; - addr->next = NULL; - if (head == NULL) { - head = addr; - tail = addr; - } else { - tail->next = addr; - tail = tail->next; - } - address_list = address_list->next; - } - return head; -} - -static void free_delegated_hostnames(void) -{ - mdns_host_item_t *host = _mdns_host_list; - while (host != NULL) { - free_address_list(host->address_list); - mdns_mem_free((char *)host->hostname); - mdns_host_item_t *item = host; - host = host->next; - mdns_mem_free(item); - } - _mdns_host_list = NULL; -} - -static bool _mdns_delegate_hostname_remove(const char *hostname) -{ - mdns_srv_item_t *srv = _mdns_server->services; - mdns_srv_item_t *prev_srv = NULL; - while (srv) { - if (strcasecmp(srv->service->hostname, hostname) == 0) { - mdns_srv_item_t *to_free = srv; - _mdns_send_bye(&srv, 1, false); - _mdns_remove_scheduled_service_packets(srv->service); - if (prev_srv == NULL) { - _mdns_server->services = srv->next; - srv = srv->next; - } else { - prev_srv->next = srv->next; - srv = srv->next; - } - _mdns_free_service(to_free->service); - mdns_mem_free(to_free); - } else { - prev_srv = srv; - srv = srv->next; - } - } - mdns_host_item_t *host = _mdns_host_list; - mdns_host_item_t *prev_host = NULL; - while (host != NULL) { - if (strcasecmp(hostname, host->hostname) == 0) { - if (prev_host == NULL) { - _mdns_host_list = host->next; - } else { - prev_host->next = host->next; - } - free_address_list(host->address_list); - mdns_mem_free((char *)host->hostname); - mdns_mem_free(host); - break; - } else { - prev_host = host; - host = host->next; - } - } - return true; -} - -/** - * @brief Check if parsed name is discovery - */ -static bool _mdns_name_is_discovery(mdns_name_t *name, uint16_t type) -{ - return ( - (name->host[0] && !strcasecmp(name->host, "_services")) - && (name->service[0] && !strcasecmp(name->service, "_dns-sd")) - && (name->proto[0] && !strcasecmp(name->proto, "_udp")) - && (name->domain[0] && !strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN)) - && type == MDNS_TYPE_PTR - ); -} - -/** - * @brief Check if the parsed name is self-hosted, i.e. we should resolve conflicts - */ -static bool _mdns_name_is_selfhosted(mdns_name_t *name) -{ - if (_str_null_or_empty(_mdns_server->hostname)) { // self-hostname needs to be defined - return false; - } - - // hostname only -- check if selfhosted name - if (_str_null_or_empty(name->service) && _str_null_or_empty(name->proto) && - strcasecmp(name->host, _mdns_server->hostname) == 0) { - return true; - } - - // service -- check if selfhosted service - mdns_srv_item_t *srv = _mdns_get_service_item(name->service, name->proto, NULL); - if (srv && strcasecmp(_mdns_server->hostname, srv->service->hostname) == 0) { - return true; - } - return false; -} - -/** - * @brief Check if the parsed name is ours (matches service or host name) - */ -static bool _mdns_name_is_ours(mdns_name_t *name) -{ - //domain have to be "local" - if (_str_null_or_empty(name->domain) || (strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN) -#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES - && strcasecmp(name->domain, "arpa") -#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ - )) { - return false; - } - - //if service and proto are empty, host must match out hostname - if (_str_null_or_empty(name->service) && _str_null_or_empty(name->proto)) { - if (!_str_null_or_empty(name->host) - && !_str_null_or_empty(_mdns_server->hostname) - && _hostname_is_ours(name->host)) { - return true; - } - return false; - } - - //if service or proto is empty, name is invalid - if (_str_null_or_empty(name->service) || _str_null_or_empty(name->proto)) { - return false; - } - - - //find the service - mdns_srv_item_t *service; - if (name->sub) { - service = _mdns_get_service_item_subtype(name->host, name->service, name->proto); - } else if (_str_null_or_empty(name->host)) { - service = _mdns_get_service_item(name->service, name->proto, NULL); - } else { - service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL); - } - if (!service) { - return false; - } - - //if query is PTR query and we have service, we have success - if (name->sub || _str_null_or_empty(name->host)) { - return true; - } - - //OK we have host in the name. find what is the instance of the service - const char *instance = _mdns_get_service_instance_name(service->service); - if (instance == NULL) { - return false; - } - - //compare the instance against the name - if (strcasecmp(name->host, instance) == 0) { - return true; - } - - return false; -} - -/** - * @brief read uint16_t from a packet - * @param packet the packet - * @param index index in the packet where the value starts - * - * @return the value - */ -static inline uint16_t _mdns_read_u16(const uint8_t *packet, uint16_t index) -{ - return (uint16_t)(packet[index]) << 8 | packet[index + 1]; -} - -/** - * @brief read uint32_t from a packet - * @param packet the packet - * @param index index in the packet where the value starts - * - * @return the value - */ -static inline uint32_t _mdns_read_u32(const uint8_t *packet, uint16_t index) -{ - return (uint32_t)(packet[index]) << 24 | (uint32_t)(packet[index + 1]) << 16 | (uint32_t)(packet[index + 2]) << 8 | packet[index + 3]; -} - -/** - * @brief reads and formats MDNS FQDN into mdns_name_t structure - * - * @param packet MDNS packet - * @param start Starting point of FQDN - * @param name mdns_name_t structure to populate - * - * @return the address after the parsed FQDN in the packet or NULL on error - */ -static const uint8_t *_mdns_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, size_t packet_len) -{ - name->parts = 0; - name->sub = 0; - name->host[0] = 0; - name->service[0] = 0; - name->proto[0] = 0; - name->domain[0] = 0; - name->invalid = false; - - static char buf[MDNS_NAME_BUF_LEN]; - - const uint8_t *next_data = (uint8_t *)_mdns_read_fqdn(packet, start, name, buf, packet_len); - if (!next_data) { - return 0; - } - if (!name->parts || name->invalid) { - return next_data; - } - if (name->parts == 3) { - memmove((uint8_t *)name + (MDNS_NAME_BUF_LEN), (uint8_t *)name, 3 * (MDNS_NAME_BUF_LEN)); - name->host[0] = 0; - } else if (name->parts == 2) { - memmove((uint8_t *)(name->domain), (uint8_t *)(name->service), (MDNS_NAME_BUF_LEN)); - name->service[0] = 0; - name->proto[0] = 0; - } - if (strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN) == 0 || strcasecmp(name->domain, "arpa") == 0) { - return next_data; - } - name->invalid = true; // mark the current name invalid, but continue with other question - return next_data; -} - -/** - * @brief Called from parser to check if question matches particular service - */ -static bool _mdns_question_matches(mdns_parsed_question_t *question, uint16_t type, mdns_srv_item_t *service) -{ - if (question->type != type) { - return false; - } - if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { - return true; - } else if (type == MDNS_TYPE_PTR || type == MDNS_TYPE_SDPTR) { - if (question->service && question->proto && question->domain - && !strcasecmp(service->service->service, question->service) - && !strcasecmp(service->service->proto, question->proto) - && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { - if (!service->service->instance) { - return true; - } else if (service->service->instance && question->host && !strcasecmp(service->service->instance, question->host)) { - return true; - } - } - } else if (service && (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT)) { - const char *name = _mdns_get_service_instance_name(service->service); - if (name && question->host && question->service && question->proto && question->domain - && !strcasecmp(name, question->host) - && !strcasecmp(service->service->service, question->service) - && !strcasecmp(service->service->proto, question->proto) - && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { - return true; - } - } - - return false; -} - -/** - * @brief Removes saved question from parsed data - */ -static void _mdns_remove_parsed_question(mdns_parsed_packet_t *parsed_packet, uint16_t type, mdns_srv_item_t *service) -{ - mdns_parsed_question_t *q = parsed_packet->questions; - - if (_mdns_question_matches(q, type, service)) { - parsed_packet->questions = q->next; - mdns_mem_free(q->host); - mdns_mem_free(q->service); - mdns_mem_free(q->proto); - mdns_mem_free(q->domain); - mdns_mem_free(q); - return; - } - - while (q->next) { - mdns_parsed_question_t *p = q->next; - if (_mdns_question_matches(p, type, service)) { - q->next = p->next; - mdns_mem_free(p->host); - mdns_mem_free(p->service); - mdns_mem_free(p->proto); - mdns_mem_free(p->domain); - mdns_mem_free(p); - return; - } - q = q->next; - } -} - -/** - * @brief Get number of items in TXT parsed data - */ -static int _mdns_txt_items_count_get(const uint8_t *data, size_t len) -{ - if (len == 1) { - return 0; - } - - int num_items = 0; - uint16_t i = 0; - size_t partLen = 0; - - while (i < len) { - partLen = data[i++]; - if (!partLen) { - break; - } - if ((i + partLen) > len) { - return -1;//error - } - i += partLen; - num_items++; - } - return num_items; -} - -/** - * @brief Get the length of TXT item's key name - */ -static int _mdns_txt_item_name_get_len(const uint8_t *data, size_t len) -{ - if (*data == '=') { - return -1; - } - for (size_t i = 0; i < len; i++) { - if (data[i] == '=') { - return i; - } - } - return len; -} - -/** - * @brief Create TXT result array from parsed TXT data - */ -static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_item_t **out_txt, uint8_t **out_value_len, - size_t *out_count) -{ - *out_txt = NULL; - *out_count = 0; - uint16_t i = 0, y; - size_t partLen = 0; - int num_items = _mdns_txt_items_count_get(data, len); - if (num_items < 0 || num_items > SIZE_MAX / sizeof(mdns_txt_item_t)) { - // Error: num_items is incorrect (or too large to allocate) - return; - } - - if (!num_items) { - return; - } - - mdns_txt_item_t *txt = (mdns_txt_item_t *)mdns_mem_malloc(sizeof(mdns_txt_item_t) * num_items); - if (!txt) { - HOOK_MALLOC_FAILED; - return; - } - uint8_t *txt_value_len = (uint8_t *)mdns_mem_malloc(num_items); - if (!txt_value_len) { - mdns_mem_free(txt); - HOOK_MALLOC_FAILED; - return; - } - memset(txt, 0, sizeof(mdns_txt_item_t) * num_items); - memset(txt_value_len, 0, num_items); - size_t txt_num = 0; - - while (i < len) { - partLen = data[i++]; - if (!partLen) { - break; - } - - if ((i + partLen) > len) { - goto handle_error;//error - } - - int name_len = _mdns_txt_item_name_get_len(data + i, partLen); - if (name_len < 0 || txt_num >= num_items) {//invalid item (no name or more items than expected) - i += partLen; - continue; - } - char *key = (char *)mdns_mem_malloc(name_len + 1); - if (!key) { - HOOK_MALLOC_FAILED; - goto handle_error;//error - } - mdns_txt_item_t *t = &txt[txt_num]; - uint8_t *value_len = &txt_value_len[txt_num]; - txt_num++; - - memcpy(key, data + i, name_len); - key[name_len] = 0; - i += name_len + 1; - t->key = key; - - int new_value_len = partLen - name_len - 1; - if (new_value_len > 0) { - char *value = (char *)mdns_mem_malloc(new_value_len + 1); - if (!value) { - HOOK_MALLOC_FAILED; - goto handle_error;//error - } - memcpy(value, data + i, new_value_len); - value[new_value_len] = 0; - *value_len = new_value_len; - i += new_value_len; - t->value = value; - } else { - t->value = NULL; - } - } - - *out_txt = txt; - *out_count = txt_num; - *out_value_len = txt_value_len; - return; - -handle_error : - for (y = 0; y < txt_num; y++) { - mdns_txt_item_t *t = &txt[y]; - mdns_mem_free((char *)t->key); - mdns_mem_free((char *)t->value); - } - mdns_mem_free(txt_value_len); - mdns_mem_free(txt); -} - -/** - * @brief Duplicate string or return error - */ -static esp_err_t _mdns_strdup_check(char **out, char *in) -{ - if (in && in[0]) { - *out = mdns_mem_strdup(in); - if (!*out) { - return ESP_FAIL; - } - return ESP_OK; - } - *out = NULL; - return ESP_OK; -} - -/** - * @brief main packet parser - * - * @param packet the packet - */ -void mdns_parse_packet(mdns_rx_packet_t *packet) -{ - static mdns_name_t n; - mdns_header_t header; - const uint8_t *data = _mdns_get_packet_data(packet); - size_t len = _mdns_get_packet_len(packet); - const uint8_t *content = data + MDNS_HEAD_LEN; - bool do_not_reply = false; - mdns_search_once_t *search_result = NULL; - mdns_browse_t *browse_result = NULL; - char *browse_result_instance = NULL; - char *browse_result_service = NULL; - char *browse_result_proto = NULL; - mdns_browse_sync_t *out_sync_browse = NULL; - -#ifdef MDNS_ENABLE_DEBUG - _mdns_dbg_printf("\nRX[%lu][%lu]: ", (unsigned long)packet->tcpip_if, (unsigned long)packet->ip_protocol); -#ifdef CONFIG_LWIP_IPV4 - if (packet->src.type == ESP_IPADDR_TYPE_V4) { - _mdns_dbg_printf("From: " IPSTR ":%u, To: " IPSTR ", ", IP2STR(&packet->src.u_addr.ip4), packet->src_port, IP2STR(&packet->dest.u_addr.ip4)); - } -#endif -#ifdef CONFIG_LWIP_IPV6 - if (packet->src.type == ESP_IPADDR_TYPE_V6) { - _mdns_dbg_printf("From: " IPV6STR ":%u, To: " IPV6STR ", ", IPV62STR(packet->src.u_addr.ip6), packet->src_port, IPV62STR(packet->dest.u_addr.ip6)); - } -#endif - mdns_debug_packet(data, len); -#endif - -#ifndef CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES - // Check if the packet wasn't sent by us -#ifdef CONFIG_LWIP_IPV4 - if (packet->ip_protocol == MDNS_IP_PROTOCOL_V4) { - esp_netif_ip_info_t if_ip_info; - if (esp_netif_get_ip_info(_mdns_get_esp_netif(packet->tcpip_if), &if_ip_info) == ESP_OK && - memcmp(&if_ip_info.ip.addr, &packet->src.u_addr.ip4.addr, sizeof(esp_ip4_addr_t)) == 0) { - return; - } - } -#endif /* CONFIG_LWIP_IPV4 */ -#ifdef CONFIG_LWIP_IPV6 - if (packet->ip_protocol == MDNS_IP_PROTOCOL_V6) { - struct esp_ip6_addr if_ip6; - if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(packet->tcpip_if), &if_ip6) == ESP_OK && - memcmp(&if_ip6, &packet->src.u_addr.ip6, sizeof(esp_ip6_addr_t)) == 0) { - return; - } - } -#endif /* CONFIG_LWIP_IPV6 */ -#endif // CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES - - // Check for the minimum size of mdns packet - if (len <= MDNS_HEAD_ADDITIONAL_OFFSET) { - return; - } - - mdns_parsed_packet_t *parsed_packet = (mdns_parsed_packet_t *)mdns_mem_malloc(sizeof(mdns_parsed_packet_t)); - if (!parsed_packet) { - HOOK_MALLOC_FAILED; - return; - } - memset(parsed_packet, 0, sizeof(mdns_parsed_packet_t)); - - mdns_name_t *name = &n; - memset(name, 0, sizeof(mdns_name_t)); - - header.id = _mdns_read_u16(data, MDNS_HEAD_ID_OFFSET); - header.flags = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); - header.questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); - header.answers = _mdns_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); - header.servers = _mdns_read_u16(data, MDNS_HEAD_SERVERS_OFFSET); - header.additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); - - if (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE && packet->src_port != MDNS_SERVICE_PORT) { - mdns_mem_free(parsed_packet); - return; - } - - //if we have not set the hostname, we can not answer questions - if (header.questions && !header.answers && _str_null_or_empty(_mdns_server->hostname)) { - mdns_mem_free(parsed_packet); - return; - } - - parsed_packet->tcpip_if = packet->tcpip_if; - parsed_packet->ip_protocol = packet->ip_protocol; - parsed_packet->multicast = packet->multicast; - parsed_packet->authoritative = (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE); - parsed_packet->distributed = header.flags == MDNS_FLAGS_DISTRIBUTED; - parsed_packet->id = header.id; - esp_netif_ip_addr_copy(&parsed_packet->src, &packet->src); - parsed_packet->src_port = packet->src_port; - parsed_packet->records = NULL; - - if (header.questions) { - uint8_t qs = header.questions; - - while (qs--) { - content = _mdns_parse_fqdn(data, content, name, len); - if (!content) { - header.answers = 0; - header.additional = 0; - header.servers = 0; - goto clear_rx_packet;//error - } - - if (content + MDNS_CLASS_OFFSET + 1 >= data + len) { - goto clear_rx_packet; // malformed packet, won't read behind it - } - uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); - uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); - bool unicast = !!(mdns_class & 0x8000); - mdns_class &= 0x7FFF; - content = content + 4; - - if (mdns_class != 0x0001 || name->invalid) {//bad class or invalid name for this question entry - continue; - } - - if (_mdns_name_is_discovery(name, type)) { - //service discovery - parsed_packet->discovery = true; - mdns_srv_item_t *a = _mdns_server->services; - while (a) { - mdns_parsed_question_t *question = (mdns_parsed_question_t *)mdns_mem_calloc(1, sizeof(mdns_parsed_question_t)); - if (!question) { - HOOK_MALLOC_FAILED; - goto clear_rx_packet; - } - question->next = parsed_packet->questions; - parsed_packet->questions = question; - - question->unicast = unicast; - question->type = MDNS_TYPE_SDPTR; - question->host = NULL; - question->service = mdns_mem_strdup(a->service->service); - question->proto = mdns_mem_strdup(a->service->proto); - question->domain = mdns_mem_strdup(MDNS_DEFAULT_DOMAIN); - if (!question->service || !question->proto || !question->domain) { - goto clear_rx_packet; - } - a = a->next; - } - continue; - } - if (!_mdns_name_is_ours(name)) { - continue; - } - - if (type == MDNS_TYPE_ANY && !_str_null_or_empty(name->host)) { - parsed_packet->probe = true; - } - - mdns_parsed_question_t *question = (mdns_parsed_question_t *)mdns_mem_calloc(1, sizeof(mdns_parsed_question_t)); - if (!question) { - HOOK_MALLOC_FAILED; - goto clear_rx_packet; - } - question->next = parsed_packet->questions; - parsed_packet->questions = question; - - question->unicast = unicast; - question->type = type; - question->sub = name->sub; - if (_mdns_strdup_check(&(question->host), name->host) - || _mdns_strdup_check(&(question->service), name->service) - || _mdns_strdup_check(&(question->proto), name->proto) - || _mdns_strdup_check(&(question->domain), name->domain)) { - goto clear_rx_packet; - } - } - } - - if (header.questions && !parsed_packet->questions && !parsed_packet->discovery && !header.answers) { - goto clear_rx_packet; - } else if (header.answers || header.servers || header.additional) { - uint16_t recordIndex = 0; - - while (content < (data + len)) { - - content = _mdns_parse_fqdn(data, content, name, len); - if (!content) { - goto clear_rx_packet;//error - } - - if (content + MDNS_LEN_OFFSET + 1 >= data + len) { - goto clear_rx_packet; // malformed packet, won't read behind it - } - uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); - uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); - uint32_t ttl = _mdns_read_u32(content, MDNS_TTL_OFFSET); - uint16_t data_len = _mdns_read_u16(content, MDNS_LEN_OFFSET); - const uint8_t *data_ptr = content + MDNS_DATA_OFFSET; - mdns_class &= 0x7FFF; - - content = data_ptr + data_len; - if (content > (data + len) || data_len == 0) { - goto clear_rx_packet; - } - - bool discovery = false; - bool ours = false; - mdns_srv_item_t *service = NULL; - mdns_parsed_record_type_t record_type = MDNS_ANSWER; - - if (recordIndex >= (header.answers + header.servers)) { - record_type = MDNS_EXTRA; - } else if (recordIndex >= (header.answers)) { - record_type = MDNS_NS; - } - recordIndex++; - - if (type == MDNS_TYPE_NSEC || type == MDNS_TYPE_OPT) { - //skip NSEC and OPT - continue; - } - - if (parsed_packet->discovery && _mdns_name_is_discovery(name, type)) { - discovery = true; - } else if (!name->sub && _mdns_name_is_ours(name)) { - ours = true; - if (name->service[0] && name->proto[0]) { - service = _mdns_get_service_item(name->service, name->proto, NULL); - } - } else { - if ((header.flags & MDNS_FLAGS_QUERY_REPSONSE) == 0 || record_type == MDNS_NS) { - //skip this record - continue; - } - search_result = _mdns_search_find_from(_mdns_server->search_once, name, type, packet->tcpip_if, packet->ip_protocol); - browse_result = _mdns_browse_find_from(_mdns_server->browse, name, type, packet->tcpip_if, packet->ip_protocol); - if (browse_result) { - if (!out_sync_browse) { - // will be freed in function `_mdns_browse_sync` - out_sync_browse = (mdns_browse_sync_t *)mdns_mem_malloc(sizeof(mdns_browse_sync_t)); - if (!out_sync_browse) { - HOOK_MALLOC_FAILED; - goto clear_rx_packet; - } - out_sync_browse->browse = browse_result; - out_sync_browse->sync_result = NULL; - } - if (!browse_result_service) { - browse_result_service = (char *)mdns_mem_malloc(MDNS_NAME_BUF_LEN); - if (!browse_result_service) { - HOOK_MALLOC_FAILED; - goto clear_rx_packet; - } - } - memcpy(browse_result_service, browse_result->service, MDNS_NAME_BUF_LEN); - if (!browse_result_proto) { - browse_result_proto = (char *)mdns_mem_malloc(MDNS_NAME_BUF_LEN); - if (!browse_result_proto) { - HOOK_MALLOC_FAILED; - goto clear_rx_packet; - } - } - memcpy(browse_result_proto, browse_result->proto, MDNS_NAME_BUF_LEN); - if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { - if (!browse_result_instance) { - browse_result_instance = (char *)mdns_mem_malloc(MDNS_NAME_BUF_LEN); - if (!browse_result_instance) { - HOOK_MALLOC_FAILED; - goto clear_rx_packet; - } - } - memcpy(browse_result_instance, name->host, MDNS_NAME_BUF_LEN); - } - } - } - - if (type == MDNS_TYPE_PTR) { - if (!_mdns_parse_fqdn(data, data_ptr, name, len)) { - continue;//error - } - if (search_result) { - _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, - packet->tcpip_if, packet->ip_protocol, ttl); - } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { - if (name->host[0]) { - service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL); - } else { - service = _mdns_get_service_item(name->service, name->proto, NULL); - } - if (discovery && service) { - _mdns_remove_parsed_question(parsed_packet, MDNS_TYPE_SDPTR, service); - } else if (service && parsed_packet->questions && !parsed_packet->probe) { - _mdns_remove_parsed_question(parsed_packet, type, service); - } else if (service) { - //check if TTL is more than half of the full TTL value (4500) - if (ttl > (MDNS_ANSWER_PTR_TTL / 2)) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); - } - } - if (service) { - mdns_parsed_record_t *record = mdns_mem_malloc(sizeof(mdns_parsed_record_t)); - if (!record) { - HOOK_MALLOC_FAILED; - goto clear_rx_packet; - } - record->next = parsed_packet->records; - parsed_packet->records = record; - record->type = MDNS_TYPE_PTR; - record->record_type = MDNS_ANSWER; - record->ttl = ttl; - record->host = NULL; - record->service = NULL; - record->proto = NULL; - if (name->host[0]) { - record->host = mdns_mem_malloc(MDNS_NAME_BUF_LEN); - if (!record->host) { - HOOK_MALLOC_FAILED; - goto clear_rx_packet; - } - memcpy(record->host, name->host, MDNS_NAME_BUF_LEN); - } - if (name->service[0]) { - record->service = mdns_mem_malloc(MDNS_NAME_BUF_LEN); - if (!record->service) { - HOOK_MALLOC_FAILED; - goto clear_rx_packet; - } - memcpy(record->service, name->service, MDNS_NAME_BUF_LEN); - } - if (name->proto[0]) { - record->proto = mdns_mem_malloc(MDNS_NAME_BUF_LEN); - if (!record->proto) { - HOOK_MALLOC_FAILED; - goto clear_rx_packet; - } - memcpy(record->proto, name->proto, MDNS_NAME_BUF_LEN); - } - } - } - } else if (type == MDNS_TYPE_SRV) { - mdns_result_t *result = NULL; - if (search_result && search_result->type == MDNS_TYPE_PTR) { - result = search_result->result; - while (result) { - if (_mdns_get_esp_netif(packet->tcpip_if) == result->esp_netif - && packet->ip_protocol == result->ip_protocol - && result->instance_name && !strcmp(name->host, result->instance_name)) { - break; - } - result = result->next; - } - if (!result) { - result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, - packet->tcpip_if, packet->ip_protocol, ttl); - if (!result) { - continue;//error - } - } - } - bool is_selfhosted = _mdns_name_is_selfhosted(name); - if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { - continue;//error - } - if (data_ptr + MDNS_SRV_PORT_OFFSET + 1 >= data + len) { - goto clear_rx_packet; // malformed packet, won't read behind it - } - uint16_t priority = _mdns_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); - uint16_t weight = _mdns_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); - uint16_t port = _mdns_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); - - if (browse_result) { - _mdns_browse_result_add_srv(browse_result, name->host, browse_result_instance, browse_result_service, - browse_result_proto, port, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); - } - if (search_result) { - if (search_result->type == MDNS_TYPE_PTR) { - if (!result->hostname) { // assign host/port for this entry only if not previously set - result->port = port; - result->hostname = mdns_mem_strdup(name->host); - } - } else { - _mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol, ttl); - } - } else if (ours) { - if (parsed_packet->questions && !parsed_packet->probe) { - _mdns_remove_parsed_question(parsed_packet, type, service); - continue; - } else if (parsed_packet->distributed) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); - continue; - } - if (!is_selfhosted) { - continue; - } - //detect collision (-1=won, 0=none, 1=lost) - int col = 0; - if (mdns_class > 1) { - col = 1; - } else if (!mdns_class) { - col = -1; - } else if (service) { // only detect srv collision if service existed - col = _mdns_check_srv_collision(service->service, priority, weight, port, name->host, name->domain); - } - if (service && col && (parsed_packet->probe || parsed_packet->authoritative)) { - if (col > 0 || !port) { - do_not_reply = true; - if (_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { - _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; - if (!_str_null_or_empty(service->service->instance)) { - char *new_instance = _mdns_mangle_name((char *)service->service->instance); - if (new_instance) { - mdns_mem_free((char *)service->service->instance); - service->service->instance = new_instance; - } - _mdns_probe_all_pcbs(&service, 1, false, false); - } else if (!_str_null_or_empty(_mdns_server->instance)) { - char *new_instance = _mdns_mangle_name((char *)_mdns_server->instance); - if (new_instance) { - mdns_mem_free((char *)_mdns_server->instance); - _mdns_server->instance = new_instance; - } - _mdns_restart_all_pcbs_no_instance(); - } else { - char *new_host = _mdns_mangle_name((char *)_mdns_server->hostname); - if (new_host) { - _mdns_remap_self_service_hostname(_mdns_server->hostname, new_host); - mdns_mem_free((char *)_mdns_server->hostname); - _mdns_server->hostname = new_host; - _mdns_self_host.hostname = new_host; - } - _mdns_restart_all_pcbs(); - } - } else if (service) { - _mdns_pcb_send_bye(packet->tcpip_if, packet->ip_protocol, &service, 1, false); - _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, false); - } - } - } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); - } - } - } else if (type == MDNS_TYPE_TXT) { - mdns_txt_item_t *txt = NULL; - uint8_t *txt_value_len = NULL; - size_t txt_count = 0; - - mdns_result_t *result = NULL; - if (browse_result) { - _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); - _mdns_browse_result_add_txt(browse_result, browse_result_instance, browse_result_service, browse_result_proto, - txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); - } - if (search_result) { - if (search_result->type == MDNS_TYPE_PTR) { - result = search_result->result; - while (result) { - if (_mdns_get_esp_netif(packet->tcpip_if) == result->esp_netif - && packet->ip_protocol == result->ip_protocol - && result->instance_name && !strcmp(name->host, result->instance_name)) { - break; - } - result = result->next; - } - if (!result) { - result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, - packet->tcpip_if, packet->ip_protocol, ttl); - if (!result) { - continue;//error - } - } - if (!result->txt) { - _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); - if (txt_count) { - result->txt = txt; - result->txt_count = txt_count; - result->txt_value_len = txt_value_len; - } - } - } else { - _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); - if (txt_count) { - _mdns_search_result_add_txt(search_result, txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, ttl); - } - } - } else if (ours) { - if (parsed_packet->questions && !parsed_packet->probe && service) { - _mdns_remove_parsed_question(parsed_packet, type, service); - continue; - } - if (!_mdns_name_is_selfhosted(name)) { - continue; - } - //detect collision (-1=won, 0=none, 1=lost) - int col = 0; - if (mdns_class > 1) { - col = 1; - } else if (!mdns_class) { - col = -1; - } else if (service) { // only detect txt collision if service existed - col = _mdns_check_txt_collision(service->service, data_ptr, data_len); - } - if (col && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running && service) { - do_not_reply = true; - _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); - } else if (ttl > (MDNS_ANSWER_TXT_TTL / 2) && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); - } - } - - } -#ifdef CONFIG_LWIP_IPV6 - else if (type == MDNS_TYPE_AAAA) {//ipv6 - esp_ip_addr_t ip6; - ip6.type = ESP_IPADDR_TYPE_V6; - memcpy(ip6.u_addr.ip6.addr, data_ptr, MDNS_ANSWER_AAAA_SIZE); - if (browse_result) { - _mdns_browse_result_add_ip(browse_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); - } - if (search_result) { - //check for more applicable searches (PTR & A/AAAA at the same time) - while (search_result) { - _mdns_search_result_add_ip(search_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, ttl); - search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); - } - } else if (ours) { - if (parsed_packet->questions && !parsed_packet->probe) { - _mdns_remove_parsed_question(parsed_packet, type, NULL); - continue; - } - if (!_mdns_name_is_selfhosted(name)) { - continue; - } - //detect collision (-1=won, 0=none, 1=lost) - int col = 0; - if (mdns_class > 1) { - col = 1; - } else if (!mdns_class) { - col = -1; - } else { - col = _mdns_check_aaaa_collision(&(ip6.u_addr.ip6), packet->tcpip_if); - } - if (col == 2) { - goto clear_rx_packet; - } else if (col == 1) { - do_not_reply = true; - if (_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { - if (col && (parsed_packet->probe || parsed_packet->authoritative)) { - _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; - char *new_host = _mdns_mangle_name((char *)_mdns_server->hostname); - if (new_host) { - _mdns_remap_self_service_hostname(_mdns_server->hostname, new_host); - mdns_mem_free((char *)_mdns_server->hostname); - _mdns_server->hostname = new_host; - _mdns_self_host.hostname = new_host; - } - _mdns_restart_all_pcbs(); - } - } else { - _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); - } - } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); - } - } - - } -#endif /* CONFIG_LWIP_IPV6 */ -#ifdef CONFIG_LWIP_IPV4 - else if (type == MDNS_TYPE_A) { - esp_ip_addr_t ip; - ip.type = ESP_IPADDR_TYPE_V4; - memcpy(&(ip.u_addr.ip4.addr), data_ptr, 4); - if (browse_result) { - _mdns_browse_result_add_ip(browse_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); - } - if (search_result) { - //check for more applicable searches (PTR & A/AAAA at the same time) - while (search_result) { - _mdns_search_result_add_ip(search_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, ttl); - search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); - } - } else if (ours) { - if (parsed_packet->questions && !parsed_packet->probe) { - _mdns_remove_parsed_question(parsed_packet, type, NULL); - continue; - } - if (!_mdns_name_is_selfhosted(name)) { - continue; - } - //detect collision (-1=won, 0=none, 1=lost) - int col = 0; - if (mdns_class > 1) { - col = 1; - } else if (!mdns_class) { - col = -1; - } else { - col = _mdns_check_a_collision(&(ip.u_addr.ip4), packet->tcpip_if); - } - if (col == 2) { - goto clear_rx_packet; - } else if (col == 1) { - do_not_reply = true; - if (_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { - if (col && (parsed_packet->probe || parsed_packet->authoritative)) { - _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; - char *new_host = _mdns_mangle_name((char *)_mdns_server->hostname); - if (new_host) { - _mdns_remap_self_service_hostname(_mdns_server->hostname, new_host); - mdns_mem_free((char *)_mdns_server->hostname); - _mdns_server->hostname = new_host; - _mdns_self_host.hostname = new_host; - } - _mdns_restart_all_pcbs(); - } - } else { - _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); - } - } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); - } - } - } -#endif /* CONFIG_LWIP_IPV4 */ - } - //end while - if (parsed_packet->authoritative) { - _mdns_search_finish_done(); - } + mdns_host_item_t *host = (mdns_host_item_t *)mdns_mem_malloc(sizeof(mdns_host_item_t)); + + if (host == NULL) { + return false; } + host->address_list = address_list; + host->hostname = hostname; + host->next = _mdns_host_list; + _mdns_host_list = host; + return true; +} + + - if (!do_not_reply && _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].state > PCB_PROBE_3 && (parsed_packet->questions || parsed_packet->discovery)) { - _mdns_create_answer_from_parsed_packet(parsed_packet); +static bool _mdns_delegate_hostname_set_address(const char *hostname, mdns_ip_addr_t *address_list) +{ + if (!_str_null_or_empty(_mdns_server->hostname) && + strcasecmp(hostname, _mdns_server->hostname) == 0) { + return false; } - if (out_sync_browse) { -#ifdef MDNS_ENABLE_DEBUG - _mdns_dbg_printf("Browse %s%s total result:", out_sync_browse->browse->service, out_sync_browse->browse->proto); - debug_printf_browse_result_all(out_sync_browse->browse->result); -#endif // MDNS_ENABLE_DEBUG - if (out_sync_browse->sync_result) { -#ifdef MDNS_ENABLE_DEBUG - _mdns_dbg_printf("Changed result:"); - debug_printf_browse_result_all(out_sync_browse->sync_result->result); -#endif // MDNS_ENABLE_DEBUG - _mdns_sync_browse_action(ACTION_BROWSE_SYNC, out_sync_browse); - } else { - mdns_mem_free(out_sync_browse); + mdns_host_item_t *host = _mdns_host_list; + while (host != NULL) { + if (strcasecmp(hostname, host->hostname) == 0) { + // free previous address list + free_address_list(host->address_list); + // set current address list to the host + host->address_list = address_list; + return true; } - out_sync_browse = NULL; + host = host->next; } + return false; +} -clear_rx_packet: - while (parsed_packet->questions) { - mdns_parsed_question_t *question = parsed_packet->questions; - parsed_packet->questions = parsed_packet->questions->next; - if (question->host) { - mdns_mem_free(question->host); - } - if (question->service) { - mdns_mem_free(question->service); - } - if (question->proto) { - mdns_mem_free(question->proto); - } - if (question->domain) { - mdns_mem_free(question->domain); - } - mdns_mem_free(question); + + +static void free_delegated_hostnames(void) +{ + mdns_host_item_t *host = _mdns_host_list; + while (host != NULL) { + free_address_list(host->address_list); + mdns_mem_free((char *)host->hostname); + mdns_host_item_t *item = host; + host = host->next; + mdns_mem_free(item); } - while (parsed_packet->records) { - mdns_parsed_record_t *record = parsed_packet->records; - parsed_packet->records = parsed_packet->records->next; - if (record->host) { - mdns_mem_free(record->host); - } - if (record->service) { - mdns_mem_free(record->service); + _mdns_host_list = NULL; +} + +static bool _mdns_delegate_hostname_remove(const char *hostname) +{ + mdns_srv_item_t *srv = _mdns_server->services; + mdns_srv_item_t *prev_srv = NULL; + while (srv) { + if (strcasecmp(srv->service->hostname, hostname) == 0) { + mdns_srv_item_t *to_free = srv; + _mdns_send_bye(&srv, 1, false); + _mdns_remove_scheduled_service_packets(srv->service); + if (prev_srv == NULL) { + _mdns_server->services = srv->next; + srv = srv->next; + } else { + prev_srv->next = srv->next; + srv = srv->next; + } + _mdns_free_service(to_free->service); + mdns_mem_free(to_free); + } else { + prev_srv = srv; + srv = srv->next; } - if (record->proto) { - mdns_mem_free(record->proto); + } + mdns_host_item_t *host = _mdns_host_list; + mdns_host_item_t *prev_host = NULL; + while (host != NULL) { + if (strcasecmp(hostname, host->hostname) == 0) { + if (prev_host == NULL) { + _mdns_host_list = host->next; + } else { + prev_host->next = host->next; + } + free_address_list(host->address_list); + mdns_mem_free((char *)host->hostname); + mdns_mem_free(host); + break; + } else { + prev_host = host; + host = host->next; } - record->next = NULL; - mdns_mem_free(record); } - mdns_mem_free(parsed_packet); - mdns_mem_free(browse_result_instance); - mdns_mem_free(browse_result_service); - mdns_mem_free(browse_result_proto); - mdns_mem_free(out_sync_browse); + return true; } + + + + + + + + + + + + + + + + + + +void mdns_parse_packet(mdns_rx_packet_t *packet); + /** * @brief Enable mDNS interface */ @@ -4594,403 +2983,87 @@ static mdns_search_once_t *_mdns_search_init(const char *name, const char *servi HOOK_MALLOC_FAILED; return NULL; } - memset(search, 0, sizeof(mdns_search_once_t)); - - search->done_semaphore = xSemaphoreCreateBinary(); - if (!search->done_semaphore) { - mdns_mem_free(search); - return NULL; - } - - if (!_str_null_or_empty(name)) { - search->instance = mdns_mem_strndup(name, MDNS_NAME_BUF_LEN - 1); - if (!search->instance) { - _mdns_search_free(search); - return NULL; - } - } - - if (!_str_null_or_empty(service)) { - search->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); - if (!search->service) { - _mdns_search_free(search); - return NULL; - } - } - - if (!_str_null_or_empty(proto)) { - search->proto = mdns_mem_strndup(proto, MDNS_NAME_BUF_LEN - 1); - if (!search->proto) { - _mdns_search_free(search); - return NULL; - } - } - - search->type = type; - search->unicast = unicast; - search->timeout = timeout; - search->num_results = 0; - search->max_results = max_results; - search->result = NULL; - search->state = SEARCH_INIT; - search->sent_at = 0; - search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS; - search->notifier = notifier; - search->next = NULL; - - return search; -} - -/** - * @brief Mark search as finished and remove it from search chain - */ -static void _mdns_search_finish(mdns_search_once_t *search) -{ - search->state = SEARCH_OFF; - queueDetach(mdns_search_once_t, _mdns_server->search_once, search); - if (search->notifier) { - search->notifier(search); - } - xSemaphoreGive(search->done_semaphore); -} - -/** - * @brief Add new search to the search chain - */ -static void _mdns_search_add(mdns_search_once_t *search) -{ - search->next = _mdns_server->search_once; - _mdns_server->search_once = search; -} - -/** - * @brief Called from parser to finish any searches that have reached maximum results - */ -static void _mdns_search_finish_done(void) -{ - mdns_search_once_t *search = _mdns_server->search_once; - mdns_search_once_t *s = NULL; - while (search) { - s = search; - search = search->next; - if (s->max_results && s->num_results >= s->max_results) { - _mdns_search_finish(s); - } - } -} - -/** - * @brief Create linked IP (copy) from parsed one - */ -static mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip) -{ - mdns_ip_addr_t *a = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); - if (!a) { - HOOK_MALLOC_FAILED; - return NULL; - } - memset(a, 0, sizeof(mdns_ip_addr_t)); - a->addr.type = ip->type; - if (ip->type == ESP_IPADDR_TYPE_V6) { - memcpy(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16); - } else { - a->addr.u_addr.ip4.addr = ip->u_addr.ip4.addr; - } - return a; -} - -static inline void _mdns_result_update_ttl(mdns_result_t *r, uint32_t ttl) -{ - r->ttl = r->ttl < ttl ? r->ttl : ttl; -} - -/** - * @brief Chain new IP to search result - */ -static void _mdns_result_add_ip(mdns_result_t *r, esp_ip_addr_t *ip) -{ - mdns_ip_addr_t *a = r->addr; - while (a) { - if (a->addr.type == ip->type) { -#ifdef CONFIG_LWIP_IPV4 - if (a->addr.type == ESP_IPADDR_TYPE_V4 && a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { - return; - } -#endif -#ifdef CONFIG_LWIP_IPV6 - if (a->addr.type == ESP_IPADDR_TYPE_V6 && !memcmp(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { - return; - } -#endif - } - a = a->next; - } - a = _mdns_result_addr_create_ip(ip); - if (!a) { - return; - } - a->next = r->addr; - r->addr = a; -} - -/** - * @brief Called from parser to add A/AAAA data to search result - */ -static void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) -{ - mdns_result_t *r = NULL; - mdns_ip_addr_t *a = NULL; - - if ((search->type == MDNS_TYPE_A && ip->type == ESP_IPADDR_TYPE_V4) - || (search->type == MDNS_TYPE_AAAA && ip->type == ESP_IPADDR_TYPE_V6) - || search->type == MDNS_TYPE_ANY) { - r = search->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { - _mdns_result_add_ip(r, ip); - _mdns_result_update_ttl(r, ttl); - return; - } - r = r->next; - } - if (!search->max_results || search->num_results < search->max_results) { - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; - return; - } - - memset(r, 0, sizeof(mdns_result_t)); - - a = _mdns_result_addr_create_ip(ip); - if (!a) { - mdns_mem_free(r); - return; - } - a->next = r->addr; - r->hostname = mdns_mem_strdup(hostname); - r->addr = a; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->next = search->result; - r->ttl = ttl; - search->result = r; - search->num_results++; - } - } else if (search->type == MDNS_TYPE_PTR || search->type == MDNS_TYPE_SRV) { - r = search->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { - _mdns_result_add_ip(r, ip); - _mdns_result_update_ttl(r, ttl); - break; - } - r = r->next; - } + memset(search, 0, sizeof(mdns_search_once_t)); + + search->done_semaphore = xSemaphoreCreateBinary(); + if (!search->done_semaphore) { + mdns_mem_free(search); + return NULL; } -} -/** - * @brief Called from parser to add PTR data to search result - */ -static mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, - const char *service_type, const char *proto, mdns_if_t tcpip_if, - mdns_ip_protocol_t ip_protocol, uint32_t ttl) -{ - mdns_result_t *r = search->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { - _mdns_result_update_ttl(r, ttl); - return r; + if (!_str_null_or_empty(name)) { + search->instance = mdns_mem_strndup(name, MDNS_NAME_BUF_LEN - 1); + if (!search->instance) { + _mdns_search_free(search); + return NULL; } - r = r->next; } - if (!search->max_results || search->num_results < search->max_results) { - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; + + if (!_str_null_or_empty(service)) { + search->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); + if (!search->service) { + _mdns_search_free(search); return NULL; } + } - memset(r, 0, sizeof(mdns_result_t)); - r->instance_name = mdns_mem_strdup(instance); - r->service_type = mdns_mem_strdup(service_type); - r->proto = mdns_mem_strdup(proto); - if (!r->instance_name) { - mdns_mem_free(r); + if (!_str_null_or_empty(proto)) { + search->proto = mdns_mem_strndup(proto, MDNS_NAME_BUF_LEN - 1); + if (!search->proto) { + _mdns_search_free(search); return NULL; } - - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->ttl = ttl; - r->next = search->result; - search->result = r; - search->num_results++; - return r; } - return NULL; + + search->type = type; + search->unicast = unicast; + search->timeout = timeout; + search->num_results = 0; + search->max_results = max_results; + search->result = NULL; + search->state = SEARCH_INIT; + search->sent_at = 0; + search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS; + search->notifier = notifier; + search->next = NULL; + + return search; } /** - * @brief Called from parser to add SRV data to search result + * @brief Mark search as finished and remove it from search chain */ -static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) +void _mdns_search_finish(mdns_search_once_t *search) { - mdns_result_t *r = search->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { - _mdns_result_update_ttl(r, ttl); - return; - } - r = r->next; - } - if (!search->max_results || search->num_results < search->max_results) { - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; - return; - } - - memset(r, 0, sizeof(mdns_result_t)); - r->hostname = mdns_mem_strdup(hostname); - if (!r->hostname) { - mdns_mem_free(r); - return; - } - if (search->instance) { - r->instance_name = mdns_mem_strdup(search->instance); - } - r->service_type = mdns_mem_strdup(search->service); - r->proto = mdns_mem_strdup(search->proto); - r->port = port; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->ttl = ttl; - r->next = search->result; - search->result = r; - search->num_results++; + search->state = SEARCH_OFF; + queueDetach(mdns_search_once_t, _mdns_server->search_once, search); + if (search->notifier) { + search->notifier(search); } + xSemaphoreGive(search->done_semaphore); } /** - * @brief Called from parser to add TXT data to search result + * @brief Add new search to the search chain */ -static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, - size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl) -{ - mdns_result_t *r = search->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { - if (r->txt) { - goto free_txt; - } - r->txt = txt; - r->txt_value_len = txt_value_len; - r->txt_count = txt_count; - _mdns_result_update_ttl(r, ttl); - return; - } - r = r->next; - } - if (!search->max_results || search->num_results < search->max_results) { - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; - goto free_txt; - } +static void _mdns_search_add(mdns_search_once_t *search) +{ + search->next = _mdns_server->search_once; + _mdns_server->search_once = search; +} + + + + + - memset(r, 0, sizeof(mdns_result_t)); - r->txt = txt; - r->txt_value_len = txt_value_len; - r->txt_count = txt_count; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->ttl = ttl; - r->next = search->result; - search->result = r; - search->num_results++; - } - return; -free_txt: - for (size_t i = 0; i < txt_count; i++) { - mdns_mem_free((char *)(txt[i].key)); - mdns_mem_free((char *)(txt[i].value)); - } - mdns_mem_free(txt); - mdns_mem_free(txt_value_len); -} -/** - * @brief Called from packet parser to find matching running search - */ -static mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_result_t *r = NULL; - while (s) { - if (s->state == SEARCH_OFF) { - s = s->next; - continue; - } - if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { - if ((s->type == MDNS_TYPE_ANY && s->service != NULL) - || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV)) { - s = s->next; - continue; - } - if (s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV) { - if (!strcasecmp(name->host, s->instance)) { - return s; - } - s = s->next; - continue; - } - r = s->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { - return s; - } - r = r->next; - } - s = s->next; - continue; - } - if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { - if ((s->type == MDNS_TYPE_ANY && s->service == NULL) - || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR)) { - s = s->next; - continue; - } - if (strcasecmp(name->service, s->service) - || strcasecmp(name->proto, s->proto)) { - s = s->next; - continue; - } - if (s->type != MDNS_TYPE_PTR) { - if (s->instance && strcasecmp(name->host, s->instance) == 0) { - return s; - } - s = s->next; - continue; - } - return s; - } - if (type == MDNS_TYPE_PTR && type == s->type && !strcasecmp(name->service, s->service) && !strcasecmp(name->proto, s->proto)) { - return s; - } - s = s->next; - } - return NULL; -} /** * @brief Create search packet for particular interface @@ -5151,7 +3224,7 @@ static void _mdns_tx_handle_packet(mdns_tx_packet_t *p) } } -static void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) +void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) { mdns_srv_item_t *service = _mdns_server->services; @@ -7029,12 +5102,12 @@ void mdns_debug_packet(const uint8_t *data, size_t len) _mdns_dbg_printf("Packet[%" PRIu32 "]: ", t); - header.id = _mdns_read_u16(data, MDNS_HEAD_ID_OFFSET); - header.flags = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); - header.questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); - header.answers = _mdns_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); - header.servers = _mdns_read_u16(data, MDNS_HEAD_SERVERS_OFFSET); - header.additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); + header.id = mdns_utils_read_u16(data, MDNS_HEAD_ID_OFFSET); + header.flags = mdns_utils_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); + header.questions = mdns_utils_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); + header.answers = mdns_utils_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); + header.servers = mdns_utils_read_u16(data, MDNS_HEAD_SERVERS_OFFSET); + header.additional = mdns_utils_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); _mdns_dbg_printf("%s", (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE) ? "AUTHORITATIVE\n" : @@ -7058,8 +5131,8 @@ void mdns_debug_packet(const uint8_t *data, size_t len) break; } - uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); - uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + uint16_t type = mdns_utils_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t mdns_class = mdns_utils_read_u16(content, MDNS_CLASS_OFFSET); bool unicast = !!(mdns_class & 0x8000); mdns_class &= 0x7FFF; content = content + 4; @@ -7106,10 +5179,10 @@ void mdns_debug_packet(const uint8_t *data, size_t len) break; } - uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); - uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); - uint32_t ttl = _mdns_read_u32(content, MDNS_TTL_OFFSET); - uint16_t data_len = _mdns_read_u16(content, MDNS_LEN_OFFSET); + uint16_t type = mdns_utils_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t mdns_class = mdns_utils_read_u16(content, MDNS_CLASS_OFFSET); + uint32_t ttl = mdns_utils_read_u32(content, MDNS_TTL_OFFSET); + uint16_t data_len = mdns_utils_read_u16(content, MDNS_LEN_OFFSET); const uint8_t *data_ptr = content + MDNS_DATA_OFFSET; bool flush = !!(mdns_class & 0x8000); mdns_class &= 0x7FFF; @@ -7178,9 +5251,9 @@ void mdns_debug_packet(const uint8_t *data, size_t len) _mdns_dbg_printf("ERROR: parse SRV\n"); continue; } - uint16_t priority = _mdns_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); - uint16_t weight = _mdns_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); - uint16_t port = _mdns_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); + uint16_t priority = mdns_utils_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); + uint16_t weight = mdns_utils_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); + uint16_t port = mdns_utils_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); _mdns_dbg_printf("%u %u %u %s.%s.\n", priority, weight, port, name->host, name->domain); } else if (type == MDNS_TYPE_TXT) { uint16_t i = 0, y; @@ -7225,8 +5298,8 @@ void mdns_debug_packet(const uint8_t *data, size_t len) } _mdns_dbg_printf("\n"); } else if (type == MDNS_TYPE_OPT) { - uint16_t opCode = _mdns_read_u16(data_ptr, 0); - uint16_t opLen = _mdns_read_u16(data_ptr, 2); + uint16_t opCode = mdns_utils_read_u16(data_ptr, 0); + uint16_t opLen = mdns_utils_read_u16(data_ptr, 2); _mdns_dbg_printf(" Code: %04x Data[%u]:", opCode, opLen); size_t i; for (i = 4; i < data_len; i++) { @@ -7248,7 +5321,7 @@ void mdns_debug_packet(const uint8_t *data, size_t len) /** * @brief Browse sync result action */ -static esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync) +esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync) { mdns_action_t *action = NULL; @@ -7450,348 +5523,6 @@ static void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface) } } -/** - * @brief Add result to browse, only add when the result is a new one. - */ -static esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r) -{ - mdns_browse_result_sync_t *sync_r = sync_browse->sync_result; - while (sync_r) { - if (sync_r->result == r) { - break; - } - sync_r = sync_r->next; - } - if (!sync_r) { - // Do not find, need to add the result to the list - mdns_browse_result_sync_t *new = (mdns_browse_result_sync_t *)mdns_mem_malloc(sizeof(mdns_browse_result_sync_t)); - - if (!new) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; - } - new->result = r; - new->next = sync_browse->sync_result; - sync_browse->sync_result = new; - } - return ESP_OK; -} - -/** - * @brief Called from parser to add A/AAAA data to search result - */ -static void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) -{ - if (out_sync_browse->browse == NULL) { - return; - } else { - if (out_sync_browse->browse != browse) { - return; - } - } - mdns_result_t *r = NULL; - mdns_ip_addr_t *r_a = NULL; - if (browse) { - r = browse->result; - while (r) { - if (r->ip_protocol == ip_protocol) { - // Find the target result in browse result. - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { - r_a = r->addr; - // Check if the address has already added in result. - while (r_a) { -#ifdef CONFIG_LWIP_IPV4 - if (r_a->addr.type == ip->type && r_a->addr.type == ESP_IPADDR_TYPE_V4 && r_a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { - break; - } -#endif -#ifdef CONFIG_LWIP_IPV6 - if (r_a->addr.type == ip->type && r_a->addr.type == ESP_IPADDR_TYPE_V6 && !memcmp(r_a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { - break; - } -#endif - r_a = r_a->next; - } - if (!r_a) { - // The current IP is a new one, add it to the link list. - mdns_ip_addr_t *a = NULL; - a = _mdns_result_addr_create_ip(ip); - if (!a) { - return; - } - a->next = r->addr; - r->addr = a; - if (r->ttl != ttl) { - if (r->ttl == 0) { - r->ttl = ttl; - } else { - _mdns_result_update_ttl(r, ttl); - } - } - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { - return; - } - break; - } - } - } - r = r->next; - } - } - return; -} - -/** - * @brief Called from packet parser to find matching running search - */ -static mdns_browse_t *_mdns_browse_find_from(mdns_browse_t *b, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - // For browse, we only care about the SRV, TXT, A and AAAA - if (type != MDNS_TYPE_SRV && type != MDNS_TYPE_A && type != MDNS_TYPE_AAAA && type != MDNS_TYPE_TXT) { - return NULL; - } - mdns_result_t *r = NULL; - while (b) { - if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { - if (strcasecmp(name->service, b->service) - || strcasecmp(name->proto, b->proto)) { - b = b->next; - continue; - } - return b; - } else if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { - r = b->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { - return b; - } - r = r->next; - } - b = b->next; - continue; - } - } - return b; -} - -static bool is_txt_item_in_list(mdns_txt_item_t txt, uint8_t txt_value_len, mdns_txt_item_t *txt_list, uint8_t *txt_value_len_list, size_t txt_count) -{ - for (size_t i = 0; i < txt_count; i++) { - if (strcmp(txt.key, txt_list[i].key) == 0) { - if (txt_value_len == txt_value_len_list[i] && memcmp(txt.value, txt_list[i].value, txt_value_len) == 0) { - return true; - } else { - // The key value is unique, so there is no need to continue searching. - return false; - } - } - } - return false; -} - -/** - * @brief Called from parser to add TXT data to search result - */ -static void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, - mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl, mdns_browse_sync_t *out_sync_browse) -{ - if (out_sync_browse->browse == NULL) { - return; - } else { - if (out_sync_browse->browse != browse) { - return; - } - } - mdns_result_t *r = browse->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && - !_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && - !_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && - !_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { - bool should_update = false; - if (r->txt) { - // Check if txt changed - if (txt_count != r->txt_count) { - should_update = true; - } else { - for (size_t txt_index = 0; txt_index < txt_count; txt_index++) { - if (!is_txt_item_in_list(txt[txt_index], txt_value_len[txt_index], r->txt, r->txt_value_len, r->txt_count)) { - should_update = true; - break; - } - } - } - // If the result has a previous txt entry, we delete it and re-add. - for (size_t i = 0; i < r->txt_count; i++) { - mdns_mem_free((char *)(r->txt[i].key)); - mdns_mem_free((char *)(r->txt[i].value)); - } - mdns_mem_free(r->txt); - mdns_mem_free(r->txt_value_len); - } - r->txt = txt; - r->txt_value_len = txt_value_len; - r->txt_count = txt_count; - if (r->ttl != ttl) { - uint32_t previous_ttl = r->ttl; - if (r->ttl == 0) { - r->ttl = ttl; - } else { - _mdns_result_update_ttl(r, ttl); - } - if (previous_ttl != r->ttl) { - should_update = true; - } - } - if (should_update) { - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { - return; - } - } - return; - } - r = r->next; - } - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; - goto free_txt; - } - memset(r, 0, sizeof(mdns_result_t)); - r->instance_name = mdns_mem_strdup(instance); - r->service_type = mdns_mem_strdup(service); - r->proto = mdns_mem_strdup(proto); - if (!r->instance_name || !r->service_type || !r->proto) { - mdns_mem_free(r->instance_name); - mdns_mem_free(r->service_type); - mdns_mem_free(r->proto); - mdns_mem_free(r); - return; - } - r->txt = txt; - r->txt_value_len = txt_value_len; - r->txt_count = txt_count; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->ttl = ttl; - r->next = browse->result; - browse->result = r; - _mdns_add_browse_result(out_sync_browse, r); - return; - -free_txt: - for (size_t i = 0; i < txt_count; i++) { - mdns_mem_free((char *)(txt[i].key)); - mdns_mem_free((char *)(txt[i].value)); - } - mdns_mem_free(txt); - mdns_mem_free(txt_value_len); - return; -} - -static esp_err_t _mdns_copy_address_in_previous_result(mdns_result_t *result_list, mdns_result_t *r) -{ - while (result_list) { - if (!_str_null_or_empty(result_list->hostname) && !_str_null_or_empty(r->hostname) && !strcasecmp(result_list->hostname, r->hostname) && - result_list->ip_protocol == r->ip_protocol && result_list->addr && !r->addr) { - // If there is a same hostname in previous result, we need to copy the address here. - r->addr = copy_address_list(result_list->addr); - if (!r->addr) { - return ESP_ERR_NO_MEM; - } - break; - } else { - result_list = result_list->next; - } - } - return ESP_OK; -} - -/** - * @brief Called from parser to add SRV data to search result - */ -static void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, - uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) -{ - if (out_sync_browse->browse == NULL) { - return; - } else { - if (out_sync_browse->browse != browse) { - return; - } - } - mdns_result_t *r = browse->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && - !_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && - !_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && - !_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { - if (_str_null_or_empty(r->hostname) || strcasecmp(hostname, r->hostname)) { - r->hostname = mdns_mem_strdup(hostname); - r->port = port; - if (!r->hostname) { - HOOK_MALLOC_FAILED; - return; - } - if (!r->addr) { - esp_err_t err = _mdns_copy_address_in_previous_result(browse->result, r); - if (err == ESP_ERR_NO_MEM) { - return; - } - } - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { - return; - } - } - if (r->ttl != ttl) { - uint32_t previous_ttl = r->ttl; - if (r->ttl == 0) { - r->ttl = ttl; - } else { - _mdns_result_update_ttl(r, ttl); - } - if (previous_ttl != r->ttl) { - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { - return; - } - } - } - return; - } - r = r->next; - } - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; - return; - } - - memset(r, 0, sizeof(mdns_result_t)); - r->hostname = mdns_mem_strdup(hostname); - r->instance_name = mdns_mem_strdup(instance); - r->service_type = mdns_mem_strdup(service); - r->proto = mdns_mem_strdup(proto); - if (!r->hostname || !r->instance_name || !r->service_type || !r->proto) { - HOOK_MALLOC_FAILED; - mdns_mem_free(r->hostname); - mdns_mem_free(r->instance_name); - mdns_mem_free(r->service_type); - mdns_mem_free(r->proto); - mdns_mem_free(r); - return; - } - r->port = port; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->ttl = ttl; - r->next = browse->result; - browse->result = r; - _mdns_add_browse_result(out_sync_browse, r); - return; -} - static void _mdns_browse_sync(mdns_browse_sync_t *browse_sync) { mdns_browse_t *browse = browse_sync->browse; @@ -7844,14 +5575,14 @@ void _debug_printf_result(mdns_result_t *r_t) } } -static void debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t) +void debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t) { _mdns_dbg_printf("----------------sync browse %s.%s result---------------\n", b_t->service, b_t->proto); _mdns_dbg_printf("browse pointer: %p\n", b_t); _debug_printf_result(r_t); } -static void debug_printf_browse_result_all(mdns_result_t *r_t) +void debug_printf_browse_result_all(mdns_result_t *r_t) { int count = 0; while (r_t) { diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c new file mode 100644 index 0000000000..4b09462eb7 --- /dev/null +++ b/components/mdns/mdns_browser.c @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "mdns_private.h" +#include "mdns_networking.h" +#include "mdns_types.h" + +// Browse functions +static esp_err_t mdns_browse_service(const char *service, const char *proto); +static void mdns_browse_result_add(mdns_browse_t *browse, mdns_result_t *result); +static void mdns_browse_finish(mdns_browse_t *browse); diff --git a/components/mdns/mdns_packet.c b/components/mdns/mdns_packet.c new file mode 100644 index 0000000000..54b723a093 --- /dev/null +++ b/components/mdns/mdns_packet.c @@ -0,0 +1,1945 @@ + +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "mdns_private.h" +#include "mdns_networking.h" +#include "mdns.h" +#include "mdns_mem_caps.h" +#include "esp_log.h" +#include "mdns_utils.h" + +static const char *TAG = "mdns_packet"; + +#ifdef MDNS_ENABLE_DEBUG +void mdns_debug_packet(const uint8_t *data, size_t len); +void debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t); +void debug_printf_browse_result_all(mdns_result_t *r_t); +#endif + +/** + * @brief Check if parsed name is discovery + */ +static bool _mdns_name_is_discovery(mdns_name_t *name, uint16_t type) +{ + return ( + (name->host[0] && !strcasecmp(name->host, "_services")) + && (name->service[0] && !strcasecmp(name->service, "_dns-sd")) + && (name->proto[0] && !strcasecmp(name->proto, "_udp")) + && (name->domain[0] && !strcasecmp(name->domain, MDNS_UTILS_DEFAULT_DOMAIN)) + && type == MDNS_TYPE_PTR + ); +} + +static mdns_srv_item_t *_mdns_get_service_item_subtype(const char *subtype, const char *service, const char *proto) +{ + mdns_srv_item_t *s = mdns_utils_get_services(); + while (s) { + if (_mdns_service_match(s->service, service, proto, NULL)) { + mdns_subtype_t *subtype_item = s->service->subtype; + while (subtype_item) { + if (!strcasecmp(subtype_item->subtype, subtype)) { + return s; + } + subtype_item = subtype_item->next; + } + } + s = s->next; + } + return NULL; +} + +/** + * @brief Check if the parsed name is ours (matches service or host name) + */ +static bool _mdns_name_is_ours(mdns_name_t *name) +{ + //domain have to be "local" + if (mdns_utils_str_null_or_empty(name->domain) || (strcasecmp(name->domain, MDNS_UTILS_DEFAULT_DOMAIN) +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + && strcasecmp(name->domain, "arpa") +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + )) { + return false; + } + + //if service and proto are empty, host must match out hostname + if (mdns_utils_str_null_or_empty(name->service) && mdns_utils_str_null_or_empty(name->proto)) { + if (!mdns_utils_str_null_or_empty(name->host) + && !mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname()) + && _hostname_is_ours(name->host)) { + return true; + } + return false; + } + + //if service or proto is empty, name is invalid + if (mdns_utils_str_null_or_empty(name->service) || mdns_utils_str_null_or_empty(name->proto)) { + return false; + } + + + //find the service + mdns_srv_item_t *service; + if (name->sub) { + service = _mdns_get_service_item_subtype(name->host, name->service, name->proto); + } else if (mdns_utils_str_null_or_empty(name->host)) { + service = _mdns_get_service_item(name->service, name->proto, NULL); + } else { + service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL); + } + if (!service) { + return false; + } + + //if query is PTR query and we have service, we have success + if (name->sub || mdns_utils_str_null_or_empty(name->host)) { + return true; + } + + //OK we have host in the name. find what is the instance of the service + const char *instance = _mdns_get_service_instance_name(service->service); + if (instance == NULL) { + return false; + } + + //compare the instance against the name + if (strcasecmp(name->host, instance) == 0) { + return true; + } + + return false; +} + +/** + * @brief Duplicate string or return error + */ +static esp_err_t _mdns_strdup_check(char **out, char *in) +{ + if (in && in[0]) { + *out = mdns_mem_strdup(in); + if (!*out) { + return ESP_FAIL; + } + return ESP_OK; + } + *out = NULL; + return ESP_OK; +} + +/* + * @brief Appends/increments a number to name/instance in case of collision + * */ +static char *_mdns_mangle_name(char *in) +{ + char *p = strrchr(in, '-'); + int suffix = 0; + if (p == NULL) { + //No - in ``in`` + suffix = 2; + } else { + char *endp = NULL; + suffix = strtol(p + 1, &endp, 10); + if (*endp != 0) { + //suffix is not numerical + suffix = 2; + p = NULL; //so we append -suffix to the entire string + } + } + char *ret; + if (p == NULL) { + //need to add -2 to string + ret = mdns_mem_malloc(strlen(in) + 3); + if (ret == NULL) { + HOOK_MALLOC_FAILED; + return NULL; + } + sprintf(ret, "%s-2", in); + } else { + size_t in_len = strlen(in); + ret = mdns_mem_malloc(in_len + 2); //one extra byte in case 9-10 or 99-100 etc + if (ret == NULL) { + HOOK_MALLOC_FAILED; + return NULL; + } + memcpy(ret, in, in_len); + int baseLen = p - in; //length of 'bla' in 'bla-123' + //overwrite suffix with new suffix + sprintf(ret + baseLen, "-%d", suffix + 1); + } + return ret; +} + +/** + * @brief Get number of items in TXT parsed data + */ +static int _mdns_txt_items_count_get(const uint8_t *data, size_t len) +{ + if (len == 1) { + return 0; + } + + int num_items = 0; + uint16_t i = 0; + size_t partLen = 0; + + while (i < len) { + partLen = data[i++]; + if (!partLen) { + break; + } + if ((i + partLen) > len) { + return -1;//error + } + i += partLen; + num_items++; + } + return num_items; +} + +/** + * @brief Get the length of TXT item's key name + */ +static int _mdns_txt_item_name_get_len(const uint8_t *data, size_t len) +{ + if (*data == '=') { + return -1; + } + for (size_t i = 0; i < len; i++) { + if (data[i] == '=') { + return i; + } + } + return len; +} + +/** + * @brief Called from parser to finish any searches that have reached maximum results + */ +static void _mdns_search_finish_done(void) +{ + mdns_search_once_t *search = mdns_utils_get_search(); + mdns_search_once_t *s = NULL; + while (search) { + s = search; + search = search->next; + if (s->max_results && s->num_results >= s->max_results) { + _mdns_search_finish(s); + } + } +} + +/** + * @brief Called from parser to add TXT data to search result + */ +static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, + size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl) +{ + mdns_result_t *r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { + if (r->txt) { + goto free_txt; + } + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + _mdns_result_update_ttl(r, ttl); + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + goto free_txt; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = search->result; + search->result = r; + search->num_results++; + } + return; + +free_txt: + for (size_t i = 0; i < txt_count; i++) { + mdns_mem_free((char *)(txt[i].key)); + mdns_mem_free((char *)(txt[i].value)); + } + mdns_mem_free(txt); + mdns_mem_free(txt_value_len); +} + + +/** + * @brief Create TXT result array from parsed TXT data + */ +static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_item_t **out_txt, uint8_t **out_value_len, + size_t *out_count) +{ + *out_txt = NULL; + *out_count = 0; + uint16_t i = 0, y; + size_t partLen = 0; + int num_items = _mdns_txt_items_count_get(data, len); + if (num_items < 0 || num_items > SIZE_MAX / sizeof(mdns_txt_item_t)) { + // Error: num_items is incorrect (or too large to allocate) + return; + } + + if (!num_items) { + return; + } + + mdns_txt_item_t *txt = (mdns_txt_item_t *)mdns_mem_malloc(sizeof(mdns_txt_item_t) * num_items); + if (!txt) { + HOOK_MALLOC_FAILED; + return; + } + uint8_t *txt_value_len = (uint8_t *)mdns_mem_malloc(num_items); + if (!txt_value_len) { + mdns_mem_free(txt); + HOOK_MALLOC_FAILED; + return; + } + memset(txt, 0, sizeof(mdns_txt_item_t) * num_items); + memset(txt_value_len, 0, num_items); + size_t txt_num = 0; + + while (i < len) { + partLen = data[i++]; + if (!partLen) { + break; + } + + if ((i + partLen) > len) { + goto handle_error;//error + } + + int name_len = _mdns_txt_item_name_get_len(data + i, partLen); + if (name_len < 0) {//invalid item (no name) + i += partLen; + continue; + } + char *key = (char *)mdns_mem_malloc(name_len + 1); + if (!key) { + HOOK_MALLOC_FAILED; + goto handle_error;//error + } + + mdns_txt_item_t *t = &txt[txt_num]; + uint8_t *value_len = &txt_value_len[txt_num]; + txt_num++; + + memcpy(key, data + i, name_len); + key[name_len] = 0; + i += name_len + 1; + t->key = key; + + int new_value_len = partLen - name_len - 1; + if (new_value_len > 0) { + char *value = (char *)mdns_mem_malloc(new_value_len + 1); + if (!value) { + HOOK_MALLOC_FAILED; + goto handle_error;//error + } + memcpy(value, data + i, new_value_len); + value[new_value_len] = 0; + *value_len = new_value_len; + i += new_value_len; + t->value = value; + } + } + + *out_txt = txt; + *out_count = txt_num; + *out_value_len = txt_value_len; + return; + +handle_error : + for (y = 0; y < txt_num; y++) { + mdns_txt_item_t *t = &txt[y]; + mdns_mem_free((char *)t->key); + mdns_mem_free((char *)t->value); + } + mdns_mem_free(txt_value_len); + mdns_mem_free(txt); +} + +static bool is_txt_item_in_list(mdns_txt_item_t txt, uint8_t txt_value_len, mdns_txt_item_t *txt_list, uint8_t *txt_value_len_list, size_t txt_count) +{ + for (size_t i = 0; i < txt_count; i++) { + if (strcmp(txt.key, txt_list[i].key) == 0) { + if (txt_value_len == txt_value_len_list[i] && memcmp(txt.value, txt_list[i].value, txt_value_len) == 0) { + return true; + } else { + // The key value is unique, so there is no need to continue searching. + return false; + } + } + } + return false; +} + +/** + * @brief Create linked IP (copy) from parsed one + */ +static mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip) +{ + mdns_ip_addr_t *a = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); + if (!a) { + HOOK_MALLOC_FAILED; + return NULL; + } + memset(a, 0, sizeof(mdns_ip_addr_t)); + a->addr.type = ip->type; + if (ip->type == ESP_IPADDR_TYPE_V6) { + memcpy(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16); + } else { + a->addr.u_addr.ip4.addr = ip->u_addr.ip4.addr; + } + return a; +} + +/** + * @brief Chain new IP to search result + */ +static void _mdns_result_add_ip(mdns_result_t *r, esp_ip_addr_t *ip) +{ + mdns_ip_addr_t *a = r->addr; + while (a) { + if (a->addr.type == ip->type) { +#ifdef CONFIG_LWIP_IPV4 + if (a->addr.type == ESP_IPADDR_TYPE_V4 && a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { + return; + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (a->addr.type == ESP_IPADDR_TYPE_V6 && !memcmp(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { + return; + } +#endif + } + a = a->next; + } + a = _mdns_result_addr_create_ip(ip); + if (!a) { + return; + } + a->next = r->addr; + r->addr = a; +} + +/** + * @brief Called from parser to add A/AAAA data to search result + */ +static void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) +{ + mdns_result_t *r = NULL; + mdns_ip_addr_t *a = NULL; + + if ((search->type == MDNS_TYPE_A && ip->type == ESP_IPADDR_TYPE_V4) + || (search->type == MDNS_TYPE_AAAA && ip->type == ESP_IPADDR_TYPE_V6) + || search->type == MDNS_TYPE_ANY) { + r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { + _mdns_result_add_ip(r, ip); + _mdns_result_update_ttl(r, ttl); + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return; + } + + memset(r, 0, sizeof(mdns_result_t)); + + a = _mdns_result_addr_create_ip(ip); + if (!a) { + mdns_mem_free(r); + return; + } + a->next = r->addr; + r->hostname = mdns_mem_strdup(hostname); + r->addr = a; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->next = search->result; + r->ttl = ttl; + search->result = r; + search->num_results++; + } + } else if (search->type == MDNS_TYPE_PTR || search->type == MDNS_TYPE_SRV) { + r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + _mdns_result_add_ip(r, ip); + _mdns_result_update_ttl(r, ttl); + break; + } + r = r->next; + } + } +} + +/** + * @brief Called from parser to add A/AAAA data to search result + */ +static void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +{ + if (out_sync_browse->browse == NULL) { + return; + } else { + if (out_sync_browse->browse != browse) { + return; + } + } + mdns_result_t *r = NULL; + mdns_ip_addr_t *r_a = NULL; + if (browse) { + r = browse->result; + while (r) { + if (r->ip_protocol == ip_protocol) { + // Find the target result in browse result. + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + r_a = r->addr; + // Check if the address has already added in result. + while (r_a) { +#ifdef CONFIG_LWIP_IPV4 + if (r_a->addr.type == ip->type && r_a->addr.type == ESP_IPADDR_TYPE_V4 && r_a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { + break; + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (r_a->addr.type == ip->type && r_a->addr.type == ESP_IPADDR_TYPE_V6 && !memcmp(r_a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { + break; + } +#endif + r_a = r_a->next; + } + if (!r_a) { + // The current IP is a new one, add it to the link list. + mdns_ip_addr_t *a = NULL; + a = _mdns_result_addr_create_ip(ip); + if (!a) { + return; + } + a->next = r->addr; + r->addr = a; + if (r->ttl != ttl) { + if (r->ttl == 0) { + r->ttl = ttl; + } else { + _mdns_result_update_ttl(r, ttl); + } + } + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + break; + } + } + } + r = r->next; + } + } + return; +} + + +/** + * @brief Called from parser to add TXT data to search result + */ +static void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, + mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +{ + if (out_sync_browse->browse == NULL) { + return; + } else { + if (out_sync_browse->browse != browse) { + return; + } + } + mdns_result_t *r = browse->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && + !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && + !mdns_utils_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && + !mdns_utils_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { + bool should_update = false; + if (r->txt) { + // Check if txt changed + if (txt_count != r->txt_count) { + should_update = true; + } else { + for (size_t txt_index = 0; txt_index < txt_count; txt_index++) { + if (!is_txt_item_in_list(txt[txt_index], txt_value_len[txt_index], r->txt, r->txt_value_len, r->txt_count)) { + should_update = true; + break; + } + } + } + // If the result has a previous txt entry, we delete it and re-add. + for (size_t i = 0; i < r->txt_count; i++) { + mdns_mem_free((char *)(r->txt[i].key)); + mdns_mem_free((char *)(r->txt[i].value)); + } + mdns_mem_free(r->txt); + mdns_mem_free(r->txt_value_len); + } + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + if (r->ttl != ttl) { + uint32_t previous_ttl = r->ttl; + if (r->ttl == 0) { + r->ttl = ttl; + } else { + _mdns_result_update_ttl(r, ttl); + } + if (previous_ttl != r->ttl) { + should_update = true; + } + } + if (should_update) { + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + } + return; + } + r = r->next; + } + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + goto free_txt; + } + memset(r, 0, sizeof(mdns_result_t)); + r->instance_name = mdns_mem_strdup(instance); + r->service_type = mdns_mem_strdup(service); + r->proto = mdns_mem_strdup(proto); + if (!r->instance_name || !r->service_type || !r->proto) { + mdns_mem_free(r->instance_name); + mdns_mem_free(r->service_type); + mdns_mem_free(r->proto); + mdns_mem_free(r); + return; + } + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = browse->result; + browse->result = r; + _mdns_add_browse_result(out_sync_browse, r); + return; + +free_txt: + for (size_t i = 0; i < txt_count; i++) { + mdns_mem_free((char *)(txt[i].key)); + mdns_mem_free((char *)(txt[i].value)); + } + mdns_mem_free(txt); + mdns_mem_free(txt_value_len); + return; +} + +#ifdef CONFIG_LWIP_IPV4 +/** + * @brief Detect IPv4 address collision + */ +static int _mdns_check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) +{ + esp_netif_ip_info_t if_ip_info; + esp_netif_ip_info_t other_ip_info; + if (!ip->addr) { + return 1;//denial! they win + } + if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { + return 1;//they win + } + int ret = memcmp((uint8_t *)&if_ip_info.ip.addr, (uint8_t *)&ip->addr, sizeof(esp_ip4_addr_t)); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + //is it the other interface? + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if == MDNS_MAX_INTERFACES) { + return 1;//AP interface! They win + } + if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &other_ip_info)) { + return 1;//IPv4 not active! They win + } + if (ip->addr != other_ip_info.ip.addr) { + return 1;//IPv4 not ours! They win + } + _mdns_dup_interface(tcpip_if); + return 2;//they win + } + return 0;//same +} +#endif /* CONFIG_LWIP_IPV4 */ + +#ifdef CONFIG_LWIP_IPV6 +/** + * @brief Detect IPv6 address collision + */ +static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) +{ + struct esp_ip6_addr if_ip6; + struct esp_ip6_addr other_ip6; + if (_ipv6_address_is_zero(*ip)) { + return 1;//denial! they win + } + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(tcpip_if), &if_ip6)) { + return 1;//they win + } + int ret = memcmp((uint8_t *)&if_ip6.addr, (uint8_t *)ip->addr, _MDNS_SIZEOF_IP6_ADDR); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + //is it the other interface? + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if == MDNS_MAX_INTERFACES) { + return 1;//AP interface! They win + } + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &other_ip6)) { + return 1;//IPv6 not active! They win + } + if (memcmp((uint8_t *)&other_ip6.addr, (uint8_t *)ip->addr, _MDNS_SIZEOF_IP6_ADDR)) { + return 1;//IPv6 not ours! They win + } + _mdns_dup_interface(tcpip_if); + return 2;//they win + } + return 0;//same +} +#endif /* CONFIG_LWIP_IPV6 */ + + +/** + * @brief Detect TXT collision + */ +static int _mdns_check_txt_collision(mdns_service_t *service, const uint8_t *data, size_t len) +{ + size_t data_len = 0; + if (len <= 1 && service->txt) { // len==0 means incorrect packet (and handled by the packet parser) + // but handled here again to fix clang-tidy warning on VLA "uint8_t our[0];" + return -1;//we win + } else if (len > 1 && !service->txt) { + return 1;//they win + } else if (len <= 1 && !service->txt) { + return 0;//same + } + + mdns_txt_linked_item_t *txt = service->txt; + while (txt) { + data_len += 1 /* record-len */ + strlen(txt->key) + txt->value_len + (txt->value ? 1 : 0 /* "=" */); + txt = txt->next; + } + + if (len > data_len) { + return 1;//they win + } else if (len < data_len) { + return -1;//we win + } + + uint8_t ours[len]; + uint16_t index = 0; + + txt = service->txt; + while (txt) { + append_one_txt_record_entry(ours, &index, txt); + txt = txt->next; + } + + int ret = memcmp(ours, data, len); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + return 1;//they win + } + return 0;//same +} + + +/** + * @brief Detect SRV collision + */ +static int _mdns_check_srv_collision(mdns_service_t *service, uint16_t priority, uint16_t weight, uint16_t port, const char *host, const char *domain) +{ + if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { + return 0; + } + + size_t our_host_len = strlen(mdns_utils_get_global_hostname()); + size_t our_len = 14 + our_host_len; + + size_t their_host_len = strlen(host); + size_t their_domain_len = strlen(domain); + size_t their_len = 9 + their_host_len + their_domain_len; + + if (their_len > our_len) { + return 1;//they win + } else if (their_len < our_len) { + return -1;//we win + } + + uint16_t our_index = 0; + uint8_t our_data[our_len]; + _mdns_append_u16(our_data, &our_index, service->priority); + _mdns_append_u16(our_data, &our_index, service->weight); + _mdns_append_u16(our_data, &our_index, service->port); + our_data[our_index++] = our_host_len; + memcpy(our_data + our_index, mdns_utils_get_global_hostname(), our_host_len); + our_index += our_host_len; + our_data[our_index++] = 5; + memcpy(our_data + our_index, MDNS_UTILS_DEFAULT_DOMAIN, 5); + our_index += 5; + our_data[our_index++] = 0; + + uint16_t their_index = 0; + uint8_t their_data[their_len]; + _mdns_append_u16(their_data, &their_index, priority); + _mdns_append_u16(their_data, &their_index, weight); + _mdns_append_u16(their_data, &their_index, port); + their_data[their_index++] = their_host_len; + memcpy(their_data + their_index, host, their_host_len); + their_index += their_host_len; + their_data[their_index++] = their_domain_len; + memcpy(their_data + their_index, domain, their_domain_len); + their_index += their_domain_len; + their_data[their_index++] = 0; + + int ret = memcmp(our_data, their_data, our_len); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + return 1;//they win + } + return 0;//same +} + +/** + * @brief Called from parser to add SRV data to search result + */ +static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) +{ + mdns_result_t *r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + _mdns_result_update_ttl(r, ttl); + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->hostname = mdns_mem_strdup(hostname); + if (!r->hostname) { + mdns_mem_free(r); + return; + } + if (search->instance) { + r->instance_name = mdns_mem_strdup(search->instance); + } + r->service_type = mdns_mem_strdup(search->service); + r->proto = mdns_mem_strdup(search->proto); + r->port = port; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = search->result; + search->result = r; + search->num_results++; + } +} + +static esp_err_t _mdns_copy_address_in_previous_result(mdns_result_t *result_list, mdns_result_t *r) +{ + while (result_list) { + if (!mdns_utils_str_null_or_empty(result_list->hostname) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(result_list->hostname, r->hostname) && + result_list->ip_protocol == r->ip_protocol && result_list->addr && !r->addr) { + // If there is a same hostname in previous result, we need to copy the address here. + r->addr = copy_address_list(result_list->addr); + if (!r->addr) { + return ESP_ERR_NO_MEM; + } + break; + } else { + result_list = result_list->next; + } + } + return ESP_OK; +} + +/** + * @brief Called from parser to add SRV data to search result + */ +static void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, + uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +{ + if (out_sync_browse->browse == NULL) { + return; + } else { + if (out_sync_browse->browse != browse) { + return; + } + } + mdns_result_t *r = browse->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && + !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && + !mdns_utils_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && + !mdns_utils_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { + if (mdns_utils_str_null_or_empty(r->hostname) || strcasecmp(hostname, r->hostname)) { + r->hostname = mdns_mem_strdup(hostname); + r->port = port; + if (!r->hostname) { + HOOK_MALLOC_FAILED; + return; + } + if (!r->addr) { + esp_err_t err = _mdns_copy_address_in_previous_result(browse->result, r); + if (err == ESP_ERR_NO_MEM) { + return; + } + } + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + } + if (r->ttl != ttl) { + uint32_t previous_ttl = r->ttl; + if (r->ttl == 0) { + r->ttl = ttl; + } else { + _mdns_result_update_ttl(r, ttl); + } + if (previous_ttl != r->ttl) { + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + } + } + return; + } + r = r->next; + } + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->hostname = mdns_mem_strdup(hostname); + r->instance_name = mdns_mem_strdup(instance); + r->service_type = mdns_mem_strdup(service); + r->proto = mdns_mem_strdup(proto); + if (!r->hostname || !r->instance_name || !r->service_type || !r->proto) { + HOOK_MALLOC_FAILED; + mdns_mem_free(r->hostname); + mdns_mem_free(r->instance_name); + mdns_mem_free(r->service_type); + mdns_mem_free(r->proto); + mdns_mem_free(r); + return; + } + r->port = port; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = browse->result; + browse->result = r; + _mdns_add_browse_result(out_sync_browse, r); + return; +} + + +/** + * @brief Check if the parsed name is self-hosted, i.e. we should resolve conflicts + */ +static bool _mdns_name_is_selfhosted(mdns_name_t *name) +{ + if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { // self-hostname needs to be defined + return false; + } + + // hostname only -- check if selfhosted name + if (mdns_utils_str_null_or_empty(name->service) && mdns_utils_str_null_or_empty(name->proto) && + strcasecmp(name->host, mdns_utils_get_global_hostname()) == 0) { + return true; + } + + // service -- check if selfhosted service + mdns_srv_item_t *srv = _mdns_get_service_item(name->service, name->proto, NULL); + if (srv && strcasecmp(mdns_utils_get_global_hostname(), srv->service->hostname) == 0) { + return true; + } + return false; +} + + +/** + * @brief Find, remove and free answer from the scheduled packets + */ +static void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service) +{ + mdns_srv_item_t s = {NULL, NULL}; + if (!service) { + service = &s; + } + mdns_tx_packet_t *q = mdns_utils_get_tx_packet(); + while (q) { + if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol && q->distributed) { + mdns_out_answer_t *a = q->answers; + if (a) { + if (a->type == type && a->service == service->service) { + q->answers = q->answers->next; + mdns_mem_free(a); + } else { + while (a->next) { + if (a->next->type == type && a->next->service == service->service) { + mdns_out_answer_t *b = a->next; + a->next = b->next; + mdns_mem_free(b); + break; + } + a = a->next; + } + } + } + } + q = q->next; + } +} + + +/** + * @brief Called from parser to check if question matches particular service + */ +static bool _mdns_question_matches(mdns_parsed_question_t *question, uint16_t type, mdns_srv_item_t *service) +{ + if (question->type != type) { + return false; + } + if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { + return true; + } else if (type == MDNS_TYPE_PTR || type == MDNS_TYPE_SDPTR) { + if (question->service && question->proto && question->domain + && !strcasecmp(service->service->service, question->service) + && !strcasecmp(service->service->proto, question->proto) + && !strcasecmp(MDNS_UTILS_DEFAULT_DOMAIN, question->domain)) { + if (!service->service->instance) { + return true; + } else if (service->service->instance && question->host && !strcasecmp(service->service->instance, question->host)) { + return true; + } + } + } else if (service && (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT)) { + const char *name = _mdns_get_service_instance_name(service->service); + if (name && question->host && question->service && question->proto && question->domain + && !strcasecmp(name, question->host) + && !strcasecmp(service->service->service, question->service) + && !strcasecmp(service->service->proto, question->proto) + && !strcasecmp(MDNS_UTILS_DEFAULT_DOMAIN, question->domain)) { + return true; + } + } + + return false; +} + +/** + * @brief Removes saved question from parsed data + */ +static void _mdns_remove_parsed_question(mdns_parsed_packet_t *parsed_packet, uint16_t type, mdns_srv_item_t *service) +{ + mdns_parsed_question_t *q = parsed_packet->questions; + + if (_mdns_question_matches(q, type, service)) { + parsed_packet->questions = q->next; + mdns_mem_free(q->host); + mdns_mem_free(q->service); + mdns_mem_free(q->proto); + mdns_mem_free(q->domain); + mdns_mem_free(q); + return; + } + + while (q->next) { + mdns_parsed_question_t *p = q->next; + if (_mdns_question_matches(p, type, service)) { + q->next = p->next; + mdns_mem_free(p->host); + mdns_mem_free(p->service); + mdns_mem_free(p->proto); + mdns_mem_free(p->domain); + mdns_mem_free(p); + return; + } + q = q->next; + } +} + + +/** + * @brief Called from parser to add PTR data to search result + */ +static mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, + const char *service_type, const char *proto, mdns_if_t tcpip_if, + mdns_ip_protocol_t ip_protocol, uint32_t ttl) +{ + mdns_result_t *r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { + _mdns_result_update_ttl(r, ttl); + return r; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return NULL; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->instance_name = mdns_mem_strdup(instance); + r->service_type = mdns_mem_strdup(service_type); + r->proto = mdns_mem_strdup(proto); + if (!r->instance_name) { + mdns_mem_free(r); + return NULL; + } + + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = search->result; + search->result = r; + search->num_results++; + return r; + } + return NULL; +} + + +/** + * @brief Called from packet parser to find matching running search + */ +static mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_result_t *r = NULL; + while (s) { + if (s->state == SEARCH_OFF) { + s = s->next; + continue; + } + + if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { + if ((s->type == MDNS_TYPE_ANY && s->service != NULL) + || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV)) { + s = s->next; + continue; + } + if (s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV) { + if (!strcasecmp(name->host, s->instance)) { + return s; + } + s = s->next; + continue; + } + r = s->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { + return s; + } + r = r->next; + } + s = s->next; + continue; + } + + if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { + if ((s->type == MDNS_TYPE_ANY && s->service == NULL) + || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR)) { + s = s->next; + continue; + } + if (strcasecmp(name->service, s->service) + || strcasecmp(name->proto, s->proto)) { + s = s->next; + continue; + } + if (s->type != MDNS_TYPE_PTR) { + if (s->instance && strcasecmp(name->host, s->instance) == 0) { + return s; + } + s = s->next; + continue; + } + return s; + } + + if (type == MDNS_TYPE_PTR && type == s->type && !strcasecmp(name->service, s->service) && !strcasecmp(name->proto, s->proto)) { + return s; + } + + s = s->next; + } + + return NULL; +} + + +/** + * @brief Called from packet parser to find matching running search + */ +static mdns_browse_t *_mdns_browse_find_from(mdns_browse_t *b, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + // For browse, we only care about the SRV, TXT, A and AAAA + if (type != MDNS_TYPE_SRV && type != MDNS_TYPE_A && type != MDNS_TYPE_AAAA && type != MDNS_TYPE_TXT) { + return NULL; + } + mdns_result_t *r = NULL; + while (b) { + if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { + if (strcasecmp(name->service, b->service) + || strcasecmp(name->proto, b->proto)) { + b = b->next; + continue; + } + return b; + } else if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { + r = b->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { + return b; + } + r = r->next; + } + b = b->next; + continue; + } + } + return b; +} + + +/** + * @brief main packet parser + * + * @param packet the packet + */ +void mdns_parse_packet(mdns_rx_packet_t *packet) +{ + static mdns_name_t n; + mdns_header_t header; + const uint8_t *data = _mdns_get_packet_data(packet); + size_t len = _mdns_get_packet_len(packet); + const uint8_t *content = data + MDNS_HEAD_LEN; + bool do_not_reply = false; + mdns_search_once_t *search_result = NULL; + mdns_browse_t *browse_result = NULL; + char *browse_result_instance = NULL; + char *browse_result_service = NULL; + char *browse_result_proto = NULL; + mdns_browse_sync_t *out_sync_browse = NULL; + +#ifdef MDNS_ENABLE_DEBUG + _mdns_dbg_printf("\nRX[%lu][%lu]: ", (unsigned long)packet->tcpip_if, (unsigned long)packet->ip_protocol); +#ifdef CONFIG_LWIP_IPV4 + if (packet->src.type == ESP_IPADDR_TYPE_V4) { + _mdns_dbg_printf("From: " IPSTR ":%u, To: " IPSTR ", ", IP2STR(&packet->src.u_addr.ip4), packet->src_port, IP2STR(&packet->dest.u_addr.ip4)); + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (packet->src.type == ESP_IPADDR_TYPE_V6) { + _mdns_dbg_printf("From: " IPV6STR ":%u, To: " IPV6STR ", ", IPV62STR(packet->src.u_addr.ip6), packet->src_port, IPV62STR(packet->dest.u_addr.ip6)); + } +#endif + mdns_debug_packet(data, len); +#endif + +#ifndef CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES + // Check if the packet wasn't sent by us +#ifdef CONFIG_LWIP_IPV4 + if (packet->ip_protocol == MDNS_IP_PROTOCOL_V4) { + esp_netif_ip_info_t if_ip_info; + if (esp_netif_get_ip_info(_mdns_get_esp_netif(packet->tcpip_if), &if_ip_info) == ESP_OK && + memcmp(&if_ip_info.ip.addr, &packet->src.u_addr.ip4.addr, sizeof(esp_ip4_addr_t)) == 0) { + return; + } + } +#endif /* CONFIG_LWIP_IPV4 */ +#ifdef CONFIG_LWIP_IPV6 + if (packet->ip_protocol == MDNS_IP_PROTOCOL_V6) { + struct esp_ip6_addr if_ip6; + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(packet->tcpip_if), &if_ip6) == ESP_OK && + memcmp(&if_ip6, &packet->src.u_addr.ip6, sizeof(esp_ip6_addr_t)) == 0) { + return; + } + } +#endif /* CONFIG_LWIP_IPV6 */ +#endif // CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES + + // Check for the minimum size of mdns packet + if (len <= MDNS_HEAD_ADDITIONAL_OFFSET) { + return; + } + + mdns_parsed_packet_t *parsed_packet = (mdns_parsed_packet_t *)mdns_mem_malloc(sizeof(mdns_parsed_packet_t)); + if (!parsed_packet) { + HOOK_MALLOC_FAILED; + return; + } + memset(parsed_packet, 0, sizeof(mdns_parsed_packet_t)); + + mdns_name_t *name = &n; + memset(name, 0, sizeof(mdns_name_t)); + + header.id = mdns_utils_read_u16(data, MDNS_HEAD_ID_OFFSET); + header.flags = mdns_utils_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); + header.questions = mdns_utils_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); + header.answers = mdns_utils_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); + header.servers = mdns_utils_read_u16(data, MDNS_HEAD_SERVERS_OFFSET); + header.additional = mdns_utils_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); + + if (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE && packet->src_port != MDNS_SERVICE_PORT) { + mdns_mem_free(parsed_packet); + return; + } + + //if we have not set the hostname, we can not answer questions + if (header.questions && !header.answers && mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { + mdns_mem_free(parsed_packet); + return; + } + + parsed_packet->tcpip_if = packet->tcpip_if; + parsed_packet->ip_protocol = packet->ip_protocol; + parsed_packet->multicast = packet->multicast; + parsed_packet->authoritative = (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE); + parsed_packet->distributed = header.flags == MDNS_FLAGS_DISTRIBUTED; + parsed_packet->id = header.id; + esp_netif_ip_addr_copy(&parsed_packet->src, &packet->src); + parsed_packet->src_port = packet->src_port; + parsed_packet->records = NULL; + + if (header.questions) { + uint8_t qs = header.questions; + + while (qs--) { + content = _mdns_parse_fqdn(data, content, name, len); + if (!content) { + header.answers = 0; + header.additional = 0; + header.servers = 0; + goto clear_rx_packet;//error + } + + if (content + MDNS_CLASS_OFFSET + 1 >= data + len) { + goto clear_rx_packet; // malformed packet, won't read behind it + } + uint16_t type = mdns_utils_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t mdns_class = mdns_utils_read_u16(content, MDNS_CLASS_OFFSET); + bool unicast = !!(mdns_class & 0x8000); + mdns_class &= 0x7FFF; + content = content + 4; + + if (mdns_class != 0x0001 || name->invalid) {//bad class or invalid name for this question entry + continue; + } + + if (_mdns_name_is_discovery(name, type)) { + //service discovery + parsed_packet->discovery = true; + mdns_srv_item_t *a = mdns_utils_get_services(); + while (a) { + mdns_parsed_question_t *question = (mdns_parsed_question_t *)mdns_mem_calloc(1, sizeof(mdns_parsed_question_t)); + if (!question) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + question->next = parsed_packet->questions; + parsed_packet->questions = question; + + question->unicast = unicast; + question->type = MDNS_TYPE_SDPTR; + question->host = NULL; + question->service = mdns_mem_strdup(a->service->service); + question->proto = mdns_mem_strdup(a->service->proto); + question->domain = mdns_mem_strdup(MDNS_UTILS_DEFAULT_DOMAIN); + if (!question->service || !question->proto || !question->domain) { + goto clear_rx_packet; + } + a = a->next; + } + continue; + } + if (!_mdns_name_is_ours(name)) { + continue; + } + + if (type == MDNS_TYPE_ANY && !mdns_utils_str_null_or_empty(name->host)) { + parsed_packet->probe = true; + } + + mdns_parsed_question_t *question = (mdns_parsed_question_t *)mdns_mem_calloc(1, sizeof(mdns_parsed_question_t)); + if (!question) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + question->next = parsed_packet->questions; + parsed_packet->questions = question; + + question->unicast = unicast; + question->type = type; + question->sub = name->sub; + if (_mdns_strdup_check(&(question->host), name->host) + || _mdns_strdup_check(&(question->service), name->service) + || _mdns_strdup_check(&(question->proto), name->proto) + || _mdns_strdup_check(&(question->domain), name->domain)) { + goto clear_rx_packet; + } + } + } + + if (header.questions && !parsed_packet->questions && !parsed_packet->discovery && !header.answers) { + goto clear_rx_packet; + } else if (header.answers || header.servers || header.additional) { + uint16_t recordIndex = 0; + + while (content < (data + len)) { + + content = _mdns_parse_fqdn(data, content, name, len); + if (!content) { + goto clear_rx_packet;//error + } + + if (content + MDNS_LEN_OFFSET + 1 >= data + len) { + goto clear_rx_packet; // malformed packet, won't read behind it + } + uint16_t type = mdns_utils_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t mdns_class = mdns_utils_read_u16(content, MDNS_CLASS_OFFSET); + uint32_t ttl = mdns_utils_read_u32(content, MDNS_TTL_OFFSET); + uint16_t data_len = mdns_utils_read_u16(content, MDNS_LEN_OFFSET); + const uint8_t *data_ptr = content + MDNS_DATA_OFFSET; + mdns_class &= 0x7FFF; + + content = data_ptr + data_len; + if (content > (data + len) || data_len == 0) { + goto clear_rx_packet; + } + + bool discovery = false; + bool ours = false; + mdns_srv_item_t *service = NULL; + mdns_parsed_record_type_t record_type = MDNS_ANSWER; + + if (recordIndex >= (header.answers + header.servers)) { + record_type = MDNS_EXTRA; + } else if (recordIndex >= (header.answers)) { + record_type = MDNS_NS; + } + recordIndex++; + + if (type == MDNS_TYPE_NSEC || type == MDNS_TYPE_OPT) { + //skip NSEC and OPT + continue; + } + + if (parsed_packet->discovery && _mdns_name_is_discovery(name, type)) { + discovery = true; + } else if (!name->sub && _mdns_name_is_ours(name)) { + ours = true; + if (name->service[0] && name->proto[0]) { + service = _mdns_get_service_item(name->service, name->proto, NULL); + } + } else { + if ((header.flags & MDNS_FLAGS_QUERY_REPSONSE) == 0 || record_type == MDNS_NS) { + //skip this record + continue; + } + search_result = _mdns_search_find_from(mdns_utils_get_search(), name, type, packet->tcpip_if, packet->ip_protocol); + browse_result = _mdns_browse_find_from(mdns_utils_get_browse(), name, type, packet->tcpip_if, packet->ip_protocol); + if (browse_result) { + if (!out_sync_browse) { + // will be freed in function `_mdns_browse_sync` + out_sync_browse = (mdns_browse_sync_t *)mdns_mem_malloc(sizeof(mdns_browse_sync_t)); + if (!out_sync_browse) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + out_sync_browse->browse = browse_result; + out_sync_browse->sync_result = NULL; + } + if (!browse_result_service) { + browse_result_service = (char *)mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!browse_result_service) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + } + memcpy(browse_result_service, browse_result->service, MDNS_NAME_BUF_LEN); + if (!browse_result_proto) { + browse_result_proto = (char *)mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!browse_result_proto) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + } + memcpy(browse_result_proto, browse_result->proto, MDNS_NAME_BUF_LEN); + if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { + if (!browse_result_instance) { + browse_result_instance = (char *)mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!browse_result_instance) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + } + memcpy(browse_result_instance, name->host, MDNS_NAME_BUF_LEN); + } + } + } + + if (type == MDNS_TYPE_PTR) { + if (!_mdns_parse_fqdn(data, data_ptr, name, len)) { + continue;//error + } + if (search_result) { + _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); + } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { + if (name->host[0]) { + service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL); + } else { + service = _mdns_get_service_item(name->service, name->proto, NULL); + } + if (discovery && service) { + _mdns_remove_parsed_question(parsed_packet, MDNS_TYPE_SDPTR, service); + } else if (service && parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, service); + } else if (service) { + //check if TTL is more than half of the full TTL value (4500) + if (ttl > (MDNS_ANSWER_PTR_TTL / 2)) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + } + } + if (service) { + mdns_parsed_record_t *record = mdns_mem_malloc(sizeof(mdns_parsed_record_t)); + if (!record) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + record->next = parsed_packet->records; + parsed_packet->records = record; + record->type = MDNS_TYPE_PTR; + record->record_type = MDNS_ANSWER; + record->ttl = ttl; + record->host = NULL; + record->service = NULL; + record->proto = NULL; + if (name->host[0]) { + record->host = mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!record->host) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + memcpy(record->host, name->host, MDNS_NAME_BUF_LEN); + } + if (name->service[0]) { + record->service = mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!record->service) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + memcpy(record->service, name->service, MDNS_NAME_BUF_LEN); + } + if (name->proto[0]) { + record->proto = mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!record->proto) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + memcpy(record->proto, name->proto, MDNS_NAME_BUF_LEN); + } + } + } + } else if (type == MDNS_TYPE_SRV) { + mdns_result_t *result = NULL; + if (search_result && search_result->type == MDNS_TYPE_PTR) { + result = search_result->result; + while (result) { + if (_mdns_get_esp_netif(packet->tcpip_if) == result->esp_netif + && packet->ip_protocol == result->ip_protocol + && result->instance_name && !strcmp(name->host, result->instance_name)) { + break; + } + result = result->next; + } + if (!result) { + result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); + if (!result) { + continue;//error + } + } + } + bool is_selfhosted = _mdns_name_is_selfhosted(name); + if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { + continue;//error + } + if (data_ptr + MDNS_SRV_PORT_OFFSET + 1 >= data + len) { + goto clear_rx_packet; // malformed packet, won't read behind it + } + uint16_t priority = mdns_utils_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); + uint16_t weight = mdns_utils_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); + uint16_t port = mdns_utils_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); + + if (browse_result) { + _mdns_browse_result_add_srv(browse_result, name->host, browse_result_instance, browse_result_service, + browse_result_proto, port, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + } + if (search_result) { + if (search_result->type == MDNS_TYPE_PTR) { + if (!result->hostname) { // assign host/port for this entry only if not previously set + result->port = port; + result->hostname = mdns_mem_strdup(name->host); + } + } else { + _mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol, ttl); + } + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, service); + continue; + } else if (parsed_packet->distributed) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + continue; + } + if (!is_selfhosted) { + continue; + } + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (mdns_class > 1) { + col = 1; + } else if (!mdns_class) { + col = -1; + } else if (service) { // only detect srv collision if service existed + col = _mdns_check_srv_collision(service->service, priority, weight, port, name->host, name->domain); + } + if (service && col && (parsed_packet->probe || parsed_packet->authoritative)) { + if (col > 0 || !port) { + do_not_reply = true; + if (mdns_utils_is_probing(packet)) { + mdns_utils_probe_failed(packet); + if (!mdns_utils_str_null_or_empty(service->service->instance)) { + char *new_instance = _mdns_mangle_name((char *)service->service->instance); + if (new_instance) { + mdns_mem_free((char *)service->service->instance); + service->service->instance = new_instance; + } + _mdns_probe_all_pcbs(&service, 1, false, false); + } else if (!mdns_utils_str_null_or_empty(mdns_utils_get_instance())) { + char *new_instance = _mdns_mangle_name((char *)mdns_utils_get_instance()); + if (new_instance) { + mdns_utils_set_instance(new_instance); + } + _mdns_restart_all_pcbs_no_instance(); + } else { + char *new_host = _mdns_mangle_name((char *)mdns_utils_get_global_hostname()); + if (new_host) { + _mdns_remap_self_service_hostname(mdns_utils_get_global_hostname(), new_host); + mdns_utils_set_global_hostname(new_host); + } + _mdns_restart_all_pcbs(); + } + } else if (service) { + _mdns_pcb_send_bye(packet->tcpip_if, packet->ip_protocol, &service, 1, false); + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, false); + } + } + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + } + } + } else if (type == MDNS_TYPE_TXT) { + mdns_txt_item_t *txt = NULL; + uint8_t *txt_value_len = NULL; + size_t txt_count = 0; + + mdns_result_t *result = NULL; + if (browse_result) { + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); + _mdns_browse_result_add_txt(browse_result, browse_result_instance, browse_result_service, browse_result_proto, + txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + } + if (search_result) { + if (search_result->type == MDNS_TYPE_PTR) { + result = search_result->result; + while (result) { + if (_mdns_get_esp_netif(packet->tcpip_if) == result->esp_netif + && packet->ip_protocol == result->ip_protocol + && result->instance_name && !strcmp(name->host, result->instance_name)) { + break; + } + result = result->next; + } + if (!result) { + result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); + if (!result) { + continue;//error + } + } + if (!result->txt) { + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); + if (txt_count) { + result->txt = txt; + result->txt_count = txt_count; + result->txt_value_len = txt_value_len; + } + } + } else { + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); + if (txt_count) { + _mdns_search_result_add_txt(search_result, txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, ttl); + } + } + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe && service) { + _mdns_remove_parsed_question(parsed_packet, type, service); + continue; + } + if (!_mdns_name_is_selfhosted(name)) { + continue; + } + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (mdns_class > 1) { + col = 1; + } else if (!mdns_class) { + col = -1; + } else if (service) { // only detect txt collision if service existed + col = _mdns_check_txt_collision(service->service, data_ptr, data_len); + } + if (col && !mdns_utils_is_probing(packet) && service) { + do_not_reply = true; + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); + } else if (ttl > (MDNS_ANSWER_TXT_TTL / 2) && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_utils_is_probing(packet)) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + } + } + + } +#ifdef CONFIG_LWIP_IPV6 + else if (type == MDNS_TYPE_AAAA) {//ipv6 + esp_ip_addr_t ip6; + ip6.type = ESP_IPADDR_TYPE_V6; + memcpy(ip6.u_addr.ip6.addr, data_ptr, MDNS_ANSWER_AAAA_SIZE); + if (browse_result) { + _mdns_browse_result_add_ip(browse_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + } + if (search_result) { + //check for more applicable searches (PTR & A/AAAA at the same time) + while (search_result) { + _mdns_search_result_add_ip(search_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, ttl); + search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); + } + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, NULL); + continue; + } + if (!_mdns_name_is_selfhosted(name)) { + continue; + } + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (mdns_class > 1) { + col = 1; + } else if (!mdns_class) { + col = -1; + } else { + col = _mdns_check_aaaa_collision(&(ip6.u_addr.ip6), packet->tcpip_if); + } + if (col == 2) { + goto clear_rx_packet; + } else if (col == 1) { + do_not_reply = true; + if (mdns_utils_is_probing(packet)) { + if (col && (parsed_packet->probe || parsed_packet->authoritative)) { + mdns_utils_probe_failed(packet); + char *new_host = _mdns_mangle_name((char *)mdns_utils_get_global_hostname()); + if (new_host) { + _mdns_remap_self_service_hostname(mdns_utils_get_global_hostname(), new_host); + mdns_utils_set_global_hostname(new_host); + } + _mdns_restart_all_pcbs(); + } + } else { + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); + } + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_utils_is_probing(packet)) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); + } + } + + } +#endif /* CONFIG_LWIP_IPV6 */ +#ifdef CONFIG_LWIP_IPV4 + else if (type == MDNS_TYPE_A) { + esp_ip_addr_t ip; + ip.type = ESP_IPADDR_TYPE_V4; + memcpy(&(ip.u_addr.ip4.addr), data_ptr, 4); + if (browse_result) { + _mdns_browse_result_add_ip(browse_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + } + if (search_result) { + //check for more applicable searches (PTR & A/AAAA at the same time) + while (search_result) { + _mdns_search_result_add_ip(search_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, ttl); + search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); + } + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, NULL); + continue; + } + if (!_mdns_name_is_selfhosted(name)) { + continue; + } + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (mdns_class > 1) { + col = 1; + } else if (!mdns_class) { + col = -1; + } else { + col = _mdns_check_a_collision(&(ip.u_addr.ip4), packet->tcpip_if); + } + if (col == 2) { + goto clear_rx_packet; + } else if (col == 1) { + do_not_reply = true; + if (mdns_utils_is_probing(packet)) { + if (col && (parsed_packet->probe || parsed_packet->authoritative)) { + mdns_utils_probe_failed(packet); + char *new_host = _mdns_mangle_name((char *)mdns_utils_get_global_hostname()); + if (new_host) { + _mdns_remap_self_service_hostname(mdns_utils_get_global_hostname(), new_host); + mdns_utils_set_global_hostname(new_host); + } + _mdns_restart_all_pcbs(); + } + } else { + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); + } + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_utils_is_probing(packet)) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); + } + } + + } +#endif /* CONFIG_LWIP_IPV4 */ + } + //end while + if (parsed_packet->authoritative) { + _mdns_search_finish_done(); + } + } + + if (!do_not_reply && mdns_utils_after_probing(packet) && (parsed_packet->questions || parsed_packet->discovery)) { + _mdns_create_answer_from_parsed_packet(parsed_packet); + } + if (out_sync_browse) { +#ifdef MDNS_ENABLE_DEBUG + _mdns_dbg_printf("Browse %s%s total result:", out_sync_browse->browse->service, out_sync_browse->browse->proto); + debug_printf_browse_result_all(out_sync_browse->browse->result); +#endif // MDNS_ENABLE_DEBUG + if (out_sync_browse->sync_result) { +#ifdef MDNS_ENABLE_DEBUG + _mdns_dbg_printf("Changed result:"); + debug_printf_browse_result_all(out_sync_browse->sync_result->result); +#endif // MDNS_ENABLE_DEBUG + _mdns_sync_browse_action(ACTION_BROWSE_SYNC, out_sync_browse); + } else { + mdns_mem_free(out_sync_browse); + } + out_sync_browse = NULL; + } + +clear_rx_packet: + while (parsed_packet->questions) { + mdns_parsed_question_t *question = parsed_packet->questions; + parsed_packet->questions = parsed_packet->questions->next; + if (question->host) { + mdns_mem_free(question->host); + } + if (question->service) { + mdns_mem_free(question->service); + } + if (question->proto) { + mdns_mem_free(question->proto); + } + if (question->domain) { + mdns_mem_free(question->domain); + } + mdns_mem_free(question); + } + while (parsed_packet->records) { + mdns_parsed_record_t *record = parsed_packet->records; + parsed_packet->records = parsed_packet->records->next; + if (record->host) { + mdns_mem_free(record->host); + } + if (record->service) { + mdns_mem_free(record->service); + } + if (record->proto) { + mdns_mem_free(record->proto); + } + record->next = NULL; + mdns_mem_free(record); + } + mdns_mem_free(parsed_packet); + mdns_mem_free(browse_result_instance); + mdns_mem_free(browse_result_service); + mdns_mem_free(browse_result_proto); + mdns_mem_free(out_sync_browse); +} diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c new file mode 100644 index 0000000000..a51c08e7a6 --- /dev/null +++ b/components/mdns/mdns_querier.c @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "mdns_private.h" +#include "mdns_networking.h" +#include "mdns_types.h" + +// Query functions +static esp_err_t mdns_send_query(mdns_out_question_t *questions); +static void mdns_query_handle_response(mdns_parsed_packet_t *packet); +static void mdns_search_finish(mdns_search_once_t *search); diff --git a/components/mdns/mdns_responder.c b/components/mdns/mdns_responder.c new file mode 100644 index 0000000000..a74c48ca5a --- /dev/null +++ b/components/mdns/mdns_responder.c @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "mdns_private.h" +#include "mdns_networking.h" +#include "mdns_types.h" + +// Response generation +static esp_err_t mdns_send_response(mdns_out_answer_t *answers, mdns_tx_packet_t *packet); +static void mdns_announce_service(mdns_service_t *service, bool bye); +static void mdns_announce_host(bool bye); diff --git a/components/mdns/mdns_service.c b/components/mdns/mdns_service.c new file mode 100644 index 0000000000..237d777894 --- /dev/null +++ b/components/mdns/mdns_service.c @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "mdns_private.h" +#include "mdns_networking.h" +#include "mdns_types.h" + +// Service management functions +static esp_err_t mdns_start_service_task(void); +static void mdns_service_task(void *pvParameters); +static void mdns_timer_cb(void *arg); + +// Action handling +static esp_err_t mdns_handle_system_event(mdns_action_t *action); +static esp_err_t mdns_handle_action(mdns_action_t *action); diff --git a/components/mdns/mdns_utils.c b/components/mdns/mdns_utils.c new file mode 100644 index 0000000000..f128b6f024 --- /dev/null +++ b/components/mdns/mdns_utils.c @@ -0,0 +1,299 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "mdns_private.h" +#include "mdns_mem_caps.h" +#include "esp_log.h" +#include "mdns_utils.h" + +static const char *MDNS_DEFAULT_DOMAIN = "local"; +static const char *MDNS_SUB_STR = "_sub"; +static const char *TAG = "mdns_utils"; + +/** + * @brief reads MDNS FQDN into mdns_name_t structure + * FQDN is in format: [hostname.|[instance.]_service._proto.]local. + * + * @param packet MDNS packet + * @param start Starting point of FQDN + * @param name mdns_name_t structure to populate + * @param buf temporary char buffer + * + * @return the address after the parsed FQDN in the packet or NULL on error + */ +const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len) +{ + size_t index = 0; + const uint8_t *packet_end = packet + packet_len; + while (start + index < packet_end && start[index]) { + if (name->parts == 4) { + name->invalid = true; + } + uint8_t len = start[index++]; + if (len < 0xC0) { + if (len > 63) { + //length can not be more than 63 + return NULL; + } + uint8_t i; + for (i = 0; i < len; i++) { + if (start + index >= packet_end) { + return NULL; + } + buf[i] = start[index++]; + } + buf[len] = '\0'; + if (name->parts == 1 && buf[0] != '_' + && (strcasecmp(buf, MDNS_DEFAULT_DOMAIN) != 0) + && (strcasecmp(buf, "arpa") != 0) +#ifndef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + && (strcasecmp(buf, "ip6") != 0) + && (strcasecmp(buf, "in-addr") != 0) +#endif + ) { + strlcat(name->host, ".", sizeof(name->host)); + strlcat(name->host, buf, sizeof(name->host)); + } else if (strcasecmp(buf, MDNS_SUB_STR) == 0) { + name->sub = 1; + } else if (!name->invalid) { + char *mdns_name_ptrs[] = {name->host, name->service, name->proto, name->domain}; + memcpy(mdns_name_ptrs[name->parts++], buf, len + 1); + } + } else { + size_t address = (((uint16_t)len & 0x3F) << 8) | start[index++]; + if ((packet + address) >= start) { + //reference address can not be after where we are + return NULL; + } + if (_mdns_read_fqdn(packet, packet + address, name, buf, packet_len)) { + return start + index; + } + return NULL; + } + } + return start + index + 1; +} + +/** + * @brief reads and formats MDNS FQDN into mdns_name_t structure + * + * @param packet MDNS packet + * @param start Starting point of FQDN + * @param name mdns_name_t structure to populate + * + * @return the address after the parsed FQDN in the packet or NULL on error + */ +const uint8_t *_mdns_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, size_t packet_len) +{ + name->parts = 0; + name->sub = 0; + name->host[0] = 0; + name->service[0] = 0; + name->proto[0] = 0; + name->domain[0] = 0; + name->invalid = false; + + static char buf[MDNS_NAME_BUF_LEN]; + + const uint8_t *next_data = (uint8_t *)_mdns_read_fqdn(packet, start, name, buf, packet_len); + if (!next_data) { + return 0; + } + if (!name->parts || name->invalid) { + return next_data; + } + if (name->parts == 3) { + memmove((uint8_t *)name + (MDNS_NAME_BUF_LEN), (uint8_t *)name, 3 * (MDNS_NAME_BUF_LEN)); + name->host[0] = 0; + } else if (name->parts == 2) { + memmove((uint8_t *)(name->domain), (uint8_t *)(name->service), (MDNS_NAME_BUF_LEN)); + name->service[0] = 0; + name->proto[0] = 0; + } + if (strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN) == 0 || strcasecmp(name->domain, "arpa") == 0) { + return next_data; + } + name->invalid = true; // mark the current name invalid, but continue with other question + return next_data; +} + +bool _hostname_is_ours(const char *hostname) +{ + if (!mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname()) && + strcasecmp(hostname, mdns_utils_get_global_hostname()) == 0) { + return true; + } + mdns_host_item_t *host = mdns_utils_get_hosts(); + while (host != NULL) { + if (strcasecmp(hostname, host->hostname) == 0) { + return true; + } + host = host->next; + } + return false; +} + +bool _mdns_service_match(const mdns_service_t *srv, const char *service, const char *proto, + const char *hostname) +{ + if (!service || !proto || !srv->hostname) { + return false; + } + return !strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && + (mdns_utils_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); +} + + +/** + * @brief finds service from given service type + * @param server the server + * @param service service type to match + * @param proto proto to match + * @param hostname hostname of the service (if non-null) + * + * @return the service item if found or NULL on error + */ +mdns_srv_item_t *_mdns_get_service_item(const char *service, const char *proto, const char *hostname) +{ + mdns_srv_item_t *s = mdns_utils_get_services(); + while (s) { + if (_mdns_service_match(s->service, service, proto, hostname)) { + return s; + } + s = s->next; + } + return NULL; +} + +mdns_srv_item_t *_mdns_get_service_item_instance(const char *instance, const char *service, const char *proto, + const char *hostname) +{ + mdns_srv_item_t *s = mdns_utils_get_services(); + while (s) { + if (instance) { + if (_mdns_service_match_instance(s->service, instance, service, proto, hostname)) { + return s; + } + } else { + if (_mdns_service_match(s->service, service, proto, hostname)) { + return s; + } + } + s = s->next; + } + return NULL; +} + +bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instance, const char *service, + const char *proto, const char *hostname) +{ + // service and proto must be supplied, if not this instance won't match + if (!service || !proto) { + return false; + } + // instance==NULL -> _mdns_instance_name_match() will check the default instance + // hostname==NULL -> matches if instance, service and proto matches + return !strcasecmp(srv->service, service) && _mdns_instance_name_match(srv->instance, instance) && + !strcasecmp(srv->proto, proto) && (mdns_utils_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); +} + +const char *_mdns_get_default_instance_name(void) +{ + const char* instance = mdns_utils_get_instance(); + if (mdns_utils_str_null_or_empty(instance)) { + return instance; + } + + const char* host = mdns_utils_get_global_hostname(); + if (mdns_utils_str_null_or_empty(host)) { + return host; + } + return NULL; +} + +/** + * @brief Get the service name of a service + */ +const char *_mdns_get_service_instance_name(const mdns_service_t *service) +{ + if (service && !mdns_utils_str_null_or_empty(service->instance)) { + return service->instance; + } + + return _mdns_get_default_instance_name(); +} + + +bool _mdns_instance_name_match(const char *lhs, const char *rhs) +{ + if (lhs == NULL) { + lhs = _mdns_get_default_instance_name(); + } + if (rhs == NULL) { + rhs = _mdns_get_default_instance_name(); + } + return !strcasecmp(lhs, rhs); +} + +/** + * @brief Add result to browse, only add when the result is a new one. + */ +esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r) +{ + mdns_browse_result_sync_t *sync_r = sync_browse->sync_result; + while (sync_r) { + if (sync_r->result == r) { + break; + } + sync_r = sync_r->next; + } + if (!sync_r) { + // Do not find, need to add the result to the list + mdns_browse_result_sync_t *new = (mdns_browse_result_sync_t *)mdns_mem_malloc(sizeof(mdns_browse_result_sync_t)); + + if (!new) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + new->result = r; + new->next = sync_browse->sync_result; + sync_browse->sync_result = new; + } + return ESP_OK; +} + +mdns_ip_addr_t *copy_address_list(const mdns_ip_addr_t *address_list) +{ + mdns_ip_addr_t *head = NULL; + mdns_ip_addr_t *tail = NULL; + while (address_list != NULL) { + mdns_ip_addr_t *addr = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); + if (addr == NULL) { + free_address_list(head); + return NULL; + } + addr->addr = address_list->addr; + addr->next = NULL; + if (head == NULL) { + head = addr; + tail = addr; + } else { + tail->next = addr; + tail = tail->next; + } + address_list = address_list->next; + } + return head; +} + +void free_address_list(mdns_ip_addr_t *address_list) +{ + while (address_list != NULL) { + mdns_ip_addr_t *next = address_list->next; + mdns_mem_free(address_list); + address_list = next; + } +} diff --git a/components/mdns/private_include/mdns_utils.h b/components/mdns/private_include/mdns_utils.h new file mode 100644 index 0000000000..2d3722a03a --- /dev/null +++ b/components/mdns/private_include/mdns_utils.h @@ -0,0 +1,264 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "mdns_private.h" + +#define MDNS_UTILS_DEFAULT_DOMAIN "local" +#define _MDNS_SIZEOF_IP6_ADDR (MDNS_ANSWER_AAAA_SIZE) + +/** + * @brief read uint16_t from a packet + * @param packet the packet + * @param index index in the packet where the value starts + * + * @return the value + */ +static inline uint16_t mdns_utils_read_u16(const uint8_t *packet, uint16_t index) +{ + return (uint16_t)(packet[index]) << 8 | packet[index + 1]; +} + +/** + * @brief read uint32_t from a packet + * @param packet the packet + * @param index index in the packet where the value starts + * + * @return the value + */ +static inline uint32_t mdns_utils_read_u32(const uint8_t *packet, uint16_t index) +{ + return (uint32_t)(packet[index]) << 24 | (uint32_t)(packet[index + 1]) << 16 | (uint32_t)(packet[index + 2]) << 8 | packet[index + 3]; +} + +static inline bool mdns_utils_str_null_or_empty(const char *str) +{ + return (str == NULL || *str == 0); +} + +static inline void _mdns_result_update_ttl(mdns_result_t *r, uint32_t ttl) +{ + r->ttl = r->ttl < ttl ? r->ttl : ttl; +} + + +const uint8_t *_mdns_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, size_t packet_len); + +const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len); + +const char *mdns_utils_get_global_hostname(void); +mdns_srv_item_t *mdns_utils_get_services(void); +mdns_host_item_t *mdns_utils_get_hosts(void); +void mdns_utils_set_global_hostname(const char *hostname); +const char *mdns_utils_get_instance(void); +void mdns_utils_set_instance(const char *instance); +mdns_search_once_t *mdns_utils_get_search(void); +mdns_search_once_t *mdns_utils_get_search(void); +mdns_browse_t *mdns_utils_get_browse(void); +mdns_tx_packet_t *mdns_utils_get_tx_packet(void); +bool mdns_utils_is_probing(mdns_rx_packet_t *packet); +bool mdns_utils_after_probing(mdns_rx_packet_t *packet); +void mdns_utils_probe_failed(mdns_rx_packet_t *packet); +void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe); +void _mdns_restart_all_pcbs_no_instance(void); +void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); +void _mdns_restart_all_pcbs(void); +void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); +void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip); +bool _ipv6_address_is_zero(esp_ip6_addr_t ip6); +void _mdns_search_finish(mdns_search_once_t *search); + + +void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet); + +bool _hostname_is_ours(const char *hostname); +bool _mdns_service_match(const mdns_service_t *srv, const char *service, const char *proto, + const char *hostname); +mdns_srv_item_t *_mdns_get_service_item(const char *service, const char *proto, const char *hostname); + +mdns_srv_item_t *_mdns_get_service_item_instance(const char *instance, const char *service, const char *proto, + const char *hostname); + +bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instance, const char *service, + const char *proto, const char *hostname); + +bool _mdns_instance_name_match(const char *lhs, const char *rhs); + +const char *_mdns_get_default_instance_name(void); +const char *_mdns_get_service_instance_name(const mdns_service_t *service); +esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r); +mdns_ip_addr_t *copy_address_list(const mdns_ip_addr_t *address_list); +void free_address_list(mdns_ip_addr_t *address_list); + +//--------------------------------------------- +/** + * @brief appends byte in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 1 on success + */ +static inline uint8_t _mdns_append_u8(uint8_t *packet, uint16_t *index, uint8_t value) +{ + if (*index >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + packet[*index] = value; + *index += 1; + return 1; +} + +/** + * @brief appends uint16_t in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 2 on success + */ +static inline uint8_t _mdns_append_u16(uint8_t *packet, uint16_t *index, uint16_t value) +{ + if ((*index + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, (value >> 8) & 0xFF); + _mdns_append_u8(packet, index, value & 0xFF); + return 2; +} + +/** + * @brief appends uint32_t in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 4 on success + */ +static inline uint8_t _mdns_append_u32(uint8_t *packet, uint16_t *index, uint32_t value) +{ + if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, (value >> 24) & 0xFF); + _mdns_append_u8(packet, index, (value >> 16) & 0xFF); + _mdns_append_u8(packet, index, (value >> 8) & 0xFF); + _mdns_append_u8(packet, index, value & 0xFF); + return 4; +} + +/** + * @brief appends answer type, class, ttl and data length to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param type answer type + * @param ttl answer ttl + * + * @return length of added data: 0 on error or 10 on success + */ +static inline uint8_t _mdns_append_type(uint8_t *packet, uint16_t *index, uint8_t type, bool flush, uint32_t ttl) +{ + if ((*index + 10) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + uint16_t mdns_class = MDNS_CLASS_IN; + if (flush) { + mdns_class = MDNS_CLASS_IN_FLUSH_CACHE; + } + if (type == MDNS_ANSWER_PTR) { + _mdns_append_u16(packet, index, MDNS_TYPE_PTR); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_TXT) { + _mdns_append_u16(packet, index, MDNS_TYPE_TXT); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_SRV) { + _mdns_append_u16(packet, index, MDNS_TYPE_SRV); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_A) { + _mdns_append_u16(packet, index, MDNS_TYPE_A); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_AAAA) { + _mdns_append_u16(packet, index, MDNS_TYPE_AAAA); + _mdns_append_u16(packet, index, mdns_class); + } else { + return 0; + } + _mdns_append_u32(packet, index, ttl); + _mdns_append_u16(packet, index, 0); + return 10; +} + +static inline uint8_t _mdns_append_string_with_len(uint8_t *packet, uint16_t *index, const char *string, uint8_t len) +{ + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, string, len); + *index += len; + return len + 1; +} + +/** + * @brief appends single string to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param string the string to append + * + * @return length of added data: 0 on error or length of the string + 1 on success + */ +static inline uint8_t _mdns_append_string(uint8_t *packet, uint16_t *index, const char *string) +{ + uint8_t len = strlen(string); + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, string, len); + *index += len; + return len + 1; +} + +/** + * @brief appends one TXT record ("key=value" or "key") + * + * @param packet MDNS packet + * @param index offset in the packet + * @param txt one txt record + * + * @return length of added data: length of the added txt value + 1 on success + * 0 if data won't fit the packet + * -1 if invalid TXT entry + */ +static inline int append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt) +{ + if (txt == NULL || txt->key == NULL) { + return -1; + } + size_t key_len = strlen(txt->key); + size_t len = key_len + txt->value_len + (txt->value ? 1 : 0); + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, txt->key, key_len); + if (txt->value) { + packet[*index + key_len] = '='; + memcpy(packet + *index + key_len + 1, txt->value, txt->value_len); + } + *index += len; + return len + 1; +} + + +/// +mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if); +void _mdns_dup_interface(mdns_if_t tcpip_if); + +esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync); diff --git a/components/mdns/tests/test_afl_fuzz_host/Makefile b/components/mdns/tests/test_afl_fuzz_host/Makefile index 6f45edb9df..6f6b16c0fc 100644 --- a/components/mdns/tests/test_afl_fuzz_host/Makefile +++ b/components/mdns/tests/test_afl_fuzz_host/Makefile @@ -51,7 +51,7 @@ else endif CPP=$(CC) LD=$(CC) -OBJECTS=esp32_mock.o mdns.o test.o esp_netif_mock.o +OBJECTS=esp32_mock.o mdns.o test.o esp_netif_mock.o mdns_utils.o mdns_packet.o OS := $(shell uname) ifeq ($(OS),Darwin) @@ -71,6 +71,10 @@ mdns.o: ../../mdns.c @echo "[CC] $<" @$(CC) $(CFLAGS) -include mdns_mock.h $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@ +%.o: ../../%.c + @echo "[CC] $<" + @$(CC) $(CFLAGS) -include mdns_mock.h -c $< -o $@ + $(TEST_NAME): $(OBJECTS) @echo "[LD] $@" @$(LD) $(OBJECTS) -o $@ $(LDLIBS) From 83a59da0bd4066c9db52dfa1693cde43940326e6 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Sat, 8 Mar 2025 10:54:41 +0100 Subject: [PATCH 02/27] feat(mdns): Make mdns-debug a separate module --- components/mdns/CMakeLists.txt | 2 +- components/mdns/mdns.c | 332 +----------------- components/mdns/mdns_debug.c | 321 +++++++++++++++++ components/mdns/mdns_packet.c | 34 +- components/mdns/private_include/mdns_debug.h | 44 +++ .../mdns/private_include/mdns_private.h | 5 - .../tests/test_afl_fuzz_host/esp32_mock.h | 4 + 7 files changed, 381 insertions(+), 361 deletions(-) create mode 100644 components/mdns/mdns_debug.c create mode 100644 components/mdns/private_include/mdns_debug.h diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 9ab5dc883b..b67df9d33d 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -12,7 +12,7 @@ endif() set(MDNS_MEMORY "mdns_mem_caps.c") -set(MDNS_CORE "mdns.c" "mdns_packet.c" "mdns_utils.c") +set(MDNS_CORE "mdns.c" "mdns_packet.c" "mdns_utils.c" "mdns_debug.c") #set(MDNS_CORE "mdns.c" ) idf_build_get_property(target IDF_TARGET) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index aa8352440c..95eb780174 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -18,6 +18,7 @@ #include "mdns_networking.h" #include "mdns_mem_caps.h" #include "mdns_utils.h" +#include "mdns_debug.h" static void _mdns_browse_item_free(mdns_browse_t *browse); static esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse); @@ -41,10 +42,6 @@ static void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface); #include "esp_wifi.h" #endif -#ifdef MDNS_ENABLE_DEBUG -void mdns_debug_packet(const uint8_t *data, size_t len); -#endif - #ifndef ARRAY_SIZE #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) #endif @@ -66,30 +63,6 @@ static volatile TaskHandle_t _mdns_service_task_handle = NULL; static SemaphoreHandle_t _mdns_service_semaphore = NULL; static StackType_t *_mdns_stack_buffer; -//static void _mdns_search_finish_done(void); -//static mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *search, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -//static mdns_browse_t *_mdns_browse_find_from(mdns_browse_t *b, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -//static void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, -// uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); -//static void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, -// mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); -//static void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, -// mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, -// uint32_t ttl, mdns_browse_sync_t *out_sync_browse); -#ifdef MDNS_ENABLE_DEBUG -void debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t); -void debug_printf_browse_result_all(mdns_result_t *r_t); -#endif // MDNS_ENABLE_DEBUG -//static void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, -// mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); -//static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, -// mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); -//static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, -// size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, -// uint32_t ttl); -//static mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, -// const char *service_type, const char *proto, mdns_if_t tcpip_if, -// mdns_ip_protocol_t ip_protocol, uint32_t ttl); static bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], size_t services_len, bool flush, bool bye); static bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye); @@ -1228,20 +1201,7 @@ static void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p) } _mdns_set_u16(packet, MDNS_HEAD_ADDITIONAL_OFFSET, count); -#ifdef MDNS_ENABLE_DEBUG - _mdns_dbg_printf("\nTX[%lu][%lu]: ", (unsigned long)p->tcpip_if, (unsigned long)p->ip_protocol); -#ifdef CONFIG_LWIP_IPV4 - if (p->dst.type == ESP_IPADDR_TYPE_V4) { - _mdns_dbg_printf("To: " IPSTR ":%u, ", IP2STR(&p->dst.u_addr.ip4), p->port); - } -#endif -#ifdef CONFIG_LWIP_IPV6 - if (p->dst.type == ESP_IPADDR_TYPE_V6) { - _mdns_dbg_printf("To: " IPV6STR ":%u, ", IPV62STR(p->dst.u_addr.ip6), p->port); - } -#endif - mdns_debug_packet(packet, index); -#endif + DBG_TX_PACKET(p, packet, index); _mdns_udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); } @@ -3575,14 +3535,12 @@ static esp_err_t _mdns_service_task_start(void) if (!_mdns_service_task_handle) { ESP_GOTO_ON_ERROR(_mdns_task_create_with_caps(), err_stop_timer, TAG, "Failed to start the mDNS service task"); -#ifdef MDNS_ENABLE_DEBUG -#if !CONFIG_IDF_TARGET_LINUX +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) && !CONFIG_IDF_TARGET_LINUX StackType_t *mdns_debug_stack_buffer; StaticTask_t *mdns_debug_task_buffer; xTaskGetStaticBuffers(_mdns_service_task_handle, &mdns_debug_stack_buffer, &mdns_debug_task_buffer); - _mdns_dbg_printf("mdns_debug_stack_buffer:%p mdns_debug_task_buffer:%p\n", mdns_debug_stack_buffer, mdns_debug_task_buffer); + ESP_LOGD(TAG, "mdns_debug_stack_buffer:%p mdns_debug_task_buffer:%p\n", mdns_debug_stack_buffer, mdns_debug_task_buffer); #endif // CONFIG_IDF_TARGET_LINUX -#endif // MDNS_ENABLE_DEBUG } MDNS_SERVICE_UNLOCK(); return ret; @@ -5089,234 +5047,6 @@ esp_err_t mdns_query_aaaa(const char *name, uint32_t timeout, esp_ip6_addr_t *ad } #endif /* CONFIG_LWIP_IPV6 */ -#ifdef MDNS_ENABLE_DEBUG - -void mdns_debug_packet(const uint8_t *data, size_t len) -{ - static mdns_name_t n; - mdns_header_t header; - const uint8_t *content = data + MDNS_HEAD_LEN; - uint32_t t = xTaskGetTickCount() * portTICK_PERIOD_MS; - mdns_name_t *name = &n; - memset(name, 0, sizeof(mdns_name_t)); - - _mdns_dbg_printf("Packet[%" PRIu32 "]: ", t); - - header.id = mdns_utils_read_u16(data, MDNS_HEAD_ID_OFFSET); - header.flags = mdns_utils_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); - header.questions = mdns_utils_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); - header.answers = mdns_utils_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); - header.servers = mdns_utils_read_u16(data, MDNS_HEAD_SERVERS_OFFSET); - header.additional = mdns_utils_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); - - _mdns_dbg_printf("%s", - (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE) ? "AUTHORITATIVE\n" : - (header.flags == MDNS_FLAGS_DISTRIBUTED) ? "DISTRIBUTED\n" : - (header.flags == 0) ? "\n" : " " - ); - if (header.flags && header.flags != MDNS_FLAGS_QR_AUTHORITATIVE) { - _mdns_dbg_printf("0x%04X\n", header.flags); - } - - if (header.questions) { - uint8_t qs = header.questions; - - while (qs--) { - content = _mdns_parse_fqdn(data, content, name, len); - if (!content || content + MDNS_CLASS_OFFSET + 1 >= data + len) { - header.answers = 0; - header.additional = 0; - header.servers = 0; - _mdns_dbg_printf("ERROR: parse header questions\n"); - break; - } - - uint16_t type = mdns_utils_read_u16(content, MDNS_TYPE_OFFSET); - uint16_t mdns_class = mdns_utils_read_u16(content, MDNS_CLASS_OFFSET); - bool unicast = !!(mdns_class & 0x8000); - mdns_class &= 0x7FFF; - content = content + 4; - - _mdns_dbg_printf(" Q: "); - if (unicast) { - _mdns_dbg_printf("*U* "); - } - if (type == MDNS_TYPE_PTR) { - _mdns_dbg_printf("%s.%s%s.%s.%s. PTR ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); - } else if (type == MDNS_TYPE_SRV) { - _mdns_dbg_printf("%s.%s%s.%s.%s. SRV ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); - } else if (type == MDNS_TYPE_TXT) { - _mdns_dbg_printf("%s.%s%s.%s.%s. TXT ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); - } else if (type == MDNS_TYPE_A) { - _mdns_dbg_printf("%s.%s. A ", name->host, name->domain); - } else if (type == MDNS_TYPE_AAAA) { - _mdns_dbg_printf("%s.%s. AAAA ", name->host, name->domain); - } else if (type == MDNS_TYPE_NSEC) { - _mdns_dbg_printf("%s.%s%s.%s.%s. NSEC ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); - } else if (type == MDNS_TYPE_ANY) { - _mdns_dbg_printf("%s.%s%s.%s.%s. ANY ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); - } else { - _mdns_dbg_printf("%s.%s%s.%s.%s. %04X ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain, type); - } - - if (mdns_class == 0x0001) { - _mdns_dbg_printf("IN"); - } else { - _mdns_dbg_printf("%04X", mdns_class); - } - _mdns_dbg_printf("\n"); - } - } - - if (header.answers || header.servers || header.additional) { - uint16_t recordIndex = 0; - - while (content < (data + len)) { - - content = _mdns_parse_fqdn(data, content, name, len); - if (!content) { - _mdns_dbg_printf("ERROR: parse mdns records\n"); - break; - } - - uint16_t type = mdns_utils_read_u16(content, MDNS_TYPE_OFFSET); - uint16_t mdns_class = mdns_utils_read_u16(content, MDNS_CLASS_OFFSET); - uint32_t ttl = mdns_utils_read_u32(content, MDNS_TTL_OFFSET); - uint16_t data_len = mdns_utils_read_u16(content, MDNS_LEN_OFFSET); - const uint8_t *data_ptr = content + MDNS_DATA_OFFSET; - bool flush = !!(mdns_class & 0x8000); - mdns_class &= 0x7FFF; - - content = data_ptr + data_len; - if (content > (data + len)) { - _mdns_dbg_printf("ERROR: content length overflow\n"); - break; - } - - mdns_parsed_record_type_t record_type = MDNS_ANSWER; - - if (recordIndex >= (header.answers + header.servers)) { - record_type = MDNS_EXTRA; - } else if (recordIndex >= (header.answers)) { - record_type = MDNS_NS; - } - recordIndex++; - - if (record_type == MDNS_EXTRA) { - _mdns_dbg_printf(" X"); - } else if (record_type == MDNS_NS) { - _mdns_dbg_printf(" S"); - } else { - _mdns_dbg_printf(" A"); - } - - if (type == MDNS_TYPE_PTR) { - _mdns_dbg_printf(": %s%s%s.%s.%s. PTR ", name->host, name->host[0] ? "." : "", name->service, name->proto, name->domain); - } else if (type == MDNS_TYPE_SRV) { - _mdns_dbg_printf(": %s.%s.%s.%s. SRV ", name->host, name->service, name->proto, name->domain); - } else if (type == MDNS_TYPE_TXT) { - _mdns_dbg_printf(": %s.%s.%s.%s. TXT ", name->host, name->service, name->proto, name->domain); - } else if (type == MDNS_TYPE_A) { - _mdns_dbg_printf(": %s.%s. A ", name->host, name->domain); - } else if (type == MDNS_TYPE_AAAA) { - _mdns_dbg_printf(": %s.%s. AAAA ", name->host, name->domain); - } else if (type == MDNS_TYPE_NSEC) { - _mdns_dbg_printf(": %s.%s.%s.%s. NSEC ", name->host, name->service, name->proto, name->domain); - } else if (type == MDNS_TYPE_ANY) { - _mdns_dbg_printf(": %s.%s.%s.%s. ANY ", name->host, name->service, name->proto, name->domain); - } else if (type == MDNS_TYPE_OPT) { - _mdns_dbg_printf(": . OPT "); - } else { - _mdns_dbg_printf(": %s.%s.%s.%s. %04X ", name->host, name->service, name->proto, name->domain, type); - } - - if (mdns_class == 0x0001) { - _mdns_dbg_printf("IN "); - } else { - _mdns_dbg_printf("%04X ", mdns_class); - } - if (flush) { - _mdns_dbg_printf("FLUSH "); - } - _mdns_dbg_printf("%" PRIu32, ttl); - _mdns_dbg_printf("[%u] ", data_len); - if (type == MDNS_TYPE_PTR) { - if (!_mdns_parse_fqdn(data, data_ptr, name, len)) { - _mdns_dbg_printf("ERROR: parse PTR\n"); - continue; - } - _mdns_dbg_printf("%s.%s.%s.%s.\n", name->host, name->service, name->proto, name->domain); - } else if (type == MDNS_TYPE_SRV) { - if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { - _mdns_dbg_printf("ERROR: parse SRV\n"); - continue; - } - uint16_t priority = mdns_utils_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); - uint16_t weight = mdns_utils_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); - uint16_t port = mdns_utils_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); - _mdns_dbg_printf("%u %u %u %s.%s.\n", priority, weight, port, name->host, name->domain); - } else if (type == MDNS_TYPE_TXT) { - uint16_t i = 0, y; - while (i < data_len) { - uint8_t partLen = data_ptr[i++]; - if ((i + partLen) > data_len) { - _mdns_dbg_printf("ERROR: parse TXT\n"); - break; - } - char txt[partLen + 1]; - for (y = 0; y < partLen; y++) { - char d = data_ptr[i++]; - txt[y] = d; - } - txt[partLen] = 0; - _mdns_dbg_printf("%s", txt); - if (i < data_len) { - _mdns_dbg_printf("; "); - } - } - _mdns_dbg_printf("\n"); - } else if (type == MDNS_TYPE_AAAA) { - esp_ip6_addr_t ip6; - memcpy(&ip6, data_ptr, sizeof(esp_ip6_addr_t)); - _mdns_dbg_printf(IPV6STR "\n", IPV62STR(ip6)); - } else if (type == MDNS_TYPE_A) { - esp_ip4_addr_t ip; - memcpy(&ip, data_ptr, sizeof(esp_ip4_addr_t)); - _mdns_dbg_printf(IPSTR "\n", IP2STR(&ip)); - } else if (type == MDNS_TYPE_NSEC) { - const uint8_t *old_ptr = data_ptr; - const uint8_t *new_ptr = _mdns_parse_fqdn(data, data_ptr, name, len); - if (new_ptr) { - _mdns_dbg_printf("%s.%s.%s.%s. ", name->host, name->service, name->proto, name->domain); - size_t diff = new_ptr - old_ptr; - data_len -= diff; - data_ptr = new_ptr; - } - size_t i; - for (i = 0; i < data_len; i++) { - _mdns_dbg_printf(" %02x", data_ptr[i]); - } - _mdns_dbg_printf("\n"); - } else if (type == MDNS_TYPE_OPT) { - uint16_t opCode = mdns_utils_read_u16(data_ptr, 0); - uint16_t opLen = mdns_utils_read_u16(data_ptr, 2); - _mdns_dbg_printf(" Code: %04x Data[%u]:", opCode, opLen); - size_t i; - for (i = 4; i < data_len; i++) { - _mdns_dbg_printf(" %02x", data_ptr[i]); - } - _mdns_dbg_printf("\n"); - } else { - size_t i; - for (i = 0; i < data_len; i++) { - _mdns_dbg_printf(" %02x", data_ptr[i]); - } - _mdns_dbg_printf("\n"); - } - } - } -} -#endif /* MDNS_ENABLE_DEBUG */ /** * @brief Browse sync result action @@ -5529,9 +5259,7 @@ static void _mdns_browse_sync(mdns_browse_sync_t *browse_sync) mdns_browse_result_sync_t *sync_result = browse_sync->sync_result; while (sync_result) { mdns_result_t *result = sync_result->result; -#ifdef MDNS_ENABLE_DEBUG - debug_printf_browse_result(result, browse_sync->browse); -#endif + DBG_BROWSE_RESULTS(result, browse_sync->browse); browse->notifier(result); if (result->ttl == 0) { queueDetach(mdns_result_t, browse->result, result); @@ -5542,53 +5270,3 @@ static void _mdns_browse_sync(mdns_browse_sync_t *browse_sync) sync_result = sync_result->next; } } - -#ifdef MDNS_ENABLE_DEBUG -void _debug_printf_result(mdns_result_t *r_t) -{ - mdns_ip_addr_t *r_a = NULL; - int addr_count = 0; - _mdns_dbg_printf("result esp_netif: %p\n", r_t->esp_netif); - _mdns_dbg_printf("result ip_protocol: %d\n", r_t->ip_protocol); - _mdns_dbg_printf("result hostname: %s\n", _str_null_or_empty(r_t->hostname) ? "NULL" : r_t->hostname); - _mdns_dbg_printf("result instance_name: %s\n", _str_null_or_empty(r_t->instance_name) ? "NULL" : r_t->instance_name); - _mdns_dbg_printf("result service_type: %s\n", _str_null_or_empty(r_t->service_type) ? "NULL" : r_t->service_type); - _mdns_dbg_printf("result proto: %s\n", _str_null_or_empty(r_t->proto) ? "NULL" : r_t->proto); - _mdns_dbg_printf("result port: %d\n", r_t->port); - _mdns_dbg_printf("result ttl: %" PRIu32 "\n", r_t->ttl); - for (int i = 0; i < r_t->txt_count; i++) { - _mdns_dbg_printf("result txt item%d, key: %s, value: %s\n", i, r_t->txt[i].key, r_t->txt[i].value); - } - r_a = r_t->addr; - while (r_a) { -#ifdef CONFIG_LWIP_IPV4 - if (r_a->addr.type == ESP_IPADDR_TYPE_V4) { - _mdns_dbg_printf("Addr%d: " IPSTR "\n", addr_count++, IP2STR(&r_a->addr.u_addr.ip4)); - } -#endif -#ifdef CONFIG_LWIP_IPV6 - if (r_a->addr.type == ESP_IPADDR_TYPE_V6) { - _mdns_dbg_printf("Addr%d: " IPV6STR "\n", addr_count++, IPV62STR(r_a->addr.u_addr.ip6)); - } -#endif - r_a = r_a->next; - } -} - -void debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t) -{ - _mdns_dbg_printf("----------------sync browse %s.%s result---------------\n", b_t->service, b_t->proto); - _mdns_dbg_printf("browse pointer: %p\n", b_t); - _debug_printf_result(r_t); -} - -void debug_printf_browse_result_all(mdns_result_t *r_t) -{ - int count = 0; - while (r_t) { - _mdns_dbg_printf("----------------result %d---------------\n", count++); - _debug_printf_result(r_t); - r_t = r_t->next; - } -} -#endif // MDNS_ENABLE_DEBUG diff --git a/components/mdns/mdns_debug.c b/components/mdns/mdns_debug.c new file mode 100644 index 0000000000..04c96ea84e --- /dev/null +++ b/components/mdns/mdns_debug.c @@ -0,0 +1,321 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "sdkconfig.h" +#include "mdns_private.h" +#include "mdns_utils.h" + +#define dbg_printf(...) printf(__VA_ARGS__) + +void static dbg_packet(const uint8_t *data, size_t len) +{ + static mdns_name_t n; + mdns_header_t header; + const uint8_t *content = data + MDNS_HEAD_LEN; + uint32_t t = xTaskGetTickCount() * portTICK_PERIOD_MS; + mdns_name_t *name = &n; + memset(name, 0, sizeof(mdns_name_t)); + + dbg_printf("Packet[%" PRIu32 "]: ", t); + + header.id = mdns_utils_read_u16(data, MDNS_HEAD_ID_OFFSET); + header.flags = mdns_utils_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); + header.questions = mdns_utils_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); + header.answers = mdns_utils_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); + header.servers = mdns_utils_read_u16(data, MDNS_HEAD_SERVERS_OFFSET); + header.additional = mdns_utils_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); + + dbg_printf("%s", + (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE) ? "AUTHORITATIVE\n" : + (header.flags == MDNS_FLAGS_DISTRIBUTED) ? "DISTRIBUTED\n" : + (header.flags == 0) ? "\n" : " " + ); + if (header.flags && header.flags != MDNS_FLAGS_QR_AUTHORITATIVE) { + dbg_printf("0x%04X\n", header.flags); + } + + if (header.questions) { + uint8_t qs = header.questions; + + while (qs--) { + content = _mdns_parse_fqdn(data, content, name, len); + if (!content || content + MDNS_CLASS_OFFSET + 1 >= data + len) { + header.answers = 0; + header.additional = 0; + header.servers = 0; + dbg_printf("ERROR: parse header questions\n"); + break; + } + + uint16_t type = mdns_utils_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t mdns_class = mdns_utils_read_u16(content, MDNS_CLASS_OFFSET); + bool unicast = !!(mdns_class & 0x8000); + mdns_class &= 0x7FFF; + content = content + 4; + + dbg_printf(" Q: "); + if (unicast) { + dbg_printf("*U* "); + } + if (type == MDNS_TYPE_PTR) { + dbg_printf("%s.%s%s.%s.%s. PTR ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_SRV) { + dbg_printf("%s.%s%s.%s.%s. SRV ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_TXT) { + dbg_printf("%s.%s%s.%s.%s. TXT ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_A) { + dbg_printf("%s.%s. A ", name->host, name->domain); + } else if (type == MDNS_TYPE_AAAA) { + dbg_printf("%s.%s. AAAA ", name->host, name->domain); + } else if (type == MDNS_TYPE_NSEC) { + dbg_printf("%s.%s%s.%s.%s. NSEC ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_ANY) { + dbg_printf("%s.%s%s.%s.%s. ANY ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); + } else { + dbg_printf("%s.%s%s.%s.%s. %04X ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain, type); + } + + if (mdns_class == 0x0001) { + dbg_printf("IN"); + } else { + dbg_printf("%04X", mdns_class); + } + dbg_printf("\n"); + } + } + + if (header.answers || header.servers || header.additional) { + uint16_t recordIndex = 0; + + while (content < (data + len)) { + + content = _mdns_parse_fqdn(data, content, name, len); + if (!content) { + dbg_printf("ERROR: parse mdns records\n"); + break; + } + + uint16_t type = mdns_utils_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t mdns_class = mdns_utils_read_u16(content, MDNS_CLASS_OFFSET); + uint32_t ttl = mdns_utils_read_u32(content, MDNS_TTL_OFFSET); + uint16_t data_len = mdns_utils_read_u16(content, MDNS_LEN_OFFSET); + const uint8_t *data_ptr = content + MDNS_DATA_OFFSET; + bool flush = !!(mdns_class & 0x8000); + mdns_class &= 0x7FFF; + + content = data_ptr + data_len; + if (content > (data + len)) { + dbg_printf("ERROR: content length overflow\n"); + break; + } + + mdns_parsed_record_type_t record_type = MDNS_ANSWER; + + if (recordIndex >= (header.answers + header.servers)) { + record_type = MDNS_EXTRA; + } else if (recordIndex >= (header.answers)) { + record_type = MDNS_NS; + } + recordIndex++; + + if (record_type == MDNS_EXTRA) { + dbg_printf(" X"); + } else if (record_type == MDNS_NS) { + dbg_printf(" S"); + } else { + dbg_printf(" A"); + } + + if (type == MDNS_TYPE_PTR) { + dbg_printf(": %s%s%s.%s.%s. PTR ", name->host, name->host[0] ? "." : "", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_SRV) { + dbg_printf(": %s.%s.%s.%s. SRV ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_TXT) { + dbg_printf(": %s.%s.%s.%s. TXT ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_A) { + dbg_printf(": %s.%s. A ", name->host, name->domain); + } else if (type == MDNS_TYPE_AAAA) { + dbg_printf(": %s.%s. AAAA ", name->host, name->domain); + } else if (type == MDNS_TYPE_NSEC) { + dbg_printf(": %s.%s.%s.%s. NSEC ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_ANY) { + dbg_printf(": %s.%s.%s.%s. ANY ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_OPT) { + dbg_printf(": . OPT "); + } else { + dbg_printf(": %s.%s.%s.%s. %04X ", name->host, name->service, name->proto, name->domain, type); + } + + if (mdns_class == 0x0001) { + dbg_printf("IN "); + } else { + dbg_printf("%04X ", mdns_class); + } + if (flush) { + dbg_printf("FLUSH "); + } + dbg_printf("%" PRIu32, ttl); + dbg_printf("[%u] ", data_len); + if (type == MDNS_TYPE_PTR) { + if (!_mdns_parse_fqdn(data, data_ptr, name, len)) { + dbg_printf("ERROR: parse PTR\n"); + continue; + } + dbg_printf("%s.%s.%s.%s.\n", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_SRV) { + if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { + dbg_printf("ERROR: parse SRV\n"); + continue; + } + uint16_t priority = mdns_utils_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); + uint16_t weight = mdns_utils_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); + uint16_t port = mdns_utils_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); + dbg_printf("%u %u %u %s.%s.\n", priority, weight, port, name->host, name->domain); + } else if (type == MDNS_TYPE_TXT) { + uint16_t i = 0, y; + while (i < data_len) { + uint8_t partLen = data_ptr[i++]; + if ((i + partLen) > data_len) { + dbg_printf("ERROR: parse TXT\n"); + break; + } + char txt[partLen + 1]; + for (y = 0; y < partLen; y++) { + char d = data_ptr[i++]; + txt[y] = d; + } + txt[partLen] = 0; + dbg_printf("%s", txt); + if (i < data_len) { + dbg_printf("; "); + } + } + dbg_printf("\n"); + } else if (type == MDNS_TYPE_AAAA) { + esp_ip6_addr_t ip6; + memcpy(&ip6, data_ptr, sizeof(esp_ip6_addr_t)); + dbg_printf(IPV6STR "\n", IPV62STR(ip6)); + } else if (type == MDNS_TYPE_A) { + esp_ip4_addr_t ip; + memcpy(&ip, data_ptr, sizeof(esp_ip4_addr_t)); + dbg_printf(IPSTR "\n", IP2STR(&ip)); + } else if (type == MDNS_TYPE_NSEC) { + const uint8_t *old_ptr = data_ptr; + const uint8_t *new_ptr = _mdns_parse_fqdn(data, data_ptr, name, len); + if (new_ptr) { + dbg_printf("%s.%s.%s.%s. ", name->host, name->service, name->proto, name->domain); + size_t diff = new_ptr - old_ptr; + data_len -= diff; + data_ptr = new_ptr; + } + size_t i; + for (i = 0; i < data_len; i++) { + dbg_printf(" %02x", data_ptr[i]); + } + dbg_printf("\n"); + } else if (type == MDNS_TYPE_OPT) { + uint16_t opCode = mdns_utils_read_u16(data_ptr, 0); + uint16_t opLen = mdns_utils_read_u16(data_ptr, 2); + dbg_printf(" Code: %04x Data[%u]:", opCode, opLen); + size_t i; + for (i = 4; i < data_len; i++) { + dbg_printf(" %02x", data_ptr[i]); + } + dbg_printf("\n"); + } else { + size_t i; + for (i = 0; i < data_len; i++) { + dbg_printf(" %02x", data_ptr[i]); + } + dbg_printf("\n"); + } + } + } +} + +void mdns_debug_tx_packet(mdns_tx_packet_t *p, uint8_t packet[MDNS_MAX_PACKET_SIZE], uint16_t index) +{ + dbg_printf("\nTX[%lu][%lu]: ", (unsigned long)p->tcpip_if, (unsigned long)p->ip_protocol); +#ifdef CONFIG_LWIP_IPV4 + if (p->dst.type == ESP_IPADDR_TYPE_V4) { + dbg_printf("To: " IPSTR ":%u, ", IP2STR(&p->dst.u_addr.ip4), p->port); + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (p->dst.type == ESP_IPADDR_TYPE_V6) { + dbg_printf("To: " IPV6STR ":%u, ", IPV62STR(p->dst.u_addr.ip6), p->port); + } +#endif + dbg_packet(packet, index); +} + +void mdns_debug_rx_packet(mdns_rx_packet_t *packet, const uint8_t* data, uint16_t len) +{ + dbg_printf("\nRX[%lu][%lu]: ", (unsigned long)packet->tcpip_if, (unsigned long)packet->ip_protocol); +#ifdef CONFIG_LWIP_IPV4 + if (packet->src.type == ESP_IPADDR_TYPE_V4) { + dbg_printf("From: " IPSTR ":%u, To: " IPSTR ", ", IP2STR(&packet->src.u_addr.ip4), packet->src_port, IP2STR(&packet->dest.u_addr.ip4)); + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (packet->src.type == ESP_IPADDR_TYPE_V6) { + dbg_printf("From: " IPV6STR ":%u, To: " IPV6STR ", ", IPV62STR(packet->src.u_addr.ip6), packet->src_port, IPV62STR(packet->dest.u_addr.ip6)); + } +#endif + dbg_packet(data, len); +} + +static void dbg_printf_result(mdns_result_t *r_t) +{ + mdns_ip_addr_t *r_a = NULL; + int addr_count = 0; + dbg_printf("result esp_netif: %p\n", r_t->esp_netif); + dbg_printf("result ip_protocol: %d\n", r_t->ip_protocol); + dbg_printf("result hostname: %s\n", mdns_utils_str_null_or_empty(r_t->hostname) ? "NULL" : r_t->hostname); + dbg_printf("result instance_name: %s\n", mdns_utils_str_null_or_empty(r_t->instance_name) ? "NULL" : r_t->instance_name); + dbg_printf("result service_type: %s\n", mdns_utils_str_null_or_empty(r_t->service_type) ? "NULL" : r_t->service_type); + dbg_printf("result proto: %s\n", mdns_utils_str_null_or_empty(r_t->proto) ? "NULL" : r_t->proto); + dbg_printf("result port: %d\n", r_t->port); + dbg_printf("result ttl: %" PRIu32 "\n", r_t->ttl); + for (int i = 0; i < r_t->txt_count; i++) { + dbg_printf("result txt item%d, key: %s, value: %s\n", i, r_t->txt[i].key, r_t->txt[i].value); + } + r_a = r_t->addr; + while (r_a) { +#ifdef CONFIG_LWIP_IPV4 + if (r_a->addr.type == ESP_IPADDR_TYPE_V4) { + dbg_printf("Addr%d: " IPSTR "\n", addr_count++, IP2STR(&r_a->addr.u_addr.ip4)); + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (r_a->addr.type == ESP_IPADDR_TYPE_V6) { + dbg_printf("Addr%d: " IPV6STR "\n", addr_count++, IPV62STR(r_a->addr.u_addr.ip6)); + } +#endif + r_a = r_a->next; + } +} + +void mdns_debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t) +{ + dbg_printf("----------------sync browse %s.%s result---------------\n", b_t->service, b_t->proto); + dbg_printf("browse pointer: %p\n", b_t); + dbg_printf_result(r_t); +} + +void mdns_debug_printf_browse_result_all(mdns_result_t *r_t) +{ + int count = 0; + while (r_t) { + dbg_printf("----------------result %d---------------\n", count++); + dbg_printf_result(r_t); + r_t = r_t->next; + } +} diff --git a/components/mdns/mdns_packet.c b/components/mdns/mdns_packet.c index 54b723a093..73b13a0572 100644 --- a/components/mdns/mdns_packet.c +++ b/components/mdns/mdns_packet.c @@ -11,15 +11,10 @@ #include "mdns_mem_caps.h" #include "esp_log.h" #include "mdns_utils.h" +#include "mdns_debug.h" static const char *TAG = "mdns_packet"; -#ifdef MDNS_ENABLE_DEBUG -void mdns_debug_packet(const uint8_t *data, size_t len); -void debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t); -void debug_printf_browse_result_all(mdns_result_t *r_t); -#endif - /** * @brief Check if parsed name is discovery */ @@ -1279,20 +1274,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) char *browse_result_proto = NULL; mdns_browse_sync_t *out_sync_browse = NULL; -#ifdef MDNS_ENABLE_DEBUG - _mdns_dbg_printf("\nRX[%lu][%lu]: ", (unsigned long)packet->tcpip_if, (unsigned long)packet->ip_protocol); -#ifdef CONFIG_LWIP_IPV4 - if (packet->src.type == ESP_IPADDR_TYPE_V4) { - _mdns_dbg_printf("From: " IPSTR ":%u, To: " IPSTR ", ", IP2STR(&packet->src.u_addr.ip4), packet->src_port, IP2STR(&packet->dest.u_addr.ip4)); - } -#endif -#ifdef CONFIG_LWIP_IPV6 - if (packet->src.type == ESP_IPADDR_TYPE_V6) { - _mdns_dbg_printf("From: " IPV6STR ":%u, To: " IPV6STR ", ", IPV62STR(packet->src.u_addr.ip6), packet->src_port, IPV62STR(packet->dest.u_addr.ip6)); - } -#endif - mdns_debug_packet(data, len); -#endif + DBG_RX_PACKET(packet, data, len); #ifndef CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES // Check if the packet wasn't sent by us @@ -1888,15 +1870,11 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) _mdns_create_answer_from_parsed_packet(parsed_packet); } if (out_sync_browse) { -#ifdef MDNS_ENABLE_DEBUG - _mdns_dbg_printf("Browse %s%s total result:", out_sync_browse->browse->service, out_sync_browse->browse->proto); - debug_printf_browse_result_all(out_sync_browse->browse->result); -#endif // MDNS_ENABLE_DEBUG + DBG_BROWSE_RESULTS_WITH_MSG(out_sync_browse->browse->result, + "Browse %s%s total result:", out_sync_browse->browse->service, out_sync_browse->browse->proto); if (out_sync_browse->sync_result) { -#ifdef MDNS_ENABLE_DEBUG - _mdns_dbg_printf("Changed result:"); - debug_printf_browse_result_all(out_sync_browse->sync_result->result); -#endif // MDNS_ENABLE_DEBUG + DBG_BROWSE_RESULTS_WITH_MSG(out_sync_browse->sync_result->result, + "Changed result:"); _mdns_sync_browse_action(ACTION_BROWSE_SYNC, out_sync_browse); } else { mdns_mem_free(out_sync_browse); diff --git a/components/mdns/private_include/mdns_debug.h b/components/mdns/private_include/mdns_debug.h new file mode 100644 index 0000000000..1de04b24ed --- /dev/null +++ b/components/mdns/private_include/mdns_debug.h @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "mdns_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_MDNS_ENABLE_DEBUG_PRINTS + +#define DBG_BROWSE_RESULTS(result, browse) mdns_debug_printf_browse_result(result, browse) + +#define DBG_BROWSE_RESULTS_WITH_MSG(result, ...) do { \ + printf(__VA_ARGS__); \ + mdns_debug_printf_browse_result_all(result); \ + } while(0) + +#define DBG_TX_PACKET(packet, data, len) mdns_debug_tx_packet(packet, data, len) + +#define DBG_RX_PACKET(packet, data, len) mdns_debug_rx_packet(packet, data, len) + +void mdns_debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t); +void mdns_debug_printf_browse_result_all(mdns_result_t *r_t); +void mdns_debug_tx_packet(mdns_tx_packet_t *p, uint8_t packet[MDNS_MAX_PACKET_SIZE], uint16_t index); +void mdns_debug_rx_packet(mdns_rx_packet_t *packet, const uint8_t* data, uint16_t len); + +#else + +#define DBG_BROWSE_RESULTS(result, browse) +#define DBG_BROWSE_RESULTS_WITH_MSG(result, ...) +#define DBG_TX_PACKET(packet, data, len) +#define DBG_RX_PACKET(packet, data, len) + +#endif // CONFIG_MDNS_ENABLE_DEBUG_PRINTS + +#ifdef __cplusplus +} +#endif diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index ce4c96b631..149177833a 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -16,11 +16,6 @@ #include "esp_timer.h" #include "esp_system.h" -#ifdef CONFIG_MDNS_ENABLE_DEBUG_PRINTS -#define MDNS_ENABLE_DEBUG -#define _mdns_dbg_printf(...) printf(__VA_ARGS__) -#endif - /** Number of predefined interfaces */ #ifndef CONFIG_MDNS_PREDEF_NETIF_STA #define CONFIG_MDNS_PREDEF_NETIF_STA 0 diff --git a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h index 68a3461058..a8193625ad 100644 --- a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h @@ -139,4 +139,8 @@ TaskHandle_t xTaskGetCurrentTaskHandle(void); void xTaskNotifyGive(TaskHandle_t task); BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time); +static inline void xTaskGetStaticBuffers(void *pvTaskBuffer, void *pvStackBuffer, void *pvTaskTCB) +{ +} + #endif //_ESP32_COMPAT_H_ From 650256711784ad36d03a0ce7958526f14e3c4a53 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Sun, 9 Mar 2025 15:07:21 +0100 Subject: [PATCH 03/27] feat(mdns): Separate packet-tx and browse --- components/mdns/CMakeLists.txt | 3 +- components/mdns/mdns.c | 1958 ++--------------- components/mdns/mdns_browser.c | 126 +- components/mdns/mdns_netif.c | 16 + components/mdns/mdns_querier.c | 38 +- components/mdns/mdns_send.c | 1568 +++++++++++++ components/mdns/private_include/mdns_browse.h | 27 + components/mdns/private_include/mdns_netif.h | 19 + .../mdns/private_include/mdns_querier.h | 19 + components/mdns/private_include/mdns_send.h | 34 + components/mdns/private_include/mdns_utils.h | 7 +- .../mdns/tests/test_afl_fuzz_host/Makefile | 2 +- 12 files changed, 2000 insertions(+), 1817 deletions(-) create mode 100644 components/mdns/mdns_netif.c create mode 100644 components/mdns/mdns_send.c create mode 100644 components/mdns/private_include/mdns_browse.h create mode 100644 components/mdns/private_include/mdns_netif.h create mode 100644 components/mdns/private_include/mdns_querier.h create mode 100644 components/mdns/private_include/mdns_send.h diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index b67df9d33d..22745eb6fa 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -12,7 +12,8 @@ endif() set(MDNS_MEMORY "mdns_mem_caps.c") -set(MDNS_CORE "mdns.c" "mdns_packet.c" "mdns_utils.c" "mdns_debug.c") +set(MDNS_CORE "mdns.c" "mdns_packet.c" "mdns_utils.c" "mdns_debug.c" "mdns_browser.c" "mdns_send.c" "mdns_netif.c" + "mdns_querier.c") #set(MDNS_CORE "mdns.c" ) idf_build_get_property(target IDF_TARGET) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 95eb780174..0198abc518 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -19,14 +19,11 @@ #include "mdns_mem_caps.h" #include "mdns_utils.h" #include "mdns_debug.h" +#include "mdns_browse.h" +#include "mdns_netif.h" +#include "mdns_send.h" +#include "mdns_querier.h" -static void _mdns_browse_item_free(mdns_browse_t *browse); -static esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse); -esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync); -static void _mdns_browse_sync(mdns_browse_sync_t *browse_sync); -static void _mdns_browse_finish(mdns_browse_t *browse); -static void _mdns_browse_add(mdns_browse_t *browse); -static void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface); #if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH #include "esp_eth.h" @@ -50,8 +47,8 @@ static void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface); // since the ip6_addr_t is defined in lwip and depends on using IPv6 zones #define _MDNS_SIZEOF_IP6_ADDR (MDNS_ANSWER_AAAA_SIZE) -static const char *MDNS_DEFAULT_DOMAIN = "local"; -static const char *MDNS_SUB_STR = "_sub"; +//static const char *MDNS_DEFAULT_DOMAIN = "local"; +//static const char *MDNS_SUB_STR = "_sub"; mdns_server_t *_mdns_server = NULL; static mdns_host_item_t *_mdns_host_list = NULL; @@ -63,12 +60,12 @@ static volatile TaskHandle_t _mdns_service_task_handle = NULL; static SemaphoreHandle_t _mdns_service_semaphore = NULL; static StackType_t *_mdns_stack_buffer; -static bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], size_t services_len, bool flush, bool bye); -static bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye); + +//static bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye); static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); -static void _mdns_query_results_free(mdns_result_t *results); +//static void _mdns_query_results_free(mdns_result_t *results); typedef enum { MDNS_IF_STA = 0, @@ -194,6 +191,25 @@ static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *esp_netif) return MDNS_MAX_INTERFACES; } +/** + * @brief Check if interface is duplicate (two interfaces on the same subnet) + */ +bool _mdns_if_is_dup(mdns_if_t tcpip_if) +{ + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if == MDNS_MAX_INTERFACES) { + return false; + } + if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP + || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state == PCB_DUP + || _mdns_server->interfaces[other_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP + || _mdns_server->interfaces[other_if].pcbs[MDNS_IP_PROTOCOL_V6].state == PCB_DUP + ) { + return true; + } + return false; +} + const char *mdns_utils_get_global_hostname(void) { return _mdns_server ? _mdns_server->hostname : NULL; @@ -209,6 +225,12 @@ mdns_host_item_t *mdns_utils_get_hosts(void) return _mdns_host_list; } +mdns_host_item_t *mdns_utils_get_selfhost(void) +{ + return &_mdns_self_host; +} + + void mdns_utils_set_global_hostname(const char *hostname) { if (_mdns_server) { @@ -245,6 +267,11 @@ mdns_browse_t *mdns_utils_get_browse(void) return _mdns_server->browse; } +bool is_mdns_server(void) +{ + return _mdns_server != NULL; +} + static inline bool _str_null_or_empty(const char *str) { return (str == NULL || *str == 0); @@ -255,6 +282,16 @@ mdns_tx_packet_t *mdns_utils_get_tx_packet(void) return _mdns_server->tx_queue_head; } +bool mdns_utils_is_pcb_after_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + return _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state > PCB_INIT; +} + +bool mdns_utils_is_pcb_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + return _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state == PCB_DUP; +} + bool mdns_utils_is_probing(mdns_rx_packet_t *packet) { return _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running; @@ -272,20 +309,7 @@ void mdns_utils_probe_failed(mdns_rx_packet_t *packet) -static mdns_host_item_t *mdns_get_host_item(const char *hostname) -{ - if (hostname == NULL || strcasecmp(hostname, _mdns_server->hostname) == 0) { - return &_mdns_self_host; - } - mdns_host_item_t *host = _mdns_host_list; - while (host != NULL) { - if (strcasecmp(host->hostname, hostname) == 0) { - return host; - } - host = host->next; - } - return NULL; -} + static bool _mdns_can_add_more_services(void) { @@ -324,585 +348,6 @@ esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) return ESP_OK; } - - - - - - - - -/** - * @brief sets uint16_t value in a packet - * - * @param packet MDNS packet - * @param index offset of uint16_t value - * @param value the value to set - */ -static inline void _mdns_set_u16(uint8_t *packet, uint16_t index, uint16_t value) -{ - if ((index + 1) >= MDNS_MAX_PACKET_SIZE) { - return; - } - packet[index] = (value >> 8) & 0xFF; - packet[index + 1] = value & 0xFF; -} - - - -#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES -static inline int append_single_str(uint8_t *packet, uint16_t *index, const char *str, int len) -{ - if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - if (!_mdns_append_u8(packet, index, len)) { - return 0; - } - memcpy(packet + *index, str, len); - *index += len; - return *index; -} - -/** - * @brief appends FQDN to a packet from hostname separated by dots. This API works the same way as - * _mdns_append_fqdn(), but refrains from DNS compression (as it's mainly used for IP addresses (many short items), - * where we gain very little (or compression even gets counter-productive mainly for IPv6 addresses) - * - * @param packet MDNS packet - * @param index offset in the packet - * @param name name representing FQDN in '.' separated parts - * @param last true if appending the last part (domain, typically "arpa") - * - * @return length of added data: 0 on error or length on success - */ -static uint16_t append_fqdn_dots(uint8_t *packet, uint16_t *index, const char *name, bool last) -{ - int len = strlen(name); - char *host = (char *)name; - char *end = host; - char *start = host; - do { - end = memchr(start, '.', host + len - start); - end = end ? end : host + len; - int part_len = end - start; - if (!append_single_str(packet, index, start, part_len)) { - return 0; - } - start = ++end; - } while (end < name + len); - - if (!append_single_str(packet, index, "arpa", sizeof("arpa") - 1)) { - return 0; - } - - //empty string so terminate - if (!_mdns_append_u8(packet, index, 0)) { - return 0; - } - return *index; -} -#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ - -/** - * @brief appends FQDN to a packet, incrementing the index and - * compressing the output if previous occurrence of the string (or part of it) has been found - * - * @param packet MDNS packet - * @param index offset in the packet - * @param strings string array containing the parts of the FQDN - * @param count number of strings in the array - * - * @return length of added data: 0 on error or length on success - */ -static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char *strings[], uint8_t count, size_t packet_len) -{ - if (!count) { - //empty string so terminate - return _mdns_append_u8(packet, index, 0); - } - static char buf[MDNS_NAME_BUF_LEN]; - uint8_t len = strlen(strings[0]); - //try to find first the string length in the packet (if it exists) - uint8_t *len_location = (uint8_t *)memchr(packet, (char)len, *index); - while (len_location) { - mdns_name_t name; - //check if the string after len_location is the string that we are looking for - if (memcmp(len_location + 1, strings[0], len)) { //not continuing with our string -search_next: - //try and find the length byte further in the packet - len_location = (uint8_t *)memchr(len_location + 1, (char)len, *index - (len_location + 1 - packet)); - continue; - } - //seems that we might have found the string that we are looking for - //read the destination into name and compare - name.parts = 0; - name.sub = 0; - name.invalid = false; - name.host[0] = 0; - name.service[0] = 0; - name.proto[0] = 0; - name.domain[0] = 0; - const uint8_t *content = _mdns_read_fqdn(packet, len_location, &name, buf, packet_len); - if (!content) { - //not a readable fqdn? - goto search_next; // could be our unfinished fqdn, continue searching - } - if (name.parts == count) { - uint8_t i; - for (i = 0; i < count; i++) { - if (strcasecmp(strings[i], (const char *)&name + (i * (MDNS_NAME_BUF_LEN)))) { - //not our string! let's search more - goto search_next; - } - } - //we actually have found the string - break; - } else { - goto search_next; - } - } - //string is not yet in the packet, so let's add it - if (!len_location) { - uint8_t written = _mdns_append_string(packet, index, strings[0]); - if (!written) { - return 0; - } - //run the same for the other strings in the name - return written + _mdns_append_fqdn(packet, index, &strings[1], count - 1, packet_len); - } - - //we have found the string so let's insert a pointer to it instead - uint16_t offset = len_location - packet; - offset |= MDNS_NAME_REF; - return _mdns_append_u16(packet, index, offset); -} - -/** - * @brief appends PTR record for service to a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param server the server that is hosting the service - * @param service the service to add record for - * - * @return length of added data: 0 on error or length on success - */ -static uint16_t _mdns_append_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, const char *service, const char *proto, bool flush, bool bye) -{ - const char *str[4]; - uint16_t record_length = 0; - uint8_t part_length; - - if (service == NULL) { - return 0; - } - - str[0] = instance; - str[1] = service; - str[2] = proto; - str[3] = MDNS_DEFAULT_DOMAIN; - - part_length = _mdns_append_fqdn(packet, index, str + 1, 3, MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - record_length += part_length; - - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL); - if (!part_length) { - return 0; - } - record_length += part_length; - - uint16_t data_len_location = *index - 2; - part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - _mdns_set_u16(packet, data_len_location, part_length); - record_length += part_length; - return record_length; -} - -/** - * @brief appends PTR record for a subtype to a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param instance the service instance name - * @param subtype the service subtype - * @param proto the service protocol - * @param flush whether to set the flush flag - * @param bye whether to set the bye flag - * - * @return length of added data: 0 on error or length on success - */ -static uint16_t _mdns_append_subtype_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, - const char *subtype, const char *service, const char *proto, bool flush, - bool bye) -{ - const char *subtype_str[5] = {subtype, MDNS_SUB_STR, service, proto, MDNS_DEFAULT_DOMAIN}; - const char *instance_str[4] = {instance, service, proto, MDNS_DEFAULT_DOMAIN}; - uint16_t record_length = 0; - uint8_t part_length; - - if (service == NULL) { - return 0; - } - - part_length = _mdns_append_fqdn(packet, index, subtype_str, ARRAY_SIZE(subtype_str), MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - record_length += part_length; - - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL); - if (!part_length) { - return 0; - } - record_length += part_length; - - uint16_t data_len_location = *index - 2; - part_length = _mdns_append_fqdn(packet, index, instance_str, ARRAY_SIZE(instance_str), MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - _mdns_set_u16(packet, data_len_location, part_length); - record_length += part_length; - return record_length; -} - -/** - * @brief appends DNS-SD PTR record for service to a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param server the server that is hosting the service - * @param service the service to add record for - * - * @return length of added data: 0 on error or length on success - */ -static uint16_t _mdns_append_sdptr_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) -{ - const char *str[3]; - const char *sd_str[4]; - uint16_t record_length = 0; - uint8_t part_length; - - if (service == NULL) { - return 0; - } - - sd_str[0] = (char *)"_services"; - sd_str[1] = (char *)"_dns-sd"; - sd_str[2] = (char *)"_udp"; - sd_str[3] = MDNS_DEFAULT_DOMAIN; - - str[0] = service->service; - str[1] = service->proto; - str[2] = MDNS_DEFAULT_DOMAIN; - - part_length = _mdns_append_fqdn(packet, index, sd_str, 4, MDNS_MAX_PACKET_SIZE); - - record_length += part_length; - - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, flush, MDNS_ANSWER_PTR_TTL); - if (!part_length) { - return 0; - } - record_length += part_length; - - uint16_t data_len_location = *index - 2; - part_length = _mdns_append_fqdn(packet, index, str, 3, MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - _mdns_set_u16(packet, data_len_location, part_length); - record_length += part_length; - return record_length; -} - -/** - * @brief appends TXT record for service to a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param server the server that is hosting the service - * @param service the service to add record for - * - * @return length of added data: 0 on error or length on success - */ -static uint16_t _mdns_append_txt_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) -{ - const char *str[4]; - uint16_t record_length = 0; - uint8_t part_length; - - if (service == NULL) { - return 0; - } - - str[0] = _mdns_get_service_instance_name(service); - str[1] = service->service; - str[2] = service->proto; - str[3] = MDNS_DEFAULT_DOMAIN; - - if (!str[0]) { - return 0; - } - - part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - record_length += part_length; - - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_TXT, flush, bye ? 0 : MDNS_ANSWER_TXT_TTL); - if (!part_length) { - return 0; - } - record_length += part_length; - - uint16_t data_len_location = *index - 2; - uint16_t data_len = 0; - - mdns_txt_linked_item_t *txt = service->txt; - while (txt) { - int l = append_one_txt_record_entry(packet, index, txt); - if (l > 0) { - data_len += l; - } else if (l == 0) { // TXT entry won't fit into the mdns packet - return 0; - } - txt = txt->next; - } - if (!data_len) { - data_len = 1; - packet[*index] = 0; - *index = *index + 1; - } - _mdns_set_u16(packet, data_len_location, data_len); - record_length += data_len; - return record_length; -} - -/** - * @brief appends SRV record for service to a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param server the server that is hosting the service - * @param service the service to add record for - * - * @return length of added data: 0 on error or length on success - */ -static uint16_t _mdns_append_srv_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) -{ - const char *str[4]; - uint16_t record_length = 0; - uint8_t part_length; - - if (service == NULL) { - return 0; - } - - str[0] = _mdns_get_service_instance_name(service); - str[1] = service->service; - str[2] = service->proto; - str[3] = MDNS_DEFAULT_DOMAIN; - - if (!str[0]) { - return 0; - } - - part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - record_length += part_length; - - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_SRV, flush, bye ? 0 : MDNS_ANSWER_SRV_TTL); - if (!part_length) { - return 0; - } - record_length += part_length; - - uint16_t data_len_location = *index - 2; - - part_length = 0; - part_length += _mdns_append_u16(packet, index, service->priority); - part_length += _mdns_append_u16(packet, index, service->weight); - part_length += _mdns_append_u16(packet, index, service->port); - if (part_length != 6) { - return 0; - } - - if (service->hostname) { - str[0] = service->hostname; - } else { - str[0] = _mdns_server->hostname; - } - str[1] = MDNS_DEFAULT_DOMAIN; - - if (_str_null_or_empty(str[0])) { - return 0; - } - - part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - _mdns_set_u16(packet, data_len_location, part_length + 6); - - record_length += part_length + 6; - return record_length; -} - -#ifdef CONFIG_LWIP_IPV4 -/** - * @brief appends A record to a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param hostname the hostname address to add - * @param ip the IP address to add - * - * @return length of added data: 0 on error or length on success - */ -static uint16_t _mdns_append_a_record(uint8_t *packet, uint16_t *index, const char *hostname, uint32_t ip, bool flush, bool bye) -{ - const char *str[2]; - uint16_t record_length = 0; - uint8_t part_length; - - str[0] = hostname; - str[1] = MDNS_DEFAULT_DOMAIN; - - if (_str_null_or_empty(str[0])) { - return 0; - } - - part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - record_length += part_length; - - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_A, flush, bye ? 0 : MDNS_ANSWER_A_TTL); - if (!part_length) { - return 0; - } - record_length += part_length; - - uint16_t data_len_location = *index - 2; - - if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, ip & 0xFF); - _mdns_append_u8(packet, index, (ip >> 8) & 0xFF); - _mdns_append_u8(packet, index, (ip >> 16) & 0xFF); - _mdns_append_u8(packet, index, (ip >> 24) & 0xFF); - _mdns_set_u16(packet, data_len_location, 4); - - record_length += 4; - return record_length; -} -#endif /* CONFIG_LWIP_IPV4 */ - -#ifdef CONFIG_LWIP_IPV6 -/** - * @brief appends AAAA record to a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param hostname the hostname address to add - * @param ipv6 the IPv6 address to add - * - * @return length of added data: 0 on error or length on success - */ -static uint16_t _mdns_append_aaaa_record(uint8_t *packet, uint16_t *index, const char *hostname, uint8_t *ipv6, bool flush, bool bye) -{ - const char *str[2]; - uint16_t record_length = 0; - uint8_t part_length; - - str[0] = hostname; - str[1] = MDNS_DEFAULT_DOMAIN; - - if (_str_null_or_empty(str[0])) { - return 0; - } - - - part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - record_length += part_length; - - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_AAAA, flush, bye ? 0 : MDNS_ANSWER_AAAA_TTL); - if (!part_length) { - return 0; - } - record_length += part_length; - - uint16_t data_len_location = *index - 2; - - if ((*index + MDNS_ANSWER_AAAA_SIZE) > MDNS_MAX_PACKET_SIZE) { - return 0; - } - - part_length = MDNS_ANSWER_AAAA_SIZE; - memcpy(packet + *index, ipv6, part_length); - *index += part_length; - _mdns_set_u16(packet, data_len_location, part_length); - record_length += part_length; - return record_length; -} -#endif - -/** - * @brief Append question to packet - */ -static uint16_t _mdns_append_question(uint8_t *packet, uint16_t *index, mdns_out_question_t *q) -{ - uint8_t part_length; -#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES - if (q->host && (strstr(q->host, "in-addr") || strstr(q->host, "ip6"))) { - part_length = append_fqdn_dots(packet, index, q->host, false); - if (!part_length) { - return 0; - } - } else -#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ - { - const char *str[4]; - uint8_t str_index = 0; - if (q->host) { - str[str_index++] = q->host; - } - if (q->service) { - str[str_index++] = q->service; - } - if (q->proto) { - str[str_index++] = q->proto; - } - if (q->domain) { - str[str_index++] = q->domain; - } - part_length = _mdns_append_fqdn(packet, index, str, str_index, MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - } - - part_length += _mdns_append_u16(packet, index, q->type); - part_length += _mdns_append_u16(packet, index, q->unicast ? 0x8001 : 0x0001); - return part_length; -} - /** * @brief Helper to get either ETH or STA if the other is provided * Used when two interfaces are on the same subnet @@ -915,30 +360,11 @@ mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if) return MDNS_MAX_INTERFACES; } +#ifdef CONFIG_LWIP_IPV6 /** - * @brief Check if interface is duplicate (two interfaces on the same subnet) + * @brief Check if IPv6 address is NULL */ -static bool _mdns_if_is_dup(mdns_if_t tcpip_if) -{ - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); - if (other_if == MDNS_MAX_INTERFACES) { - return false; - } - if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP - || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state == PCB_DUP - || _mdns_server->interfaces[other_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP - || _mdns_server->interfaces[other_if].pcbs[MDNS_IP_PROTOCOL_V6].state == PCB_DUP - ) { - return true; - } - return false; -} - -#ifdef CONFIG_LWIP_IPV6 -/** - * @brief Check if IPv6 address is NULL - */ -bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) +bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) { uint8_t i; uint8_t *data = (uint8_t *)ip6.addr; @@ -951,931 +377,142 @@ bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) } #endif /* CONFIG_LWIP_IPV6 */ -static uint8_t _mdns_append_host_answer(uint8_t *packet, uint16_t *index, mdns_host_item_t *host, - uint8_t address_type, bool flush, bool bye) -{ - mdns_ip_addr_t *addr = host->address_list; - uint8_t num_records = 0; - - while (addr != NULL) { - if (addr->addr.type == address_type) { -#ifdef CONFIG_LWIP_IPV4 - if (address_type == ESP_IPADDR_TYPE_V4 && - _mdns_append_a_record(packet, index, host->hostname, addr->addr.u_addr.ip4.addr, flush, bye) <= 0) { - break; - } -#endif /* CONFIG_LWIP_IPV4 */ -#ifdef CONFIG_LWIP_IPV6 - if (address_type == ESP_IPADDR_TYPE_V6 && - _mdns_append_aaaa_record(packet, index, host->hostname, (uint8_t *)addr->addr.u_addr.ip6.addr, flush, - bye) <= 0) { - break; - } -#endif /* CONFIG_LWIP_IPV6 */ - num_records++; - } - addr = addr->next; - } - return num_records; -} - -#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES -/** - * @brief Appends reverse lookup PTR record - */ -static uint8_t _mdns_append_reverse_ptr_record(uint8_t *packet, uint16_t *index, const char *name) -{ - if (strstr(name, "in-addr") == NULL && strstr(name, "ip6") == NULL) { - return 0; - } - - if (!append_fqdn_dots(packet, index, name, false)) { - return 0; - } - - if (!_mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, 10 /* TTL set to 10s*/)) { - return 0; - } - - uint16_t data_len_location = *index - 2; /* store the position of size (2=16bis) of this record */ - const char *str[2] = { _mdns_self_host.hostname, MDNS_DEFAULT_DOMAIN }; - - int part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); - if (!part_length) { - return 0; - } - - _mdns_set_u16(packet, data_len_location, part_length); - return 1; /* appending only 1 record */ -} -#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ - -/** - * @brief Append PTR answers to packet - * - * @return number of answers added to the packet - */ -static uint8_t _mdns_append_service_ptr_answers(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, - bool bye) -{ - uint8_t appended_answers = 0; - - if (_mdns_append_ptr_record(packet, index, _mdns_get_service_instance_name(service), service->service, - service->proto, flush, bye) <= 0) { - return appended_answers; - } - appended_answers++; - - mdns_subtype_t *subtype = service->subtype; - while (subtype) { - appended_answers += - (_mdns_append_subtype_ptr_record(packet, index, _mdns_get_service_instance_name(service), subtype->subtype, - service->service, service->proto, flush, bye) > 0); - subtype = subtype->next; - } - - return appended_answers; -} - - -/** - * @brief Append answer to packet - * - * @return number of answers added to the packet - */ -static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_answer_t *answer, mdns_if_t tcpip_if) -{ - if (answer->host) { - bool is_host_valid = (&_mdns_self_host == answer->host); - mdns_host_item_t *target_host = _mdns_host_list; - while (target_host && !is_host_valid) { - if (target_host == answer->host) { - is_host_valid = true; - } - target_host = target_host->next; - } - if (!is_host_valid) { - return 0; - } - } - - if (answer->type == MDNS_TYPE_PTR) { - if (answer->service) { - return _mdns_append_service_ptr_answers(packet, index, answer->service, answer->flush, answer->bye); -#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES - } else if (answer->host && answer->host->hostname && - (strstr(answer->host->hostname, "in-addr") || strstr(answer->host->hostname, "ip6"))) { - return _mdns_append_reverse_ptr_record(packet, index, answer->host->hostname) > 0; -#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ - } else { - return _mdns_append_ptr_record(packet, index, - answer->custom_instance, answer->custom_service, answer->custom_proto, - answer->flush, answer->bye) > 0; - } - } else if (answer->type == MDNS_TYPE_SRV) { - return _mdns_append_srv_record(packet, index, answer->service, answer->flush, answer->bye) > 0; - } else if (answer->type == MDNS_TYPE_TXT) { - return _mdns_append_txt_record(packet, index, answer->service, answer->flush, answer->bye) > 0; - } else if (answer->type == MDNS_TYPE_SDPTR) { - return _mdns_append_sdptr_record(packet, index, answer->service, answer->flush, answer->bye) > 0; - } -#ifdef CONFIG_LWIP_IPV4 - else if (answer->type == MDNS_TYPE_A) { - if (answer->host == &_mdns_self_host) { - esp_netif_ip_info_t if_ip_info; - if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state != PCB_DUP) { - return 0; - } - if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { - return 0; - } - if (_mdns_append_a_record(packet, index, _mdns_server->hostname, if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { - return 0; - } - if (!_mdns_if_is_dup(tcpip_if)) { - return 1; - } - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); - if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &if_ip_info)) { - return 1; - } - if (_mdns_append_a_record(packet, index, _mdns_server->hostname, if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { - return 2; - } - return 1; - } else if (answer->host != NULL) { - return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V4, answer->flush, answer->bye); - } - } -#endif /* CONFIG_LWIP_IPV4 */ -#ifdef CONFIG_LWIP_IPV6 - else if (answer->type == MDNS_TYPE_AAAA) { - if (answer->host == &_mdns_self_host) { - struct esp_ip6_addr if_ip6s[NETIF_IPV6_MAX_NUMS]; - uint8_t count = 0; - if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state != PCB_DUP) { - return 0; - } - count = esp_netif_get_all_ip6(_mdns_get_esp_netif(tcpip_if), if_ip6s); - assert(count <= NETIF_IPV6_MAX_NUMS); - for (int i = 0; i < count; i++) { - if (_ipv6_address_is_zero(if_ip6s[i])) { - return 0; - } - if (_mdns_append_aaaa_record(packet, index, _mdns_server->hostname, (uint8_t *)if_ip6s[i].addr, - answer->flush, answer->bye) <= 0) { - return 0; - } - } - if (!_mdns_if_is_dup(tcpip_if)) { - return count; - } - - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); - struct esp_ip6_addr other_ip6; - if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &other_ip6)) { - return count; - } - if (_mdns_append_aaaa_record(packet, index, _mdns_server->hostname, (uint8_t *)other_ip6.addr, - answer->flush, answer->bye) > 0) { - return 1 + count; - } - return count; - } else if (answer->host != NULL) { - return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V6, answer->flush, - answer->bye); - } - } -#endif /* CONFIG_LWIP_IPV6 */ - return 0; -} - -/** - * @brief sends a packet - * - * @param p the packet - */ -static void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p) -{ - static uint8_t packet[MDNS_MAX_PACKET_SIZE]; - uint16_t index = MDNS_HEAD_LEN; - memset(packet, 0, MDNS_HEAD_LEN); - mdns_out_question_t *q; - mdns_out_answer_t *a; - uint8_t count; - - _mdns_set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, p->flags); - _mdns_set_u16(packet, MDNS_HEAD_ID_OFFSET, p->id); - - count = 0; - q = p->questions; - while (q) { - if (_mdns_append_question(packet, &index, q)) { - count++; - } - q = q->next; - } - _mdns_set_u16(packet, MDNS_HEAD_QUESTIONS_OFFSET, count); - - count = 0; - a = p->answers; - while (a) { - count += _mdns_append_answer(packet, &index, a, p->tcpip_if); - a = a->next; - } - _mdns_set_u16(packet, MDNS_HEAD_ANSWERS_OFFSET, count); - - count = 0; - a = p->servers; - while (a) { - count += _mdns_append_answer(packet, &index, a, p->tcpip_if); - a = a->next; - } - _mdns_set_u16(packet, MDNS_HEAD_SERVERS_OFFSET, count); - - count = 0; - a = p->additional; - while (a) { - count += _mdns_append_answer(packet, &index, a, p->tcpip_if); - a = a->next; - } - _mdns_set_u16(packet, MDNS_HEAD_ADDITIONAL_OFFSET, count); - - DBG_TX_PACKET(p, packet, index); - - _mdns_udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); -} - -/** - * @brief frees a packet - * - * @param packet the packet - */ -static void _mdns_free_tx_packet(mdns_tx_packet_t *packet) -{ - if (!packet) { - return; - } - mdns_out_question_t *q = packet->questions; - while (q) { - mdns_out_question_t *next = q->next; - if (q->own_dynamic_memory) { - mdns_mem_free((char *)q->host); - mdns_mem_free((char *)q->service); - mdns_mem_free((char *)q->proto); - mdns_mem_free((char *)q->domain); - } - mdns_mem_free(q); - q = next; - } - queueFree(mdns_out_answer_t, packet->answers); - queueFree(mdns_out_answer_t, packet->servers); - queueFree(mdns_out_answer_t, packet->additional); - mdns_mem_free(packet); -} - -/** - * @brief schedules a packet to be sent after given milliseconds - * - * @param packet the packet - * @param ms_after number of milliseconds after which the packet should be dispatched - */ -static void _mdns_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after) -{ - if (!packet) { - return; - } - packet->send_at = (xTaskGetTickCount() * portTICK_PERIOD_MS) + ms_after; - packet->next = NULL; - if (!_mdns_server->tx_queue_head || _mdns_server->tx_queue_head->send_at > packet->send_at) { - packet->next = _mdns_server->tx_queue_head; - _mdns_server->tx_queue_head = packet; - return; - } - mdns_tx_packet_t *q = _mdns_server->tx_queue_head; - while (q->next && q->next->send_at <= packet->send_at) { - q = q->next; - } - packet->next = q->next; - q->next = packet; -} - -/** - * @brief free all packets scheduled for sending - */ -static void _mdns_clear_tx_queue_head(void) -{ - mdns_tx_packet_t *q; - while (_mdns_server->tx_queue_head) { - q = _mdns_server->tx_queue_head; - _mdns_server->tx_queue_head = _mdns_server->tx_queue_head->next; - _mdns_free_tx_packet(q); - } -} - -/** - * @brief clear packets scheduled for sending on a specific interface - * - * @param tcpip_if the interface - * @param ip_protocol pcb type V4/V6 - */ -static void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_tx_packet_t *q, * p; - while (_mdns_server->tx_queue_head && _mdns_server->tx_queue_head->tcpip_if == tcpip_if && _mdns_server->tx_queue_head->ip_protocol == ip_protocol) { - q = _mdns_server->tx_queue_head; - _mdns_server->tx_queue_head = _mdns_server->tx_queue_head->next; - _mdns_free_tx_packet(q); - } - if (_mdns_server->tx_queue_head) { - q = _mdns_server->tx_queue_head; - while (q->next) { - if (q->next->tcpip_if == tcpip_if && q->next->ip_protocol == ip_protocol) { - p = q->next; - q->next = p->next; - _mdns_free_tx_packet(p); - } else { - q = q->next; - } - } - } -} - -/** - * @brief get the next packet scheduled for sending on a specific interface - * - * @param tcpip_if the interface - * @param ip_protocol pcb type V4/V6 - */ -static mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_tx_packet_t *q = _mdns_server->tx_queue_head; - while (q) { - if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol) { - return q; - } - q = q->next; - } - return NULL; -} - - -/** - * @brief Remove and free answer from answer list (destination) - */ -static void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service) -{ - mdns_out_answer_t *d = *destination; - if (!d) { - return; - } - mdns_srv_item_t s = {NULL, NULL}; - if (!service) { - service = &s; - } - if (d->type == type && d->service == service->service) { - *destination = d->next; - mdns_mem_free(d); - return; - } - while (d->next) { - mdns_out_answer_t *a = d->next; - if (a->type == type && a->service == service->service) { - d->next = a->next; - mdns_mem_free(a); - return; - } - d = d->next; - } -} - -/** - * @brief Allocate new answer and add it to answer list (destination) - */ -static bool _mdns_alloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_service_t *service, - mdns_host_item_t *host, bool flush, bool bye) -{ - mdns_out_answer_t *d = *destination; - while (d) { - if (d->type == type && d->service == service && d->host == host) { - return true; - } - d = d->next; - } - - mdns_out_answer_t *a = (mdns_out_answer_t *)mdns_mem_malloc(sizeof(mdns_out_answer_t)); - if (!a) { - HOOK_MALLOC_FAILED; - return false; - } - a->type = type; - a->service = service; - a->host = host; - a->custom_service = NULL; - a->bye = bye; - a->flush = flush; - a->next = NULL; - queueToEnd(mdns_out_answer_t, *destination, a); - return true; -} - -/** - * @brief Allocate new packet for sending - */ -static mdns_tx_packet_t *_mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_tx_packet_t *packet = (mdns_tx_packet_t *)mdns_mem_malloc(sizeof(mdns_tx_packet_t)); - if (!packet) { - HOOK_MALLOC_FAILED; - return NULL; - } - memset((uint8_t *)packet, 0, sizeof(mdns_tx_packet_t)); - packet->tcpip_if = tcpip_if; - packet->ip_protocol = ip_protocol; - packet->port = MDNS_SERVICE_PORT; -#ifdef CONFIG_LWIP_IPV4 - if (ip_protocol == MDNS_IP_PROTOCOL_V4) { - esp_ip_addr_t addr = ESP_IP4ADDR_INIT(224, 0, 0, 251); - memcpy(&packet->dst, &addr, sizeof(esp_ip_addr_t)); - } -#endif -#ifdef CONFIG_LWIP_IPV6 - if (ip_protocol == MDNS_IP_PROTOCOL_V6) { - esp_ip_addr_t addr = ESP_IP6ADDR_INIT(0x000002ff, 0, 0, 0xfb000000); - memcpy(&packet->dst, &addr, sizeof(esp_ip_addr_t)); - } -#endif - return packet; -} - -static bool _mdns_create_answer_from_service(mdns_tx_packet_t *packet, mdns_service_t *service, - mdns_parsed_question_t *question, bool shared, bool send_flush) -{ - mdns_host_item_t *host = mdns_get_host_item(service->hostname); - bool is_delegated = (host != &_mdns_self_host); - if (question->type == MDNS_TYPE_PTR || question->type == MDNS_TYPE_ANY) { - // According to RFC6763-section12.1, for DNS-SD, SRV, TXT and all address records - // should be included in additional records. - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service, NULL, false, false) || - !_mdns_alloc_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || - !_mdns_alloc_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false) || - !_mdns_alloc_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_A, service, host, send_flush, - false) || - !_mdns_alloc_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_AAAA, service, host, - send_flush, false)) { - return false; - } - } else if (question->type == MDNS_TYPE_SRV) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || - !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_A, service, host, send_flush, false) || - !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_AAAA, service, host, send_flush, false)) { - return false; - } - } else if (question->type == MDNS_TYPE_TXT) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false)) { - return false; - } - } else if (question->type == MDNS_TYPE_SDPTR) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, service, NULL, false, false)) { - return false; - } - } - return true; -} - -static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t *packet, const char *hostname, bool send_flush) -{ - mdns_host_item_t *host = mdns_get_host_item(hostname); - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host, send_flush, false) || - !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, send_flush, false)) { - return false; - } - return true; -} -static bool _mdns_service_match_ptr_question(const mdns_service_t *service, const mdns_parsed_question_t *question) -{ - if (!_mdns_service_match(service, question->service, question->proto, NULL)) { - return false; - } - // The question parser stores anything before _type._proto in question->host - // So the question->host can be subtype or instance name based on its content - if (question->sub) { - mdns_subtype_t *subtype = service->subtype; - while (subtype) { - if (!strcasecmp(subtype->subtype, question->host)) { - return true; - } - subtype = subtype->next; - } - return false; - } - if (question->host) { - if (strcasecmp(_mdns_get_service_instance_name(service), question->host) != 0) { - return false; - } - } - return true; -} -/** - * @brief Create answer packet to questions from parsed packet - */ -void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) -{ - if (!parsed_packet->questions) { - return; - } - bool send_flush = parsed_packet->src_port == MDNS_SERVICE_PORT; - bool unicast = false; - bool shared = false; - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(parsed_packet->tcpip_if, parsed_packet->ip_protocol); - if (!packet) { - return; - } - packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; - packet->distributed = parsed_packet->distributed; - packet->id = parsed_packet->id; - - mdns_parsed_question_t *q = parsed_packet->questions; - uint32_t out_record_nums = 0; - while (q) { - shared = q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_SDPTR || !parsed_packet->probe; - if (q->type == MDNS_TYPE_SRV || q->type == MDNS_TYPE_TXT) { - mdns_srv_item_t *service = _mdns_get_service_item_instance(q->host, q->service, q->proto, NULL); - if (service == NULL) { // Service not found, but we continue to the next question - q = q->next; - continue; - } - if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { - _mdns_free_tx_packet(packet); - return; - } else { - out_record_nums++; - } - } else if (q->service && q->proto) { - mdns_srv_item_t *service = _mdns_server->services; - while (service) { - if (_mdns_service_match_ptr_question(service->service, q)) { - mdns_parsed_record_t *r = parsed_packet->records; - bool is_record_exist = false; - while (r) { - if (service->service->instance && r->host) { - if (_mdns_service_match_instance(service->service, r->host, r->service, r->proto, NULL) && r->ttl > (MDNS_ANSWER_PTR_TTL / 2)) { - is_record_exist = true; - break; - } - } else if (!service->service->instance && !r->host) { - if (_mdns_service_match(service->service, r->service, r->proto, NULL) && r->ttl > (MDNS_ANSWER_PTR_TTL / 2)) { - is_record_exist = true; - break; - } - } - r = r->next; - } - if (!is_record_exist) { - if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { - _mdns_free_tx_packet(packet); - return; - } else { - out_record_nums++; - } - } - } - service = service->next; - } - } else if (q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA) { - if (!_mdns_create_answer_from_hostname(packet, q->host, send_flush)) { - _mdns_free_tx_packet(packet); - return; - } else { - out_record_nums++; - } - } else if (q->type == MDNS_TYPE_ANY) { - if (!_mdns_append_host_list(&packet->answers, send_flush, false)) { - _mdns_free_tx_packet(packet); - return; - } else { - out_record_nums++; - } -#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES - } else if (q->type == MDNS_TYPE_PTR) { - mdns_host_item_t *host = mdns_get_host_item(q->host); - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, NULL, host, send_flush, false)) { - _mdns_free_tx_packet(packet); - return; - } else { - out_record_nums++; - } -#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ - } else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, NULL, send_flush, false)) { - _mdns_free_tx_packet(packet); - return; - } else { - out_record_nums++; - } - - if (parsed_packet->src_port != MDNS_SERVICE_PORT && // Repeat the queries only for "One-Shot mDNS queries" - (q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA -#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES - || q->type == MDNS_TYPE_PTR -#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ - )) { - mdns_out_question_t *out_question = mdns_mem_malloc(sizeof(mdns_out_question_t)); - if (out_question == NULL) { - HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); - return; - } - out_question->type = q->type; - out_question->unicast = q->unicast; - out_question->host = q->host; - q->host = NULL; - out_question->service = q->service; - q->service = NULL; - out_question->proto = q->proto; - q->proto = NULL; - out_question->domain = q->domain; - q->domain = NULL; - out_question->next = NULL; - out_question->own_dynamic_memory = true; - queueToEnd(mdns_out_question_t, packet->questions, out_question); - } - if (q->unicast) { - unicast = true; - } - q = q->next; - } - if (out_record_nums == 0) { - _mdns_free_tx_packet(packet); - return; - } - if (unicast || !send_flush) { - memcpy(&packet->dst, &parsed_packet->src, sizeof(esp_ip_addr_t)); - packet->port = parsed_packet->src_port; - } - - static uint8_t share_step = 0; - if (shared) { - _mdns_schedule_tx_packet(packet, 25 + (share_step * 25)); - share_step = (share_step + 1) & 0x03; - } else { - _mdns_dispatch_tx_packet(packet); - _mdns_free_tx_packet(packet); - } -} - -/** - * @brief Check if question is already in the list - */ -static bool _mdns_question_exists(mdns_out_question_t *needle, mdns_out_question_t *haystack) -{ - while (haystack) { - if (haystack->type == needle->type - && haystack->host == needle->host - && haystack->service == needle->service - && haystack->proto == needle->proto) { - return true; - } - haystack = haystack->next; - } - return false; -} - -static bool _mdns_append_host(mdns_out_answer_t **destination, mdns_host_item_t *host, bool flush, bool bye) -{ - if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { - return false; - } - if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { - return false; - } - return true; -} - -static bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], - size_t services_len, bool flush, bool bye) -{ - if (services == NULL) { - mdns_host_item_t *host = mdns_get_host_item(_mdns_server->hostname); - if (host != NULL) { - return _mdns_append_host(destination, host, flush, bye); - } - return true; - } - for (size_t i = 0; i < services_len; i++) { - mdns_host_item_t *host = mdns_get_host_item(services[i]->service->hostname); - if (!_mdns_append_host(destination, host, flush, bye)) { - return false; - } - } - return true; -} - -static bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye) -{ - if (!_str_null_or_empty(_mdns_server->hostname)) { - mdns_host_item_t *self_host = mdns_get_host_item(_mdns_server->hostname); - if (!_mdns_append_host(destination, self_host, flush, bye)) { - return false; - } - } - mdns_host_item_t *host = _mdns_host_list; - while (host != NULL) { - host = host->next; - if (!_mdns_append_host(destination, host, flush, bye)) { - return false; - } - } - return true; -} - -static bool _mdns_append_host_question(mdns_out_question_t **questions, const char *hostname, bool unicast) -{ - mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); - if (!q) { - HOOK_MALLOC_FAILED; - return false; - } - q->next = NULL; - q->unicast = unicast; - q->type = MDNS_TYPE_ANY; - q->host = hostname; - q->service = NULL; - q->proto = NULL; - q->domain = MDNS_DEFAULT_DOMAIN; - q->own_dynamic_memory = false; - if (_mdns_question_exists(q, *questions)) { - mdns_mem_free(q); - } else { - queueToEnd(mdns_out_question_t, *questions, q); - } - return true; -} - -static bool _mdns_append_host_questions_for_services(mdns_out_question_t **questions, mdns_srv_item_t *services[], - size_t len, bool unicast) -{ - if (!_str_null_or_empty(_mdns_server->hostname) && - !_mdns_append_host_question(questions, _mdns_server->hostname, unicast)) { - return false; - } - for (size_t i = 0; i < len; i++) { - if (!_mdns_append_host_question(questions, services[i]->service->hostname, unicast)) { - return false; - } - } - return true; -} - -/** - * @brief Create probe packet for particular services on particular PCB - */ -static mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool first, bool include_ip) -{ - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); - if (!packet) { - return NULL; - } - - size_t i; - for (i = 0; i < len; i++) { - mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); - if (!q) { - HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); - return NULL; - } - q->next = NULL; - q->unicast = first; - q->type = MDNS_TYPE_ANY; - q->host = _mdns_get_service_instance_name(services[i]->service); - q->service = services[i]->service->service; - q->proto = services[i]->service->proto; - q->domain = MDNS_DEFAULT_DOMAIN; - q->own_dynamic_memory = false; - if (!q->host || _mdns_question_exists(q, packet->questions)) { - mdns_mem_free(q); - continue; - } else { - queueToEnd(mdns_out_question_t, packet->questions, q); - } - if (!q->host || !_mdns_alloc_answer(&packet->servers, MDNS_TYPE_SRV, services[i]->service, NULL, false, false)) { - _mdns_free_tx_packet(packet); - return NULL; - } - } - if (include_ip) { - if (!_mdns_append_host_questions_for_services(&packet->questions, services, len, first)) { - _mdns_free_tx_packet(packet); - return NULL; - } - if (!_mdns_append_host_list_in_services(&packet->servers, services, len, false, false)) { - _mdns_free_tx_packet(packet); - return NULL; - } - } - return packet; -} + + + + /** - * @brief Create announce packet for particular services on particular PCB + * @brief schedules a packet to be sent after given milliseconds + * + * @param packet the packet + * @param ms_after number of milliseconds after which the packet should be dispatched */ -static mdns_tx_packet_t *_mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool include_ip) +void _mdns_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after) { - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); if (!packet) { - return NULL; + return; } - packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; - - uint8_t i; - for (i = 0; i < len; i++) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, false)) { - _mdns_free_tx_packet(packet); - return NULL; - } + packet->send_at = (xTaskGetTickCount() * portTICK_PERIOD_MS) + ms_after; + packet->next = NULL; + if (!_mdns_server->tx_queue_head || _mdns_server->tx_queue_head->send_at > packet->send_at) { + packet->next = _mdns_server->tx_queue_head; + _mdns_server->tx_queue_head = packet; + return; } - if (include_ip) { - if (!_mdns_append_host_list_in_services(&packet->servers, services, len, true, false)) { - _mdns_free_tx_packet(packet); - return NULL; - } + mdns_tx_packet_t *q = _mdns_server->tx_queue_head; + while (q->next && q->next->send_at <= packet->send_at) { + q = q->next; } - return packet; + packet->next = q->next; + q->next = packet; } /** - * @brief Convert probe packet to announce + * @brief free all packets scheduled for sending */ -static mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *probe) +static void _mdns_clear_tx_queue_head(void) { - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(probe->tcpip_if, probe->ip_protocol); - if (!packet) { - return NULL; + mdns_tx_packet_t *q; + while (_mdns_server->tx_queue_head) { + q = _mdns_server->tx_queue_head; + _mdns_server->tx_queue_head = _mdns_server->tx_queue_head->next; + _mdns_free_tx_packet(q); } - packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; - - mdns_out_answer_t *s = probe->servers; - while (s) { - if (s->type == MDNS_TYPE_SRV) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, s->service, NULL, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, s->service, NULL, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, s->service, NULL, true, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, s->service, NULL, true, false)) { - _mdns_free_tx_packet(packet); - return NULL; - } - mdns_host_item_t *host = mdns_get_host_item(s->service->hostname); - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host, true, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, true, false)) { - _mdns_free_tx_packet(packet); - return NULL; - } +} - } else if (s->type == MDNS_TYPE_A || s->type == MDNS_TYPE_AAAA) { - if (!_mdns_alloc_answer(&packet->answers, s->type, NULL, s->host, true, false)) { - _mdns_free_tx_packet(packet); - return NULL; +/** + * @brief clear packets scheduled for sending on a specific interface + * + * @param tcpip_if the interface + * @param ip_protocol pcb type V4/V6 + */ +static void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t *q, * p; + while (_mdns_server->tx_queue_head && _mdns_server->tx_queue_head->tcpip_if == tcpip_if && _mdns_server->tx_queue_head->ip_protocol == ip_protocol) { + q = _mdns_server->tx_queue_head; + _mdns_server->tx_queue_head = _mdns_server->tx_queue_head->next; + _mdns_free_tx_packet(q); + } + if (_mdns_server->tx_queue_head) { + q = _mdns_server->tx_queue_head; + while (q->next) { + if (q->next->tcpip_if == tcpip_if && q->next->ip_protocol == ip_protocol) { + p = q->next; + q->next = p->next; + _mdns_free_tx_packet(p); + } else { + q = q->next; } } + } +} - s = s->next; +/** + * @brief get the next packet scheduled for sending on a specific interface + * + * @param tcpip_if the interface + * @param ip_protocol pcb type V4/V6 + */ +static mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t *q = _mdns_server->tx_queue_head; + while (q) { + if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol) { + return q; + } + q = q->next; } - return packet; + return NULL; } + /** - * @brief Send by for particular services on particular PCB + * @brief Remove and free answer from answer list (destination) */ -void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) +static void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service) { - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); - if (!packet) { + mdns_out_answer_t *d = *destination; + if (!d) { return; } - packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; - size_t i; - for (i = 0; i < len; i++) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, true, true)) { - _mdns_free_tx_packet(packet); + mdns_srv_item_t s = {NULL, NULL}; + if (!service) { + service = &s; + } + if (d->type == type && d->service == service->service) { + *destination = d->next; + mdns_mem_free(d); + return; + } + while (d->next) { + mdns_out_answer_t *a = d->next; + if (a->type == type && a->service == service->service) { + d->next = a->next; + mdns_mem_free(a); return; } + d = d->next; } - if (include_ip) { - _mdns_append_host_list_in_services(&packet->answers, services, len, true, true); - } - _mdns_dispatch_tx_packet(packet); - _mdns_free_tx_packet(packet); } + + + + + + + + + + /** * @brief Send probe for additional services on particular PCB */ @@ -2017,55 +654,7 @@ static void _mdns_send_bye(mdns_srv_item_t **services, size_t len, bool include_ } } -/** - * @brief Send bye for particular subtypes - */ -static void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, mdns_subtype_t *remove_subtypes) -{ - uint8_t i, j; - for (i = 0; i < MDNS_MAX_INTERFACES; i++) { - for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - if (mdns_is_netif_ready(i, j)) { - mdns_tx_packet_t *packet = _mdns_alloc_packet_default((mdns_if_t)i, (mdns_ip_protocol_t)j); - if (packet == NULL) { - return; - } - packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service->service, NULL, true, true)) { - _mdns_free_tx_packet(packet); - return; - } - - static uint8_t pkt[MDNS_MAX_PACKET_SIZE]; - uint16_t index = MDNS_HEAD_LEN; - memset(pkt, 0, MDNS_HEAD_LEN); - mdns_out_answer_t *a; - uint8_t count; - - _mdns_set_u16(pkt, MDNS_HEAD_FLAGS_OFFSET, packet->flags); - _mdns_set_u16(pkt, MDNS_HEAD_ID_OFFSET, packet->id); - - count = 0; - a = packet->answers; - while (a) { - if (a->type == MDNS_TYPE_PTR && a->service) { - const mdns_subtype_t *current_subtype = remove_subtypes; - while (current_subtype) { - count += (_mdns_append_subtype_ptr_record(pkt, &index, instance_name, current_subtype->subtype, a->service->service, a->service->proto, a->flush, a->bye) > 0); - current_subtype = current_subtype->next; - } - } - a = a->next; - } - _mdns_set_u16(pkt, MDNS_HEAD_ANSWERS_OFFSET, count); - - _mdns_udp_pcb_write(packet->tcpip_if, packet->ip_protocol, &packet->dst, packet->port, pkt, index); - _mdns_free_tx_packet(packet); - } - } - } -} /** * @brief Send announcement on particular PCB @@ -3025,107 +1614,9 @@ static void _mdns_search_add(mdns_search_once_t *search) -/** - * @brief Create search packet for particular interface - */ -static mdns_tx_packet_t *_mdns_create_search_packet(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_result_t *r = NULL; - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); - if (!packet) { - return NULL; - } - - mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); - if (!q) { - HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); - return NULL; - } - q->next = NULL; - q->unicast = search->unicast; - q->type = search->type; - q->host = search->instance; - q->service = search->service; - q->proto = search->proto; - q->domain = MDNS_DEFAULT_DOMAIN; - q->own_dynamic_memory = false; - queueToEnd(mdns_out_question_t, packet->questions, q); - - if (search->type == MDNS_TYPE_PTR) { - r = search->result; - while (r) { - //full record on the same interface is available - if (r->esp_netif != _mdns_get_esp_netif(tcpip_if) || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { - r = r->next; - continue; - } - mdns_out_answer_t *a = (mdns_out_answer_t *)mdns_mem_malloc(sizeof(mdns_out_answer_t)); - if (!a) { - HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); - return NULL; - } - a->type = MDNS_TYPE_PTR; - a->service = NULL; - a->custom_instance = r->instance_name; - a->custom_service = search->service; - a->custom_proto = search->proto; - a->bye = false; - a->flush = false; - a->next = NULL; - queueToEnd(mdns_out_answer_t, packet->answers, a); - r = r->next; - } - } - - return packet; -} - -/** - * @brief Send search packet to particular interface - */ -static void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_tx_packet_t *packet = NULL; - if (mdns_is_netif_ready(tcpip_if, ip_protocol) && _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state > PCB_INIT) { - packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol); - if (!packet) { - return; - } - _mdns_dispatch_tx_packet(packet); - _mdns_free_tx_packet(packet); - } -} -/** - * @brief Send search packet to all available interfaces - */ -static void _mdns_search_send(mdns_search_once_t *search) -{ - mdns_search_once_t *queue = _mdns_server->search_once; - bool found = false; - // looking for this search in active searches - while (queue) { - if (queue == search) { - found = true; - break; - } - queue = queue->next; - } - if (!found) { - // no longer active -> skip sending this search - return; - } - uint8_t i, j; - for (i = 0; i < MDNS_MAX_INTERFACES; i++) { - for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - _mdns_search_send_pcb(search, (mdns_if_t)i, (mdns_ip_protocol_t)j); - } - } -} static void _mdns_tx_handle_packet(mdns_tx_packet_t *p) { @@ -4793,36 +3284,6 @@ void mdns_query_results_free(mdns_result_t *results) MDNS_SERVICE_UNLOCK(); } -static void _mdns_query_results_free(mdns_result_t *results) -{ - mdns_result_t *r; - mdns_ip_addr_t *a; - - while (results) { - r = results; - - mdns_mem_free((char *)(r->hostname)); - mdns_mem_free((char *)(r->instance_name)); - mdns_mem_free((char *)(r->service_type)); - mdns_mem_free((char *)(r->proto)); - - for (size_t i = 0; i < r->txt_count; i++) { - mdns_mem_free((char *)(r->txt[i].key)); - mdns_mem_free((char *)(r->txt[i].value)); - } - mdns_mem_free(r->txt); - mdns_mem_free(r->txt_value_len); - - while (r->addr) { - a = r->addr; - r->addr = r->addr->next; - mdns_mem_free(a); - } - - results = results->next; - mdns_mem_free(r); - } -} esp_err_t mdns_query_async_delete(mdns_search_once_t *search) { @@ -5073,7 +3534,7 @@ esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t * /** * @brief Browse action */ -static esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse) +esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse) { mdns_action_t *action = NULL; @@ -5093,98 +3554,12 @@ static esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t return ESP_OK; } -/** - * @brief Free a browse item (Not free the list). - */ -static void _mdns_browse_item_free(mdns_browse_t *browse) -{ - mdns_mem_free(browse->service); - mdns_mem_free(browse->proto); - if (browse->result) { - _mdns_query_results_free(browse->result); - } - mdns_mem_free(browse); -} - -/** - * @brief Allocate new browse structure - */ -static mdns_browse_t *_mdns_browse_init(const char *service, const char *proto, mdns_browse_notify_t notifier) -{ - mdns_browse_t *browse = (mdns_browse_t *)mdns_mem_malloc(sizeof(mdns_browse_t)); - - if (!browse) { - HOOK_MALLOC_FAILED; - return NULL; - } - memset(browse, 0, sizeof(mdns_browse_t)); - - browse->state = BROWSE_INIT; - if (!_str_null_or_empty(service)) { - browse->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); - if (!browse->service) { - _mdns_browse_item_free(browse); - return NULL; - } - } - - if (!_str_null_or_empty(proto)) { - browse->proto = mdns_mem_strndup(proto, MDNS_NAME_BUF_LEN - 1); - if (!browse->proto) { - _mdns_browse_item_free(browse); - return NULL; - } - } - - browse->notifier = notifier; - return browse; -} - -mdns_browse_t *mdns_browse_new(const char *service, const char *proto, mdns_browse_notify_t notifier) -{ - mdns_browse_t *browse = NULL; - - if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto)) { - return NULL; - } - - browse = _mdns_browse_init(service, proto, notifier); - if (!browse) { - return NULL; - } - - if (_mdns_send_browse_action(ACTION_BROWSE_ADD, browse)) { - _mdns_browse_item_free(browse); - return NULL; - } - - return browse; -} - -esp_err_t mdns_browse_delete(const char *service, const char *proto) -{ - mdns_browse_t *browse = NULL; - - if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto)) { - return ESP_FAIL; - } - - browse = _mdns_browse_init(service, proto, NULL); - if (!browse) { - return ESP_ERR_NO_MEM; - } - if (_mdns_send_browse_action(ACTION_BROWSE_END, browse)) { - _mdns_browse_item_free(browse); - return ESP_ERR_NO_MEM; - } - return ESP_OK; -} /** * @brief Mark browse as finished, remove and free it from browse chain */ -static void _mdns_browse_finish(mdns_browse_t *browse) +void _mdns_browse_finish(mdns_browse_t *browse) { browse->state = BROWSE_OFF; mdns_browse_t *b = _mdns_server->browse; @@ -5206,7 +3581,7 @@ static void _mdns_browse_finish(mdns_browse_t *browse) /** * @brief Add new browse to the browse chain */ -static void _mdns_browse_add(mdns_browse_t *browse) +void _mdns_browse_add(mdns_browse_t *browse) { browse->state = BROWSE_RUNNING; mdns_browse_t *queue = _mdns_server->browse; @@ -5232,28 +3607,7 @@ static void _mdns_browse_add(mdns_browse_t *browse) } } -/** - * @brief Send PTR query packet to all available interfaces for browsing. - */ -static void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface) -{ - // Using search once for sending the PTR query - mdns_search_once_t search = {0}; - - search.instance = NULL; - search.service = browse->service; - search.proto = browse->proto; - search.type = MDNS_TYPE_PTR; - search.unicast = false; - search.result = NULL; - search.next = NULL; - - for (uint8_t protocol_idx = 0; protocol_idx < MDNS_IP_PROTOCOL_MAX; protocol_idx++) { - _mdns_search_send_pcb(&search, interface, (mdns_ip_protocol_t)protocol_idx); - } -} - -static void _mdns_browse_sync(mdns_browse_sync_t *browse_sync) +void _mdns_browse_sync(mdns_browse_sync_t *browse_sync) { mdns_browse_t *browse = browse_sync->browse; mdns_browse_result_sync_t *sync_result = browse_sync->sync_result; diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index 4b09462eb7..6d1c3fd29f 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -3,11 +3,125 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include #include "mdns_private.h" -#include "mdns_networking.h" -#include "mdns_types.h" +#include "mdns_browse.h" +#include "mdns_send.h" +#include "mdns_mem_caps.h" +#include "mdns_debug.h" +#include "mdns_utils.h" +#include "mdns_querier.h" +#include "esp_log.h" -// Browse functions -static esp_err_t mdns_browse_service(const char *service, const char *proto); -static void mdns_browse_result_add(mdns_browse_t *browse, mdns_result_t *result); -static void mdns_browse_finish(mdns_browse_t *browse); +static const char *TAG = "mdns_send"; + + +/** + * @brief Send PTR query packet to all available interfaces for browsing. + */ +void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface) +{ + // Using search once for sending the PTR query + mdns_search_once_t search = {0}; + + search.instance = NULL; + search.service = browse->service; + search.proto = browse->proto; + search.type = MDNS_TYPE_PTR; + search.unicast = false; + search.result = NULL; + search.next = NULL; + + for (uint8_t protocol_idx = 0; protocol_idx < MDNS_IP_PROTOCOL_MAX; protocol_idx++) { + _mdns_search_send_pcb(&search, interface, (mdns_ip_protocol_t)protocol_idx); + } +} + +/** + * @brief Free a browse item (Not free the list). + */ +void _mdns_browse_item_free(mdns_browse_t *browse) +{ + mdns_mem_free(browse->service); + mdns_mem_free(browse->proto); + if (browse->result) { + _mdns_query_results_free(browse->result); + } + mdns_mem_free(browse); +} + + +/** + * @brief Allocate new browse structure + */ +static mdns_browse_t *_mdns_browse_init(const char *service, const char *proto, mdns_browse_notify_t notifier) +{ + mdns_browse_t *browse = (mdns_browse_t *)mdns_mem_malloc(sizeof(mdns_browse_t)); + + if (!browse) { + HOOK_MALLOC_FAILED; + return NULL; + } + memset(browse, 0, sizeof(mdns_browse_t)); + + browse->state = BROWSE_INIT; + if (!mdns_utils_str_null_or_empty(service)) { + browse->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); + if (!browse->service) { + _mdns_browse_item_free(browse); + return NULL; + } + } + + if (!mdns_utils_str_null_or_empty(proto)) { + browse->proto = mdns_mem_strndup(proto, MDNS_NAME_BUF_LEN - 1); + if (!browse->proto) { + _mdns_browse_item_free(browse); + return NULL; + } + } + + browse->notifier = notifier; + return browse; +} + +mdns_browse_t *mdns_browse_new(const char *service, const char *proto, mdns_browse_notify_t notifier) +{ + mdns_browse_t *browse = NULL; + + if (is_mdns_server() || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + return NULL; + } + + browse = _mdns_browse_init(service, proto, notifier); + if (!browse) { + return NULL; + } + + if (_mdns_send_browse_action(ACTION_BROWSE_ADD, browse)) { + _mdns_browse_item_free(browse); + return NULL; + } + + return browse; +} + +esp_err_t mdns_browse_delete(const char *service, const char *proto) +{ + mdns_browse_t *browse = NULL; + + if (!is_mdns_server() || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + return ESP_FAIL; + } + + browse = _mdns_browse_init(service, proto, NULL); + if (!browse) { + return ESP_ERR_NO_MEM; + } + + if (_mdns_send_browse_action(ACTION_BROWSE_END, browse)) { + _mdns_browse_item_free(browse); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c new file mode 100644 index 0000000000..65642a05de --- /dev/null +++ b/components/mdns/mdns_netif.c @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_log.h" +#include "esp_check.h" +#include "mdns.h" +#include "mdns_private.h" +#include "mdns_networking.h" +#include "mdns_mem_caps.h" +#include "mdns_utils.h" +#include "mdns_debug.h" +#include "mdns_browse.h" diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index a51c08e7a6..1338d9b230 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -4,10 +4,36 @@ * SPDX-License-Identifier: Apache-2.0 */ #include "mdns_private.h" -#include "mdns_networking.h" -#include "mdns_types.h" +#include "mdns_querier.h" +#include "mdns_mem_caps.h" -// Query functions -static esp_err_t mdns_send_query(mdns_out_question_t *questions); -static void mdns_query_handle_response(mdns_parsed_packet_t *packet); -static void mdns_search_finish(mdns_search_once_t *search); +void _mdns_query_results_free(mdns_result_t *results) +{ + mdns_result_t *r; + mdns_ip_addr_t *a; + + while (results) { + r = results; + + mdns_mem_free((char *)(r->hostname)); + mdns_mem_free((char *)(r->instance_name)); + mdns_mem_free((char *)(r->service_type)); + mdns_mem_free((char *)(r->proto)); + + for (size_t i = 0; i < r->txt_count; i++) { + mdns_mem_free((char *)(r->txt[i].key)); + mdns_mem_free((char *)(r->txt[i].value)); + } + mdns_mem_free(r->txt); + mdns_mem_free(r->txt_value_len); + + while (r->addr) { + a = r->addr; + r->addr = r->addr->next; + mdns_mem_free(a); + } + + results = results->next; + mdns_mem_free(r); + } +} diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c new file mode 100644 index 0000000000..ad918036c7 --- /dev/null +++ b/components/mdns/mdns_send.c @@ -0,0 +1,1568 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "mdns_private.h" +#include "mdns_send.h" +#include "mdns_utils.h" +#include "mdns_networking.h" +#include "mdns_debug.h" +#include "mdns_mem_caps.h" +#include "esp_log.h" +#include "mdns_debug.h" +#include "mdns_netif.h" + +static const char *TAG = "mdns_send"; +static const char *MDNS_SUB_STR = "_sub"; + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +#endif + +static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char *strings[], uint8_t count, size_t packet_len); + +/** + * @brief sets uint16_t value in a packet + * + * @param packet MDNS packet + * @param index offset of uint16_t value + * @param value the value to set + */ +static inline void _mdns_set_u16(uint8_t *packet, uint16_t index, uint16_t value) +{ + if ((index + 1) >= MDNS_MAX_PACKET_SIZE) { + return; + } + packet[index] = (value >> 8) & 0xFF; + packet[index + 1] = value & 0xFF; +} + +/** + * @brief Allocate new packet for sending + */ +static mdns_tx_packet_t *_mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t *packet = (mdns_tx_packet_t *)mdns_mem_malloc(sizeof(mdns_tx_packet_t)); + if (!packet) { + HOOK_MALLOC_FAILED; + return NULL; + } + memset((uint8_t *)packet, 0, sizeof(mdns_tx_packet_t)); + packet->tcpip_if = tcpip_if; + packet->ip_protocol = ip_protocol; + packet->port = MDNS_SERVICE_PORT; +#ifdef CONFIG_LWIP_IPV4 + if (ip_protocol == MDNS_IP_PROTOCOL_V4) { + esp_ip_addr_t addr = ESP_IP4ADDR_INIT(224, 0, 0, 251); + memcpy(&packet->dst, &addr, sizeof(esp_ip_addr_t)); + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (ip_protocol == MDNS_IP_PROTOCOL_V6) { + esp_ip_addr_t addr = ESP_IP6ADDR_INIT(0x000002ff, 0, 0, 0xfb000000); + memcpy(&packet->dst, &addr, sizeof(esp_ip_addr_t)); + } +#endif + return packet; +} + +/** + * @brief frees a packet + * + * @param packet the packet + */ +void _mdns_free_tx_packet(mdns_tx_packet_t *packet) +{ + if (!packet) { + return; + } + mdns_out_question_t *q = packet->questions; + while (q) { + mdns_out_question_t *next = q->next; + if (q->own_dynamic_memory) { + mdns_mem_free((char *)q->host); + mdns_mem_free((char *)q->service); + mdns_mem_free((char *)q->proto); + mdns_mem_free((char *)q->domain); + } + mdns_mem_free(q); + q = next; + } + queueFree(mdns_out_answer_t, packet->answers); + queueFree(mdns_out_answer_t, packet->servers); + queueFree(mdns_out_answer_t, packet->additional); + mdns_mem_free(packet); +} + +/** + * @brief Allocate new answer and add it to answer list (destination) + */ +bool _mdns_alloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_service_t *service, + mdns_host_item_t *host, bool flush, bool bye) +{ + mdns_out_answer_t *d = *destination; + while (d) { + if (d->type == type && d->service == service && d->host == host) { + return true; + } + d = d->next; + } + + mdns_out_answer_t *a = (mdns_out_answer_t *)mdns_mem_malloc(sizeof(mdns_out_answer_t)); + if (!a) { + HOOK_MALLOC_FAILED; + return false; + } + a->type = type; + a->service = service; + a->host = host; + a->custom_service = NULL; + a->bye = bye; + a->flush = flush; + a->next = NULL; + queueToEnd(mdns_out_answer_t, *destination, a); + return true; +} + +static mdns_host_item_t *mdns_get_host_item(const char *hostname) +{ + if (hostname == NULL || strcasecmp(hostname, mdns_utils_get_global_hostname()) == 0) { + return mdns_utils_get_selfhost(); + } + mdns_host_item_t *host = mdns_utils_get_hosts(); + while (host != NULL) { + if (strcasecmp(host->hostname, hostname) == 0) { + return host; + } + host = host->next; + } + return NULL; +} + +static bool _mdns_create_answer_from_service(mdns_tx_packet_t *packet, mdns_service_t *service, + mdns_parsed_question_t *question, bool shared, bool send_flush) +{ + mdns_host_item_t *host = mdns_get_host_item(service->hostname); + bool is_delegated = (host != mdns_utils_get_selfhost()); + if (question->type == MDNS_TYPE_PTR || question->type == MDNS_TYPE_ANY) { + // According to RFC6763-section12.1, for DNS-SD, SRV, TXT and all address records + // should be included in additional records. + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service, NULL, false, false) || + !_mdns_alloc_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || + !_mdns_alloc_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false) || + !_mdns_alloc_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_A, service, host, send_flush, + false) || + !_mdns_alloc_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_AAAA, service, host, + send_flush, false)) { + return false; + } + } else if (question->type == MDNS_TYPE_SRV) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || + !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_A, service, host, send_flush, false) || + !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_AAAA, service, host, send_flush, false)) { + return false; + } + } else if (question->type == MDNS_TYPE_TXT) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false)) { + return false; + } + } else if (question->type == MDNS_TYPE_SDPTR) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, service, NULL, false, false)) { + return false; + } + } + return true; +} + +static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t *packet, const char *hostname, bool send_flush) +{ + mdns_host_item_t *host = mdns_get_host_item(hostname); + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host, send_flush, false) || + !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, send_flush, false)) { + return false; + } + return true; +} + +static bool _mdns_service_match_ptr_question(const mdns_service_t *service, const mdns_parsed_question_t *question) +{ + if (!_mdns_service_match(service, question->service, question->proto, NULL)) { + return false; + } + // The question parser stores anything before _type._proto in question->host + // So the question->host can be subtype or instance name based on its content + if (question->sub) { + mdns_subtype_t *subtype = service->subtype; + while (subtype) { + if (!strcasecmp(subtype->subtype, question->host)) { + return true; + } + subtype = subtype->next; + } + return false; + } + if (question->host) { + if (strcasecmp(_mdns_get_service_instance_name(service), question->host) != 0) { + return false; + } + } + return true; +} +static bool _mdns_append_host(mdns_out_answer_t **destination, mdns_host_item_t *host, bool flush, bool bye) +{ + if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { + return false; + } + if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { + return false; + } + return true; +} + +bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], + size_t services_len, bool flush, bool bye) +{ + if (services == NULL) { + mdns_host_item_t *host = mdns_get_host_item(mdns_utils_get_global_hostname()); + if (host != NULL) { + return _mdns_append_host(destination, host, flush, bye); + } + return true; + } + for (size_t i = 0; i < services_len; i++) { + mdns_host_item_t *host = mdns_get_host_item(services[i]->service->hostname); + if (!_mdns_append_host(destination, host, flush, bye)) { + return false; + } + } + return true; +} + +bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye) +{ + if (!mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { + mdns_host_item_t *self_host = mdns_get_host_item(mdns_utils_get_global_hostname()); + if (!_mdns_append_host(destination, self_host, flush, bye)) { + return false; + } + } + mdns_host_item_t *host = mdns_utils_get_hosts(); + while (host != NULL) { + host = host->next; + if (!_mdns_append_host(destination, host, flush, bye)) { + return false; + } + } + return true; +} + +/** + * @brief Check if question is already in the list + */ +static bool _mdns_question_exists(mdns_out_question_t *needle, mdns_out_question_t *haystack) +{ + while (haystack) { + if (haystack->type == needle->type + && haystack->host == needle->host + && haystack->service == needle->service + && haystack->proto == needle->proto) { + return true; + } + haystack = haystack->next; + } + return false; +} + +static bool _mdns_append_host_question(mdns_out_question_t **questions, const char *hostname, bool unicast) +{ + mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); + if (!q) { + HOOK_MALLOC_FAILED; + return false; + } + q->next = NULL; + q->unicast = unicast; + q->type = MDNS_TYPE_ANY; + q->host = hostname; + q->service = NULL; + q->proto = NULL; + q->domain = MDNS_UTILS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; + if (_mdns_question_exists(q, *questions)) { + mdns_mem_free(q); + } else { + queueToEnd(mdns_out_question_t, *questions, q); + } + return true; +} + +static bool _mdns_append_host_questions_for_services(mdns_out_question_t **questions, mdns_srv_item_t *services[], + size_t len, bool unicast) +{ + if (!mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname()) && + !_mdns_append_host_question(questions, mdns_utils_get_global_hostname(), unicast)) { + return false; + } + for (size_t i = 0; i < len; i++) { + if (!_mdns_append_host_question(questions, services[i]->service->hostname, unicast)) { + return false; + } + } + return true; +} + +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES +static inline int append_single_str(uint8_t *packet, uint16_t *index, const char *str, int len) +{ + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + if (!_mdns_append_u8(packet, index, len)) { + return 0; + } + memcpy(packet + *index, str, len); + *index += len; + return *index; +} + +/** + * @brief appends FQDN to a packet from hostname separated by dots. This API works the same way as + * _mdns_append_fqdn(), but refrains from DNS compression (as it's mainly used for IP addresses (many short items), + * where we gain very little (or compression even gets counter-productive mainly for IPv6 addresses) + * + * @param packet MDNS packet + * @param index offset in the packet + * @param name name representing FQDN in '.' separated parts + * @param last true if appending the last part (domain, typically "arpa") + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t append_fqdn_dots(uint8_t *packet, uint16_t *index, const char *name, bool last) +{ + int len = strlen(name); + char *host = (char *)name; + char *end = host; + char *start = host; + do { + end = memchr(start, '.', host + len - start); + end = end ? end : host + len; + int part_len = end - start; + if (!append_single_str(packet, index, start, part_len)) { + return 0; + } + start = ++end; + } while (end < name + len); + + if (!append_single_str(packet, index, "arpa", sizeof("arpa") - 1)) { + return 0; + } + + //empty string so terminate + if (!_mdns_append_u8(packet, index, 0)) { + return 0; + } + return *index; +} + +/** + * @brief Appends reverse lookup PTR record + */ +static uint8_t _mdns_append_reverse_ptr_record(uint8_t *packet, uint16_t *index, const char *name) +{ + if (strstr(name, "in-addr") == NULL && strstr(name, "ip6") == NULL) { + return 0; + } + + if (!append_fqdn_dots(packet, index, name, false)) { + return 0; + } + + if (!_mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, 10 /* TTL set to 10s*/)) { + return 0; + } + + uint16_t data_len_location = *index - 2; /* store the position of size (2=16bis) of this record */ + const char *str[2] = { mdns_utils_get_selfhost()->hostname, MDNS_UTILS_DEFAULT_DOMAIN }; + + int part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + + _mdns_set_u16(packet, data_len_location, part_length); + return 1; /* appending only 1 record */ +} +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + +/** + * @brief Create answer packet to questions from parsed packet + */ +void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) +{ + if (!parsed_packet->questions) { + return; + } + bool send_flush = parsed_packet->src_port == MDNS_SERVICE_PORT; + bool unicast = false; + bool shared = false; + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(parsed_packet->tcpip_if, parsed_packet->ip_protocol); + if (!packet) { + return; + } + packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; + packet->distributed = parsed_packet->distributed; + packet->id = parsed_packet->id; + + mdns_parsed_question_t *q = parsed_packet->questions; + uint32_t out_record_nums = 0; + while (q) { + shared = q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_SDPTR || !parsed_packet->probe; + if (q->type == MDNS_TYPE_SRV || q->type == MDNS_TYPE_TXT) { + mdns_srv_item_t *service = _mdns_get_service_item_instance(q->host, q->service, q->proto, NULL); + if (service == NULL) { // Service not found, but we continue to the next question + q = q->next; + continue; + } + if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } + } else if (q->service && q->proto) { + mdns_srv_item_t *service = mdns_utils_get_services(); + while (service) { + if (_mdns_service_match_ptr_question(service->service, q)) { + mdns_parsed_record_t *r = parsed_packet->records; + bool is_record_exist = false; + while (r) { + if (service->service->instance && r->host) { + if (_mdns_service_match_instance(service->service, r->host, r->service, r->proto, NULL) && r->ttl > (MDNS_ANSWER_PTR_TTL / 2)) { + is_record_exist = true; + break; + } + } else if (!service->service->instance && !r->host) { + if (_mdns_service_match(service->service, r->service, r->proto, NULL) && r->ttl > (MDNS_ANSWER_PTR_TTL / 2)) { + is_record_exist = true; + break; + } + } + r = r->next; + } + if (!is_record_exist) { + if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } + } + } + service = service->next; + } + } else if (q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA) { + if (!_mdns_create_answer_from_hostname(packet, q->host, send_flush)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } + } else if (q->type == MDNS_TYPE_ANY) { + if (!_mdns_append_host_list(&packet->answers, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + } else if (q->type == MDNS_TYPE_PTR) { + mdns_host_item_t *host = mdns_get_host_item(q->host); + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, NULL, host, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + } else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, NULL, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } + + if (parsed_packet->src_port != MDNS_SERVICE_PORT && // Repeat the queries only for "One-Shot mDNS queries" + (q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + || q->type == MDNS_TYPE_PTR +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + )) { + mdns_out_question_t *out_question = mdns_mem_malloc(sizeof(mdns_out_question_t)); + if (out_question == NULL) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return; + } + out_question->type = q->type; + out_question->unicast = q->unicast; + out_question->host = q->host; + q->host = NULL; + out_question->service = q->service; + q->service = NULL; + out_question->proto = q->proto; + q->proto = NULL; + out_question->domain = q->domain; + q->domain = NULL; + out_question->next = NULL; + out_question->own_dynamic_memory = true; + queueToEnd(mdns_out_question_t, packet->questions, out_question); + } + if (q->unicast) { + unicast = true; + } + q = q->next; + } + if (out_record_nums == 0) { + _mdns_free_tx_packet(packet); + return; + } + if (unicast || !send_flush) { + memcpy(&packet->dst, &parsed_packet->src, sizeof(esp_ip_addr_t)); + packet->port = parsed_packet->src_port; + } + + static uint8_t share_step = 0; + if (shared) { + _mdns_schedule_tx_packet(packet, 25 + (share_step * 25)); + share_step = (share_step + 1) & 0x03; + } else { + _mdns_dispatch_tx_packet(packet); + _mdns_free_tx_packet(packet); + } +} + +/** + * @brief appends FQDN to a packet, incrementing the index and + * compressing the output if previous occurrence of the string (or part of it) has been found + * + * @param packet MDNS packet + * @param index offset in the packet + * @param strings string array containing the parts of the FQDN + * @param count number of strings in the array + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char *strings[], uint8_t count, size_t packet_len) +{ + if (!count) { + //empty string so terminate + return _mdns_append_u8(packet, index, 0); + } + static char buf[MDNS_NAME_BUF_LEN]; + uint8_t len = strlen(strings[0]); + //try to find first the string length in the packet (if it exists) + uint8_t *len_location = (uint8_t *)memchr(packet, (char)len, *index); + while (len_location) { + mdns_name_t name; + //check if the string after len_location is the string that we are looking for + if (memcmp(len_location + 1, strings[0], len)) { //not continuing with our string +search_next: + //try and find the length byte further in the packet + len_location = (uint8_t *)memchr(len_location + 1, (char)len, *index - (len_location + 1 - packet)); + continue; + } + //seems that we might have found the string that we are looking for + //read the destination into name and compare + name.parts = 0; + name.sub = 0; + name.invalid = false; + name.host[0] = 0; + name.service[0] = 0; + name.proto[0] = 0; + name.domain[0] = 0; + const uint8_t *content = _mdns_read_fqdn(packet, len_location, &name, buf, packet_len); + if (!content) { + //not a readable fqdn? + goto search_next; // could be our unfinished fqdn, continue searching + } + if (name.parts == count) { + uint8_t i; + for (i = 0; i < count; i++) { + if (strcasecmp(strings[i], (const char *)&name + (i * (MDNS_NAME_BUF_LEN)))) { + //not our string! let's search more + goto search_next; + } + } + //we actually have found the string + break; + } else { + goto search_next; + } + } + //string is not yet in the packet, so let's add it + if (!len_location) { + uint8_t written = _mdns_append_string(packet, index, strings[0]); + if (!written) { + return 0; + } + //run the same for the other strings in the name + return written + _mdns_append_fqdn(packet, index, &strings[1], count - 1, packet_len); + } + + //we have found the string so let's insert a pointer to it instead + uint16_t offset = len_location - packet; + offset |= MDNS_NAME_REF; + return _mdns_append_u16(packet, index, offset); +} + + +/** + * @brief Append question to packet + */ +static uint16_t _mdns_append_question(uint8_t *packet, uint16_t *index, mdns_out_question_t *q) +{ + uint8_t part_length; +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + if (q->host && (strstr(q->host, "in-addr") || strstr(q->host, "ip6"))) { + part_length = append_fqdn_dots(packet, index, q->host, false); + if (!part_length) { + return 0; + } + } else +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + { + const char *str[4]; + uint8_t str_index = 0; + if (q->host) { + str[str_index++] = q->host; + } + if (q->service) { + str[str_index++] = q->service; + } + if (q->proto) { + str[str_index++] = q->proto; + } + if (q->domain) { + str[str_index++] = q->domain; + } + part_length = _mdns_append_fqdn(packet, index, str, str_index, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + } + + part_length += _mdns_append_u16(packet, index, q->type); + part_length += _mdns_append_u16(packet, index, q->unicast ? 0x8001 : 0x0001); + return part_length; +} + +/** + * @brief appends PTR record for service to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server that is hosting the service + * @param service the service to add record for + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, const char *service, const char *proto, bool flush, bool bye) +{ + const char *str[4]; + uint16_t record_length = 0; + uint8_t part_length; + + if (service == NULL) { + return 0; + } + + str[0] = instance; + str[1] = service; + str[2] = proto; + str[3] = MDNS_UTILS_DEFAULT_DOMAIN; + + part_length = _mdns_append_fqdn(packet, index, str + 1, 3, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} + +/** + * @brief appends PTR record for a subtype to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param instance the service instance name + * @param subtype the service subtype + * @param proto the service protocol + * @param flush whether to set the flush flag + * @param bye whether to set the bye flag + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_subtype_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, + const char *subtype, const char *service, const char *proto, bool flush, + bool bye) +{ + const char *subtype_str[5] = {subtype, MDNS_SUB_STR, service, proto, MDNS_UTILS_DEFAULT_DOMAIN}; + const char *instance_str[4] = {instance, service, proto, MDNS_UTILS_DEFAULT_DOMAIN}; + uint16_t record_length = 0; + uint8_t part_length; + + if (service == NULL) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, subtype_str, ARRAY_SIZE(subtype_str), MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + part_length = _mdns_append_fqdn(packet, index, instance_str, ARRAY_SIZE(instance_str), MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} +/** + * @brief Append PTR answers to packet + * + * @return number of answers added to the packet + */ +static uint8_t _mdns_append_service_ptr_answers(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, + bool bye) +{ + uint8_t appended_answers = 0; + + if (_mdns_append_ptr_record(packet, index, _mdns_get_service_instance_name(service), service->service, + service->proto, flush, bye) <= 0) { + return appended_answers; + } + appended_answers++; + + mdns_subtype_t *subtype = service->subtype; + while (subtype) { + appended_answers += + (_mdns_append_subtype_ptr_record(packet, index, _mdns_get_service_instance_name(service), subtype->subtype, + service->service, service->proto, flush, bye) > 0); + subtype = subtype->next; + } + + return appended_answers; +} + +/** + * @brief appends SRV record for service to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server that is hosting the service + * @param service the service to add record for + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_srv_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) +{ + const char *str[4]; + uint16_t record_length = 0; + uint8_t part_length; + + if (service == NULL) { + return 0; + } + + str[0] = _mdns_get_service_instance_name(service); + str[1] = service->service; + str[2] = service->proto; + str[3] = MDNS_UTILS_DEFAULT_DOMAIN; + + if (!str[0]) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_SRV, flush, bye ? 0 : MDNS_ANSWER_SRV_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + + part_length = 0; + part_length += _mdns_append_u16(packet, index, service->priority); + part_length += _mdns_append_u16(packet, index, service->weight); + part_length += _mdns_append_u16(packet, index, service->port); + if (part_length != 6) { + return 0; + } + + if (service->hostname) { + str[0] = service->hostname; + } else { + str[0] = mdns_utils_get_global_hostname(); + } + str[1] = MDNS_UTILS_DEFAULT_DOMAIN; + + if (mdns_utils_str_null_or_empty(str[0])) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length + 6); + + record_length += part_length + 6; + return record_length; +} + +/** + * @brief appends TXT record for service to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server that is hosting the service + * @param service the service to add record for + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_txt_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) +{ + const char *str[4]; + uint16_t record_length = 0; + uint8_t part_length; + + if (service == NULL) { + return 0; + } + + str[0] = _mdns_get_service_instance_name(service); + str[1] = service->service; + str[2] = service->proto; + str[3] = MDNS_UTILS_DEFAULT_DOMAIN; + + if (!str[0]) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_TXT, flush, bye ? 0 : MDNS_ANSWER_TXT_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + uint16_t data_len = 0; + + mdns_txt_linked_item_t *txt = service->txt; + while (txt) { + int l = append_one_txt_record_entry(packet, index, txt); + if (l > 0) { + data_len += l; + } else if (l == 0) { // TXT entry won't fit into the mdns packet + return 0; + } + txt = txt->next; + } + if (!data_len) { + data_len = 1; + packet[*index] = 0; + *index = *index + 1; + } + _mdns_set_u16(packet, data_len_location, data_len); + record_length += data_len; + return record_length; +} + +/** + * @brief appends DNS-SD PTR record for service to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server that is hosting the service + * @param service the service to add record for + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_sdptr_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) +{ + const char *str[3]; + const char *sd_str[4]; + uint16_t record_length = 0; + uint8_t part_length; + + if (service == NULL) { + return 0; + } + + sd_str[0] = (char *)"_services"; + sd_str[1] = (char *)"_dns-sd"; + sd_str[2] = (char *)"_udp"; + sd_str[3] = MDNS_UTILS_DEFAULT_DOMAIN; + + str[0] = service->service; + str[1] = service->proto; + str[2] = MDNS_UTILS_DEFAULT_DOMAIN; + + part_length = _mdns_append_fqdn(packet, index, sd_str, 4, MDNS_MAX_PACKET_SIZE); + + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, flush, MDNS_ANSWER_PTR_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + part_length = _mdns_append_fqdn(packet, index, str, 3, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} + +#ifdef CONFIG_LWIP_IPV4 +/** + * @brief appends A record to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param hostname the hostname address to add + * @param ip the IP address to add + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_a_record(uint8_t *packet, uint16_t *index, const char *hostname, uint32_t ip, bool flush, bool bye) +{ + const char *str[2]; + uint16_t record_length = 0; + uint8_t part_length; + + str[0] = hostname; + str[1] = MDNS_UTILS_DEFAULT_DOMAIN; + + if (mdns_utils_str_null_or_empty(str[0])) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_A, flush, bye ? 0 : MDNS_ANSWER_A_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + + if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, ip & 0xFF); + _mdns_append_u8(packet, index, (ip >> 8) & 0xFF); + _mdns_append_u8(packet, index, (ip >> 16) & 0xFF); + _mdns_append_u8(packet, index, (ip >> 24) & 0xFF); + _mdns_set_u16(packet, data_len_location, 4); + + record_length += 4; + return record_length; +} +#endif /* CONFIG_LWIP_IPV4 */ + +#ifdef CONFIG_LWIP_IPV6 +/** + * @brief appends AAAA record to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param hostname the hostname address to add + * @param ipv6 the IPv6 address to add + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_aaaa_record(uint8_t *packet, uint16_t *index, const char *hostname, uint8_t *ipv6, bool flush, bool bye) +{ + const char *str[2]; + uint16_t record_length = 0; + uint8_t part_length; + + str[0] = hostname; + str[1] = MDNS_UTILS_DEFAULT_DOMAIN; + + if (mdns_utils_str_null_or_empty(str[0])) { + return 0; + } + + + part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_AAAA, flush, bye ? 0 : MDNS_ANSWER_AAAA_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + + if ((*index + MDNS_ANSWER_AAAA_SIZE) > MDNS_MAX_PACKET_SIZE) { + return 0; + } + + part_length = MDNS_ANSWER_AAAA_SIZE; + memcpy(packet + *index, ipv6, part_length); + *index += part_length; + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} +#endif + +static uint8_t _mdns_append_host_answer(uint8_t *packet, uint16_t *index, mdns_host_item_t *host, + uint8_t address_type, bool flush, bool bye) +{ + mdns_ip_addr_t *addr = host->address_list; + uint8_t num_records = 0; + + while (addr != NULL) { + if (addr->addr.type == address_type) { +#ifdef CONFIG_LWIP_IPV4 + if (address_type == ESP_IPADDR_TYPE_V4 && + _mdns_append_a_record(packet, index, host->hostname, addr->addr.u_addr.ip4.addr, flush, bye) <= 0) { + break; + } +#endif /* CONFIG_LWIP_IPV4 */ +#ifdef CONFIG_LWIP_IPV6 + if (address_type == ESP_IPADDR_TYPE_V6 && + _mdns_append_aaaa_record(packet, index, host->hostname, (uint8_t *)addr->addr.u_addr.ip6.addr, flush, + bye) <= 0) { + break; + } +#endif /* CONFIG_LWIP_IPV6 */ + num_records++; + } + addr = addr->next; + } + return num_records; +} + +/** + * @brief Append answer to packet + * + * @return number of answers added to the packet + */ +static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_answer_t *answer, mdns_if_t tcpip_if) +{ + if (answer->host) { + bool is_host_valid = (mdns_utils_get_selfhost() == answer->host); + mdns_host_item_t *target_host = mdns_utils_get_hosts(); + while (target_host && !is_host_valid) { + if (target_host == answer->host) { + is_host_valid = true; + } + target_host = target_host->next; + } + if (!is_host_valid) { + return 0; + } + } + + if (answer->type == MDNS_TYPE_PTR) { + if (answer->service) { + return _mdns_append_service_ptr_answers(packet, index, answer->service, answer->flush, answer->bye); +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + } else if (answer->host && answer->host->hostname && + (strstr(answer->host->hostname, "in-addr") || strstr(answer->host->hostname, "ip6"))) { + return _mdns_append_reverse_ptr_record(packet, index, answer->host->hostname) > 0; +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + } else { + return _mdns_append_ptr_record(packet, index, + answer->custom_instance, answer->custom_service, answer->custom_proto, + answer->flush, answer->bye) > 0; + } + } else if (answer->type == MDNS_TYPE_SRV) { + return _mdns_append_srv_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + } else if (answer->type == MDNS_TYPE_TXT) { + return _mdns_append_txt_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + } else if (answer->type == MDNS_TYPE_SDPTR) { + return _mdns_append_sdptr_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + } +#ifdef CONFIG_LWIP_IPV4 + else if (answer->type == MDNS_TYPE_A) { + if (answer->host == mdns_utils_get_selfhost()) { + esp_netif_ip_info_t if_ip_info; + if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && !mdns_utils_is_pcb_duplicate(tcpip_if, MDNS_IP_PROTOCOL_V4)) { + return 0; + } + if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { + return 0; + } + if (_mdns_append_a_record(packet, index, mdns_utils_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { + return 0; + } + if (!_mdns_if_is_dup(tcpip_if)) { + return 1; + } + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &if_ip_info)) { + return 1; + } + if (_mdns_append_a_record(packet, index, mdns_utils_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { + return 2; + } + return 1; + } else if (answer->host != NULL) { + return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V4, answer->flush, answer->bye); + } + } +#endif /* CONFIG_LWIP_IPV4 */ +#ifdef CONFIG_LWIP_IPV6 + else if (answer->type == MDNS_TYPE_AAAA) { + if (answer->host == mdns_utils_get_selfhost()) { + struct esp_ip6_addr if_ip6s[NETIF_IPV6_MAX_NUMS]; + uint8_t count = 0; + if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && !mdns_utils_is_pcb_duplicate(tcpip_if, MDNS_IP_PROTOCOL_V6)) { + return 0; + } + count = esp_netif_get_all_ip6(_mdns_get_esp_netif(tcpip_if), if_ip6s); + assert(count <= NETIF_IPV6_MAX_NUMS); + for (int i = 0; i < count; i++) { + if (_ipv6_address_is_zero(if_ip6s[i])) { + return 0; + } + if (_mdns_append_aaaa_record(packet, index, mdns_utils_get_global_hostname(), (uint8_t *)if_ip6s[i].addr, + answer->flush, answer->bye) <= 0) { + return 0; + } + } + if (!_mdns_if_is_dup(tcpip_if)) { + return count; + } + + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + struct esp_ip6_addr other_ip6; + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &other_ip6)) { + return count; + } + if (_mdns_append_aaaa_record(packet, index, mdns_utils_get_global_hostname(), (uint8_t *)other_ip6.addr, + answer->flush, answer->bye) > 0) { + return 1 + count; + } + return count; + } else if (answer->host != NULL) { + return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V6, answer->flush, + answer->bye); + } + } +#endif /* CONFIG_LWIP_IPV6 */ + return 0; +} + +/** + * @brief sends a packet + * + * @param p the packet + */ +void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p) +{ + static uint8_t packet[MDNS_MAX_PACKET_SIZE]; + uint16_t index = MDNS_HEAD_LEN; + memset(packet, 0, MDNS_HEAD_LEN); + mdns_out_question_t *q; + mdns_out_answer_t *a; + uint8_t count; + + _mdns_set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, p->flags); + _mdns_set_u16(packet, MDNS_HEAD_ID_OFFSET, p->id); + + count = 0; + q = p->questions; + while (q) { + if (_mdns_append_question(packet, &index, q)) { + count++; + } + q = q->next; + } + _mdns_set_u16(packet, MDNS_HEAD_QUESTIONS_OFFSET, count); + + count = 0; + a = p->answers; + while (a) { + count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + a = a->next; + } + _mdns_set_u16(packet, MDNS_HEAD_ANSWERS_OFFSET, count); + + count = 0; + a = p->servers; + while (a) { + count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + a = a->next; + } + _mdns_set_u16(packet, MDNS_HEAD_SERVERS_OFFSET, count); + + count = 0; + a = p->additional; + while (a) { + count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + a = a->next; + } + _mdns_set_u16(packet, MDNS_HEAD_ADDITIONAL_OFFSET, count); + + DBG_TX_PACKET(p, packet, index); + + _mdns_udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); +} + +/** + * @brief Create search packet for particular interface + */ +static mdns_tx_packet_t *_mdns_create_search_packet(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_result_t *r = NULL; + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return NULL; + } + + mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); + if (!q) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return NULL; + } + q->next = NULL; + q->unicast = search->unicast; + q->type = search->type; + q->host = search->instance; + q->service = search->service; + q->proto = search->proto; + q->domain = MDNS_UTILS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; + queueToEnd(mdns_out_question_t, packet->questions, q); + + if (search->type == MDNS_TYPE_PTR) { + r = search->result; + while (r) { + //full record on the same interface is available + if (r->esp_netif != _mdns_get_esp_netif(tcpip_if) || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { + r = r->next; + continue; + } + mdns_out_answer_t *a = (mdns_out_answer_t *)mdns_mem_malloc(sizeof(mdns_out_answer_t)); + if (!a) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return NULL; + } + a->type = MDNS_TYPE_PTR; + a->service = NULL; + a->custom_instance = r->instance_name; + a->custom_service = search->service; + a->custom_proto = search->proto; + a->bye = false; + a->flush = false; + a->next = NULL; + queueToEnd(mdns_out_answer_t, packet->answers, a); + r = r->next; + } + } + + return packet; +} + + +/** + * @brief Send search packet to particular interface + */ +void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t *packet = NULL; + if (mdns_is_netif_ready(tcpip_if, ip_protocol) && mdns_utils_is_pcb_after_init(tcpip_if, ip_protocol)) { + packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol); + if (!packet) { + return; + } + _mdns_dispatch_tx_packet(packet); + _mdns_free_tx_packet(packet); + } +} + +/** + * @brief Send search packet to all available interfaces + */ +void _mdns_search_send(mdns_search_once_t *search) +{ + mdns_search_once_t *queue = mdns_utils_get_search(); + bool found = false; + // looking for this search in active searches + while (queue) { + if (queue == search) { + found = true; + break; + } + queue = queue->next; + } + + if (!found) { + // no longer active -> skip sending this search + return; + } + + uint8_t i, j; + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + _mdns_search_send_pcb(search, (mdns_if_t)i, (mdns_ip_protocol_t)j); + } + } +} + + +/** + * @brief Create probe packet for particular services on particular PCB + */ +mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool first, bool include_ip) +{ + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return NULL; + } + + size_t i; + for (i = 0; i < len; i++) { + mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); + if (!q) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return NULL; + } + q->next = NULL; + q->unicast = first; + q->type = MDNS_TYPE_ANY; + q->host = _mdns_get_service_instance_name(services[i]->service); + q->service = services[i]->service->service; + q->proto = services[i]->service->proto; + q->domain = MDNS_UTILS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; + if (!q->host || _mdns_question_exists(q, packet->questions)) { + mdns_mem_free(q); + continue; + } else { + queueToEnd(mdns_out_question_t, packet->questions, q); + } + + if (!q->host || !_mdns_alloc_answer(&packet->servers, MDNS_TYPE_SRV, services[i]->service, NULL, false, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + + if (include_ip) { + if (!_mdns_append_host_questions_for_services(&packet->questions, services, len, first)) { + _mdns_free_tx_packet(packet); + return NULL; + } + + if (!_mdns_append_host_list_in_services(&packet->servers, services, len, false, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + + return packet; +} + +/** + * @brief Create announce packet for particular services on particular PCB + */ +mdns_tx_packet_t *_mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool include_ip) +{ + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return NULL; + } + packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; + + uint8_t i; + for (i = 0; i < len; i++) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + if (include_ip) { + if (!_mdns_append_host_list_in_services(&packet->servers, services, len, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + return packet; +} + +/** + * @brief Convert probe packet to announce + */ +mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *probe) +{ + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(probe->tcpip_if, probe->ip_protocol); + if (!packet) { + return NULL; + } + packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; + + mdns_out_answer_t *s = probe->servers; + while (s) { + if (s->type == MDNS_TYPE_SRV) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, s->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, s->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, s->service, NULL, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, s->service, NULL, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + mdns_host_item_t *host = mdns_get_host_item(s->service->hostname); + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + + } else if (s->type == MDNS_TYPE_A || s->type == MDNS_TYPE_AAAA) { + if (!_mdns_alloc_answer(&packet->answers, s->type, NULL, s->host, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + + s = s->next; + } + return packet; +} + +/** + * @brief Send by for particular services on particular PCB + */ +void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) +{ + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return; + } + packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; + size_t i; + for (i = 0; i < len; i++) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, true, true)) { + _mdns_free_tx_packet(packet); + return; + } + } + if (include_ip) { + _mdns_append_host_list_in_services(&packet->answers, services, len, true, true); + } + _mdns_dispatch_tx_packet(packet); + _mdns_free_tx_packet(packet); +} + +/** + * @brief Send bye for particular subtypes + */ +void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, mdns_subtype_t *remove_subtypes) +{ + uint8_t i, j; + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + if (mdns_is_netif_ready(i, j)) { + mdns_tx_packet_t *packet = _mdns_alloc_packet_default((mdns_if_t)i, (mdns_ip_protocol_t)j); + if (packet == NULL) { + return; + } + packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service->service, NULL, true, true)) { + _mdns_free_tx_packet(packet); + return; + } + + static uint8_t pkt[MDNS_MAX_PACKET_SIZE]; + uint16_t index = MDNS_HEAD_LEN; + memset(pkt, 0, MDNS_HEAD_LEN); + mdns_out_answer_t *a; + uint8_t count; + + _mdns_set_u16(pkt, MDNS_HEAD_FLAGS_OFFSET, packet->flags); + _mdns_set_u16(pkt, MDNS_HEAD_ID_OFFSET, packet->id); + + count = 0; + a = packet->answers; + while (a) { + if (a->type == MDNS_TYPE_PTR && a->service) { + const mdns_subtype_t *current_subtype = remove_subtypes; + while (current_subtype) { + count += (_mdns_append_subtype_ptr_record(pkt, &index, instance_name, current_subtype->subtype, a->service->service, a->service->proto, a->flush, a->bye) > 0); + current_subtype = current_subtype->next; + } + } + a = a->next; + } + _mdns_set_u16(pkt, MDNS_HEAD_ANSWERS_OFFSET, count); + + _mdns_udp_pcb_write(packet->tcpip_if, packet->ip_protocol, &packet->dst, packet->port, pkt, index); + + _mdns_free_tx_packet(packet); + } + } + } +} diff --git a/components/mdns/private_include/mdns_browse.h b/components/mdns/private_include/mdns_browse.h new file mode 100644 index 0000000000..3962234b21 --- /dev/null +++ b/components/mdns/private_include/mdns_browse.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "mdns_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//void _mdns_browse_item_free(mdns_browse_t *browse); +esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse); +esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync); +void _mdns_browse_sync(mdns_browse_sync_t *browse_sync); +void _mdns_browse_finish(mdns_browse_t *browse); +void _mdns_browse_add(mdns_browse_t *browse); +void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface); + +void _mdns_browse_item_free(mdns_browse_t *browse); + +#ifdef __cplusplus +} +#endif diff --git a/components/mdns/private_include/mdns_netif.h b/components/mdns/private_include/mdns_netif.h new file mode 100644 index 0000000000..d50ca8cfe5 --- /dev/null +++ b/components/mdns/private_include/mdns_netif.h @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "mdns_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool _mdns_if_is_dup(mdns_if_t tcpip_if); + +#ifdef __cplusplus +} +#endif diff --git a/components/mdns/private_include/mdns_querier.h b/components/mdns/private_include/mdns_querier.h new file mode 100644 index 0000000000..e984dca69e --- /dev/null +++ b/components/mdns/private_include/mdns_querier.h @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "mdns_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _mdns_query_results_free(mdns_result_t *results); + +#ifdef __cplusplus +} +#endif diff --git a/components/mdns/private_include/mdns_send.h b/components/mdns/private_include/mdns_send.h new file mode 100644 index 0000000000..32fe1970b8 --- /dev/null +++ b/components/mdns/private_include/mdns_send.h @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "mdns_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +void _mdns_search_send(mdns_search_once_t *search); + +void _mdns_free_tx_packet(mdns_tx_packet_t *packet); + +mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool first, bool include_ip); + +bool _mdns_alloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_service_t *service, + mdns_host_item_t *host, bool flush, bool bye); + +mdns_tx_packet_t *_mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool include_ip); +mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *probe); +void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p); +void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, mdns_subtype_t *remove_subtypes); +bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], size_t services_len, bool flush, bool bye); + +#ifdef __cplusplus +} +#endif diff --git a/components/mdns/private_include/mdns_utils.h b/components/mdns/private_include/mdns_utils.h index 2d3722a03a..9bf4409513 100644 --- a/components/mdns/private_include/mdns_utils.h +++ b/components/mdns/private_include/mdns_utils.h @@ -47,19 +47,24 @@ const uint8_t *_mdns_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdn const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len); +bool is_mdns_server(void); const char *mdns_utils_get_global_hostname(void); mdns_srv_item_t *mdns_utils_get_services(void); mdns_host_item_t *mdns_utils_get_hosts(void); +mdns_host_item_t *mdns_utils_get_selfhost(void); void mdns_utils_set_global_hostname(const char *hostname); const char *mdns_utils_get_instance(void); void mdns_utils_set_instance(const char *instance); mdns_search_once_t *mdns_utils_get_search(void); -mdns_search_once_t *mdns_utils_get_search(void); mdns_browse_t *mdns_utils_get_browse(void); mdns_tx_packet_t *mdns_utils_get_tx_packet(void); bool mdns_utils_is_probing(mdns_rx_packet_t *packet); +bool mdns_utils_is_pcb_after_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +bool mdns_utils_is_pcb_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); bool mdns_utils_after_probing(mdns_rx_packet_t *packet); void mdns_utils_probe_failed(mdns_rx_packet_t *packet); + +void _mdns_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after); void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe); void _mdns_restart_all_pcbs_no_instance(void); void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); diff --git a/components/mdns/tests/test_afl_fuzz_host/Makefile b/components/mdns/tests/test_afl_fuzz_host/Makefile index 6f6b16c0fc..d55193c647 100644 --- a/components/mdns/tests/test_afl_fuzz_host/Makefile +++ b/components/mdns/tests/test_afl_fuzz_host/Makefile @@ -51,7 +51,7 @@ else endif CPP=$(CC) LD=$(CC) -OBJECTS=esp32_mock.o mdns.o test.o esp_netif_mock.o mdns_utils.o mdns_packet.o +OBJECTS=esp32_mock.o mdns.o test.o esp_netif_mock.o mdns_utils.o mdns_packet.o mdns_browser.o mdns_querier.o mdns_send.o OS := $(shell uname) ifeq ($(OS),Darwin) From a569c638c2338e040811b9f06caefbb73647b341 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Sun, 9 Mar 2025 18:21:26 +0100 Subject: [PATCH 04/27] feat(mdns): Add responder module --- components/mdns/CMakeLists.txt | 2 +- components/mdns/mdns.c | 862 +----------------- components/mdns/mdns_netif.c | 540 +++++++++++ components/mdns/mdns_packet.c | 36 +- components/mdns/mdns_responder.c | 52 +- components/mdns/mdns_send.c | 356 ++++++++ components/mdns/private_include/mdns_netif.h | 8 + .../mdns/private_include/mdns_private.h | 2 +- .../mdns/private_include/mdns_responder.h | 19 + components/mdns/private_include/mdns_send.h | 8 + components/mdns/private_include/mdns_utils.h | 11 +- .../mdns/tests/test_afl_fuzz_host/Makefile | 2 +- 12 files changed, 1031 insertions(+), 867 deletions(-) create mode 100644 components/mdns/private_include/mdns_responder.h diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 22745eb6fa..a6273c972a 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -13,7 +13,7 @@ endif() set(MDNS_MEMORY "mdns_mem_caps.c") set(MDNS_CORE "mdns.c" "mdns_packet.c" "mdns_utils.c" "mdns_debug.c" "mdns_browser.c" "mdns_send.c" "mdns_netif.c" - "mdns_querier.c") + "mdns_querier.c" "mdns_responder.c") #set(MDNS_CORE "mdns.c" ) idf_build_get_property(target IDF_TARGET) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 0198abc518..2ff92ee90b 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -23,22 +23,9 @@ #include "mdns_netif.h" #include "mdns_send.h" #include "mdns_querier.h" +#include "mdns_responder.h" -#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 -#endif - -#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP) -#include "esp_wifi.h" -#endif - #ifndef ARRAY_SIZE #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) #endif @@ -63,151 +50,21 @@ static StackType_t *_mdns_stack_buffer; //static bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye); -static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); +esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); //static void _mdns_query_results_free(mdns_result_t *results); -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 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_if(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 *esp_netif_from_preset_if(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; - } -} -/** - * @brief Gets the actual esp_netif pointer from the internal network interface list - * - * The supplied ordinal number could - * - point to a predef netif -> "STA", "AP", "ETH" - * - if no entry in the list (NULL) -> check if the system added this netif - * - point to a custom netif -> just return the entry in the list - * - users is responsible for the lifetime of this netif (to be valid between mdns-init -> deinit) - * - * @param tcpip_if Ordinal number of the interface - * @return Pointer ot the esp_netif object if the interface is available, NULL otherwise - */ -esp_netif_t *_mdns_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 = esp_netif_from_preset_if(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 - */ -static inline void _mdns_clean_netif_ptr(mdns_if_t tcpip_if) +mdns_pcb_t *mdns_utils_get_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { - 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 _mdns_get_if_from_esp_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 = esp_netif_from_preset_if(s_esp_netifs[i].predef_if); - } - if (esp_netif == s_esp_netifs[i].netif) { - return i; - } - } - return MDNS_MAX_INTERFACES; -} - -/** - * @brief Check if interface is duplicate (two interfaces on the same subnet) - */ -bool _mdns_if_is_dup(mdns_if_t tcpip_if) -{ - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); - if (other_if == MDNS_MAX_INTERFACES) { - return false; - } - if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP - || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state == PCB_DUP - || _mdns_server->interfaces[other_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP - || _mdns_server->interfaces[other_if].pcbs[MDNS_IP_PROTOCOL_V6].state == PCB_DUP - ) { - return true; - } - return false; + return &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; } const char *mdns_utils_get_global_hostname(void) @@ -277,10 +134,10 @@ static inline bool _str_null_or_empty(const char *str) return (str == NULL || *str == 0); } -mdns_tx_packet_t *mdns_utils_get_tx_packet(void) -{ - return _mdns_server->tx_queue_head; -} +//mdns_tx_packet_t *mdns_utils_get_tx_packet(void) +//{ +// return _mdns_server->tx_queue_head; +//} bool mdns_utils_is_pcb_after_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { @@ -348,17 +205,7 @@ esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) return ESP_OK; } -/** - * @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_get_other_if(mdns_if_t tcpip_if) -{ - if (tcpip_if < MDNS_MAX_INTERFACES) { - return s_esp_netifs[tcpip_if].duplicate; - } - return MDNS_MAX_INTERFACES; -} + #ifdef CONFIG_LWIP_IPV6 /** @@ -388,120 +235,7 @@ bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) -/** - * @brief schedules a packet to be sent after given milliseconds - * - * @param packet the packet - * @param ms_after number of milliseconds after which the packet should be dispatched - */ -void _mdns_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after) -{ - if (!packet) { - return; - } - packet->send_at = (xTaskGetTickCount() * portTICK_PERIOD_MS) + ms_after; - packet->next = NULL; - if (!_mdns_server->tx_queue_head || _mdns_server->tx_queue_head->send_at > packet->send_at) { - packet->next = _mdns_server->tx_queue_head; - _mdns_server->tx_queue_head = packet; - return; - } - mdns_tx_packet_t *q = _mdns_server->tx_queue_head; - while (q->next && q->next->send_at <= packet->send_at) { - q = q->next; - } - packet->next = q->next; - q->next = packet; -} -/** - * @brief free all packets scheduled for sending - */ -static void _mdns_clear_tx_queue_head(void) -{ - mdns_tx_packet_t *q; - while (_mdns_server->tx_queue_head) { - q = _mdns_server->tx_queue_head; - _mdns_server->tx_queue_head = _mdns_server->tx_queue_head->next; - _mdns_free_tx_packet(q); - } -} - -/** - * @brief clear packets scheduled for sending on a specific interface - * - * @param tcpip_if the interface - * @param ip_protocol pcb type V4/V6 - */ -static void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_tx_packet_t *q, * p; - while (_mdns_server->tx_queue_head && _mdns_server->tx_queue_head->tcpip_if == tcpip_if && _mdns_server->tx_queue_head->ip_protocol == ip_protocol) { - q = _mdns_server->tx_queue_head; - _mdns_server->tx_queue_head = _mdns_server->tx_queue_head->next; - _mdns_free_tx_packet(q); - } - if (_mdns_server->tx_queue_head) { - q = _mdns_server->tx_queue_head; - while (q->next) { - if (q->next->tcpip_if == tcpip_if && q->next->ip_protocol == ip_protocol) { - p = q->next; - q->next = p->next; - _mdns_free_tx_packet(p); - } else { - q = q->next; - } - } - } -} - -/** - * @brief get the next packet scheduled for sending on a specific interface - * - * @param tcpip_if the interface - * @param ip_protocol pcb type V4/V6 - */ -static mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_tx_packet_t *q = _mdns_server->tx_queue_head; - while (q) { - if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol) { - return q; - } - q = q->next; - } - return NULL; -} - - -/** - * @brief Remove and free answer from answer list (destination) - */ -static void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service) -{ - mdns_out_answer_t *d = *destination; - if (!d) { - return; - } - mdns_srv_item_t s = {NULL, NULL}; - if (!service) { - service = &s; - } - if (d->type == type && d->service == service->service) { - *destination = d->next; - mdns_mem_free(d); - return; - } - while (d->next) { - mdns_out_answer_t *a = d->next; - if (a->type == type && a->service == service->service) { - d->next = a->next; - mdns_mem_free(a); - return; - } - d = d->next; - } -} @@ -609,31 +343,7 @@ void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, md } } -/** - * @brief Restart the responder on particular PCB - */ -static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - size_t srv_count = 0; - mdns_srv_item_t *a = _mdns_server->services; - while (a) { - srv_count++; - a = a->next; - } - if (srv_count == 0) { - // proble only IP - _mdns_init_pcb_probe(tcpip_if, ip_protocol, NULL, 0, true); - return; - } - mdns_srv_item_t *services[srv_count]; - size_t i = 0; - a = _mdns_server->services; - while (a) { - services[i++] = a; - a = a->next; - } - _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, srv_count, true); -} + /** * @brief Send by for particular services @@ -656,48 +366,6 @@ static void _mdns_send_bye(mdns_srv_item_t **services, size_t len, bool include_ -/** - * @brief Send announcement on particular PCB - */ -static void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) -{ - mdns_pcb_t *_pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; - size_t i; - if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { - if (PCB_STATE_IS_PROBING(_pcb)) { - _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, len, include_ip); - } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { - mdns_tx_packet_t *p = _mdns_get_next_pcb_packet(tcpip_if, ip_protocol); - if (p) { - for (i = 0; i < len; i++) { - if (!_mdns_alloc_answer(&p->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) - || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, false) - || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, false) - || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, false)) { - break; - } - } - if (include_ip) { - _mdns_dealloc_answer(&p->additional, MDNS_TYPE_A, NULL); - _mdns_dealloc_answer(&p->additional, MDNS_TYPE_AAAA, NULL); - _mdns_append_host_list_in_services(&p->answers, services, len, true, false); - } - _pcb->state = PCB_ANNOUNCE_1; - } - } else if (_pcb->state == PCB_RUNNING) { - - if (_str_null_or_empty(_mdns_server->hostname)) { - return; - } - - _pcb->state = PCB_ANNOUNCE_1; - mdns_tx_packet_t *p = _mdns_create_announce_packet(tcpip_if, ip_protocol, services, len, include_ip); - if (p) { - _mdns_schedule_tx_packet(p, 0); - } - } - } -} /** * @brief Send probe on all active PCBs @@ -962,114 +630,8 @@ static mdns_service_t *_mdns_create_service(const char *service, const char *pro return NULL; } -/** - * @brief Remove and free service answer from answer list (destination) - */ -static void _mdns_dealloc_scheduled_service_answers(mdns_out_answer_t **destination, mdns_service_t *service) -{ - mdns_out_answer_t *d = *destination; - if (!d) { - return; - } - while (d && d->service == service) { - *destination = d->next; - mdns_mem_free(d); - d = *destination; - } - while (d && d->next) { - mdns_out_answer_t *a = d->next; - if (a->service == service) { - d->next = a->next; - mdns_mem_free(a); - } else { - d = d->next; - } - } -} -/** - * @brief Find, remove and free answers and scheduled packets for service - */ -static void _mdns_remove_scheduled_service_packets(mdns_service_t *service) -{ - if (!service) { - return; - } - mdns_tx_packet_t *p = NULL; - mdns_tx_packet_t *q = _mdns_server->tx_queue_head; - while (q) { - bool had_answers = (q->answers != NULL); - - _mdns_dealloc_scheduled_service_answers(&(q->answers), service); - _mdns_dealloc_scheduled_service_answers(&(q->additional), service); - _mdns_dealloc_scheduled_service_answers(&(q->servers), service); - - - mdns_pcb_t *_pcb = &_mdns_server->interfaces[q->tcpip_if].pcbs[q->ip_protocol]; - if (mdns_is_netif_ready(q->tcpip_if, q->ip_protocol)) { - if (PCB_STATE_IS_PROBING(_pcb)) { - uint8_t i; - //check if we are probing this service - for (i = 0; i < _pcb->probe_services_len; i++) { - mdns_srv_item_t *s = _pcb->probe_services[i]; - if (s->service == service) { - break; - } - } - if (i < _pcb->probe_services_len) { - if (_pcb->probe_services_len > 1) { - uint8_t n; - for (n = (i + 1); n < _pcb->probe_services_len; n++) { - _pcb->probe_services[n - 1] = _pcb->probe_services[n]; - } - _pcb->probe_services_len--; - } else { - _pcb->probe_services_len = 0; - mdns_mem_free(_pcb->probe_services); - _pcb->probe_services = NULL; - if (!_pcb->probe_ip) { - _pcb->probe_running = false; - _pcb->state = PCB_RUNNING; - } - } - if (q->questions) { - mdns_out_question_t *qsn = NULL; - mdns_out_question_t *qs = q->questions; - if (qs->type == MDNS_TYPE_ANY - && qs->service && strcmp(qs->service, service->service) == 0 - && qs->proto && strcmp(qs->proto, service->proto) == 0) { - q->questions = q->questions->next; - mdns_mem_free(qs); - } else while (qs->next) { - qsn = qs->next; - if (qsn->type == MDNS_TYPE_ANY - && qsn->service && strcmp(qsn->service, service->service) == 0 - && qsn->proto && strcmp(qsn->proto, service->proto) == 0) { - qs->next = qsn->next; - mdns_mem_free(qsn); - break; - } - qs = qs->next; - } - } - } - } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { - //if answers were cleared, set to running - if (had_answers && q->answers == NULL) { - _pcb->state = PCB_RUNNING; - } - } - } - - p = q; - q = q->next; - if (!p->questions && !p->answers && !p->additional && !p->servers) { - queueDetach(mdns_tx_packet_t, _mdns_server->tx_queue_head, p); - _mdns_free_tx_packet(p); - } - } -} static void _mdns_free_subtype(mdns_subtype_t *subtype) { @@ -1120,44 +682,7 @@ static void _mdns_free_service(mdns_service_t *service) -static esp_err_t mdns_pcb_deinit_local(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_proto) -{ - esp_err_t err = _mdns_pcb_deinit(tcpip_if, ip_proto); - mdns_pcb_t *_pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_proto]; - if (_pcb == NULL || err != ESP_OK) { - return err; - } - mdns_mem_free(_pcb->probe_services); - _pcb->state = PCB_OFF; - _pcb->probe_ip = false; - _pcb->probe_services = NULL; - _pcb->probe_services_len = 0; - _pcb->probe_running = false; - _pcb->failed_probes = 0; - return ESP_OK; -} -/** - * @brief Set interface as duplicate if another is found on the same subnet - */ -void _mdns_dup_interface(mdns_if_t tcpip_if) -{ - uint8_t i; - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); - if (other_if == MDNS_MAX_INTERFACES) { - return; // no other interface found - } - for (i = 0; i < MDNS_IP_PROTOCOL_MAX; i++) { - if (mdns_is_netif_ready(other_if, i)) { - //stop this interface and mark as dup - if (mdns_is_netif_ready(tcpip_if, i)) { - _mdns_clear_pcb_tx_queue_head(tcpip_if, i); - mdns_pcb_deinit_local(tcpip_if, i); - } - _mdns_server->interfaces[tcpip_if].pcbs[i].state = PCB_DUP; - _mdns_announce_pcb(other_if, i, NULL, 0, true); - } - } -} + @@ -1289,38 +814,9 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) void mdns_parse_packet(mdns_rx_packet_t *packet); -/** - * @brief Enable mDNS interface - */ -void _mdns_enable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - if (!mdns_is_netif_ready(tcpip_if, ip_protocol)) { - if (_mdns_pcb_init(tcpip_if, ip_protocol)) { - _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].failed_probes = 0; - return; - } - } - _mdns_restart_pcb(tcpip_if, ip_protocol); -} -/** - * @brief Disable mDNS interface - */ -void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - _mdns_clean_netif_ptr(tcpip_if); - if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { - _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); - mdns_pcb_deinit_local(tcpip_if, ip_protocol); - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); - if (other_if != MDNS_MAX_INTERFACES && _mdns_server->interfaces[other_if].pcbs[ip_protocol].state == PCB_DUP) { - _mdns_server->interfaces[other_if].pcbs[ip_protocol].state = PCB_OFF; - _mdns_enable_pcb(other_if, ip_protocol); - } - } - _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state = PCB_OFF; -} + #ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES static inline char nibble_to_hex(int var) @@ -1400,110 +896,6 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) #endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ } -/** - * @brief Dispatch interface changes based on system events - */ -static inline void post_mdns_disable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) -{ - mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(preset_if), protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_DISABLE_IP4 : MDNS_EVENT_DISABLE_IP6); -} - -static inline void post_mdns_enable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) -{ - mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(preset_if), protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_ENABLE_IP4 : MDNS_EVENT_ENABLE_IP6); -} - -static inline void post_mdns_announce_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) -{ - mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(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 -void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) -{ - if (!_mdns_server) { - return; - } - - esp_netif_dhcp_status_t dcst; -#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP) - if (event_base == WIFI_EVENT) { - switch (event_id) { - case WIFI_EVENT_STA_CONNECTED: - if (!esp_netif_dhcpc_get_status(esp_netif_from_preset_if(MDNS_IF_STA), &dcst)) { - if (dcst == ESP_NETIF_DHCP_STOPPED) { - post_mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); - } - } - break; - case WIFI_EVENT_STA_DISCONNECTED: - post_mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); - post_mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6); - break; - case WIFI_EVENT_AP_START: - post_mdns_enable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); - break; - case WIFI_EVENT_AP_STOP: - post_mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); - post_mdns_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) { - switch (event_id) { - case ETHERNET_EVENT_CONNECTED: - if (!esp_netif_dhcpc_get_status(esp_netif_from_preset_if(MDNS_IF_ETH), &dcst)) { - if (dcst == ESP_NETIF_DHCP_STOPPED) { - post_mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); - } - } - break; - case ETHERNET_EVENT_DISCONNECTED: - post_mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); - post_mdns_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_mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); - post_mdns_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_mdns_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 = _mdns_get_if_from_esp_netif(event->esp_netif); - if (mdns_if >= MDNS_MAX_INTERFACES) { - return; - } - post_mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); - post_mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); - mdns_browse_t *browse = _mdns_server->browse; - while (browse) { - _mdns_browse_send(browse, mdns_if); - browse = browse->next; - } - } - break; - default: - break; - } - } -} -#endif /* CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH */ /* * MDNS Search @@ -1618,62 +1010,7 @@ static void _mdns_search_add(mdns_search_once_t *search) -static void _mdns_tx_handle_packet(mdns_tx_packet_t *p) -{ - mdns_tx_packet_t *a = NULL; - mdns_out_question_t *q = NULL; - mdns_pcb_t *pcb = &_mdns_server->interfaces[p->tcpip_if].pcbs[p->ip_protocol]; - uint32_t send_after = 1000; - if (pcb->state == PCB_OFF) { - _mdns_free_tx_packet(p); - return; - } - _mdns_dispatch_tx_packet(p); - - switch (pcb->state) { - case PCB_PROBE_1: - q = p->questions; - while (q) { - q->unicast = false; - q = q->next; - } - //fallthrough - case PCB_PROBE_2: - _mdns_schedule_tx_packet(p, 250); - pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); - break; - case PCB_PROBE_3: - a = _mdns_create_announce_from_probe(p); - if (!a) { - _mdns_schedule_tx_packet(p, 250); - break; - } - pcb->probe_running = false; - pcb->probe_ip = false; - pcb->probe_services_len = 0; - pcb->failed_probes = 0; - mdns_mem_free(pcb->probe_services); - pcb->probe_services = NULL; - _mdns_free_tx_packet(p); - p = a; - send_after = 250; - //fallthrough - case PCB_ANNOUNCE_1: - //fallthrough - case PCB_ANNOUNCE_2: - _mdns_schedule_tx_packet(p, send_after); - pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); - break; - case PCB_ANNOUNCE_3: - pcb->state = PCB_RUNNING; - _mdns_free_tx_packet(p); - break; - default: - _mdns_free_tx_packet(p); - break; - } -} void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) { @@ -1794,18 +1131,9 @@ static void _mdns_execute_action(mdns_action_t *action) _mdns_browse_finish(action->data.browse_add.browse); break; - case ACTION_TX_HANDLE: { - mdns_tx_packet_t *p = _mdns_server->tx_queue_head; - // packet to be handled should be at tx head, but must be consistent with the one pushed to action queue - if (p && p == action->data.tx_handle.packet && p->queued) { - p->queued = false; // clearing, as the packet might be reused (pushed and transmitted again) - _mdns_server->tx_queue_head = p->next; - _mdns_tx_handle_packet(p); - } else { - ESP_LOGD(TAG, "Skipping transmit of an unexpected packet!"); - } - } - break; + case ACTION_TX_HANDLE: + mdns_send_handle_tx_packet(action->data.tx_handle.packet); + break; case ACTION_RX_HANDLE: mdns_parse_packet(action->data.rx_handle.packet); _mdns_packet_free(action->data.rx_handle.packet); @@ -1867,7 +1195,7 @@ static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_o static void _mdns_scheduler_run(void) { MDNS_SERVICE_LOCK(); - mdns_tx_packet_t *p = _mdns_server->tx_queue_head; + mdns_tx_packet_t *p = _mdns_get_next_tx_packet(); mdns_action_t *action = NULL; // find first unqueued packet @@ -2072,7 +1400,7 @@ static esp_err_t _mdns_service_task_stop(void) return ESP_OK; } -static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action) +esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action) { if (!_mdns_server || mdns_if >= MDNS_MAX_INTERFACES) { return ESP_ERR_INVALID_STATE; @@ -2093,92 +1421,16 @@ static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_ return ESP_OK; } -static inline void set_default_duplicated_interfaces(void) +void mdns_service_lock(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; - } -} - -static inline void 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, mdns_preset_if_handle_system_event); -#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, mdns_preset_if_handle_system_event); -#endif -#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH - esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event); -#endif -} - -/* - * Public Methods - * */ - -esp_err_t mdns_netif_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action) -{ - return mdns_post_custom_action_tcpip_if(_mdns_get_if_from_esp_netif(esp_netif), event_action); -} - -esp_err_t mdns_register_netif(esp_netif_t *esp_netif) -{ - if (!_mdns_server) { - return ESP_ERR_INVALID_STATE; - } - - esp_err_t err = ESP_ERR_NO_MEM; MDNS_SERVICE_LOCK(); - for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; ++i) { - if (s_esp_netifs[i].netif == esp_netif) { - MDNS_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_SERVICE_UNLOCK(); - return err; } -esp_err_t mdns_unregister_netif(esp_netif_t *esp_netif) +void mdns_service_unlock(void) { - if (!_mdns_server) { - return ESP_ERR_INVALID_STATE; - } - - esp_err_t err = ESP_ERR_NOT_FOUND; - MDNS_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_SERVICE_UNLOCK(); - return err; } - esp_err_t mdns_init(void) { esp_err_t err = ESP_OK; @@ -2193,10 +1445,10 @@ esp_err_t mdns_init(void) return ESP_ERR_NO_MEM; } memset((uint8_t *)_mdns_server, 0, sizeof(mdns_server_t)); - // 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; - } +// // 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; +// } _mdns_server->action_queue = xQueueCreate(MDNS_ACTION_QUEUE_LEN, sizeof(mdns_action_t *)); if (!_mdns_server->action_queue) { @@ -2210,46 +1462,12 @@ esp_err_t mdns_init(void) goto free_queue; } -#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, mdns_preset_if_handle_system_event, 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, mdns_preset_if_handle_system_event, 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, mdns_preset_if_handle_system_event, 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_get_esp_netif(i), &tmp_addr6) && !_ipv6_address_is_zero(tmp_addr6)) { - _mdns_enable_pcb(i, MDNS_IP_PROTOCOL_V6); - } -#endif -#ifdef CONFIG_LWIP_IPV4 - if (!esp_netif_get_ip_info(_mdns_get_esp_netif(i), &if_ip_info) && if_ip_info.ip.addr) { - _mdns_enable_pcb(i, MDNS_IP_PROTOCOL_V4); - } -#endif + if (mdns_netif_init() != ESP_OK) { + err = ESP_FAIL; + goto free_action_sema; } + if (_mdns_service_task_start()) { //service start failed! err = ESP_FAIL; @@ -2259,15 +1477,16 @@ esp_err_t mdns_init(void) return ESP_OK; free_all_and_disable_pcbs: - for (i = 0; i < MDNS_MAX_INTERFACES; i++) { - _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V6); - _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V4); - s_esp_netifs[i].duplicate = MDNS_MAX_INTERFACES; - } -#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH -free_event_handlers: - unregister_predefined_handlers(); -#endif + mdns_netif_deinit(); +// for (i = 0; i < MDNS_MAX_INTERFACES; i++) { +// _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V6); +// _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V4); +// s_esp_netifs[i].duplicate = MDNS_MAX_INTERFACES; +// } +//#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH +free_action_sema: +// unregister_predefined_handlers(); +//#endif vSemaphoreDelete(_mdns_server->action_sema); free_queue: vQueueDelete(_mdns_server->action_queue); @@ -2279,7 +1498,6 @@ esp_err_t mdns_init(void) void mdns_free(void) { - uint8_t i, j; if (!_mdns_server) { return; } @@ -2292,11 +1510,7 @@ void mdns_free(void) _mdns_service_task_stop(); // at this point, the service task is deleted, so we can destroy the stack size mdns_mem_task_free(_mdns_stack_buffer); - for (i = 0; i < MDNS_MAX_INTERFACES; i++) { - for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - mdns_pcb_deinit_local(i, j); - } - } + mdns_netif_free(); mdns_mem_free((char *)_mdns_server->hostname); mdns_mem_free((char *)_mdns_server->instance); if (_mdns_server->action_queue) { diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c index 65642a05de..859f5c518b 100644 --- a/components/mdns/mdns_netif.c +++ b/components/mdns/mdns_netif.c @@ -7,6 +7,7 @@ #include #include "esp_log.h" #include "esp_check.h" +#include "esp_event.h" #include "mdns.h" #include "mdns_private.h" #include "mdns_networking.h" @@ -14,3 +15,542 @@ #include "mdns_utils.h" #include "mdns_debug.h" #include "mdns_browse.h" +#include "mdns_netif.h" +#include "mdns_send.h" +#include "mdns_responder.h" +#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 +#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_get_other_if(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_if(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 *esp_netif_from_preset_if(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; + } +} + +/** + * @brief Gets the actual esp_netif pointer from the internal network interface list + * + * The supplied ordinal number could + * - point to a predef netif -> "STA", "AP", "ETH" + * - if no entry in the list (NULL) -> check if the system added this netif + * - point to a custom netif -> just return the entry in the list + * - users is responsible for the lifetime of this netif (to be valid between mdns-init -> deinit) + * + * @param tcpip_if Ordinal number of the interface + * @return Pointer ot the esp_netif object if the interface is available, NULL otherwise + */ +esp_netif_t *_mdns_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 = esp_netif_from_preset_if(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 + */ +static inline void _mdns_clean_netif_ptr(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 _mdns_get_if_from_esp_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 = esp_netif_from_preset_if(s_esp_netifs[i].predef_if); + } + if (esp_netif == s_esp_netifs[i].netif) { + return i; + } + } + return MDNS_MAX_INTERFACES; +} +/** + * @brief Check if interface is duplicate (two interfaces on the same subnet) + */ +bool _mdns_if_is_dup(mdns_if_t tcpip_if) +{ + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if == MDNS_MAX_INTERFACES) { + return false; + } + mdns_pcb_state_t state_v4 = mdns_utils_get_pcb(tcpip_if, MDNS_IP_PROTOCOL_V4)->state; + mdns_pcb_state_t state_v6 = mdns_utils_get_pcb(tcpip_if, MDNS_IP_PROTOCOL_V6)->state; + mdns_pcb_state_t other_state_v4 = mdns_utils_get_pcb(other_if, MDNS_IP_PROTOCOL_V4)->state; + mdns_pcb_state_t other_state_v6 = mdns_utils_get_pcb(other_if, MDNS_IP_PROTOCOL_V6)->state; + + if (state_v4 == PCB_DUP || state_v6 == PCB_DUP || other_state_v4 == PCB_DUP || other_state_v6 == PCB_DUP) { + return true; + } + return false; +} + +static esp_err_t mdns_pcb_deinit_local(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_proto) +{ + esp_err_t err = _mdns_pcb_deinit(tcpip_if, ip_proto); + mdns_pcb_t *_pcb = mdns_utils_get_pcb(tcpip_if, ip_proto); + if (_pcb == NULL || err != ESP_OK) { + return err; + } + mdns_mem_free(_pcb->probe_services); + _pcb->state = PCB_OFF; + _pcb->probe_ip = false; + _pcb->probe_services = NULL; + _pcb->probe_services_len = 0; + _pcb->probe_running = false; + _pcb->failed_probes = 0; + return ESP_OK; +} + +/** + * @brief Restart the responder on particular PCB + */ +static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + size_t srv_count = 0; + mdns_srv_item_t *a = mdns_utils_get_services(); + while (a) { + srv_count++; + a = a->next; + } + if (srv_count == 0) { + // proble only IP + _mdns_init_pcb_probe(tcpip_if, ip_protocol, NULL, 0, true); + return; + } + mdns_srv_item_t *services[srv_count]; + size_t i = 0; + a = mdns_utils_get_services(); + while (a) { + services[i++] = a; + a = a->next; + } + _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, srv_count, true); +} + +/** + * @brief Disable mDNS interface + */ +void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + _mdns_clean_netif_ptr(tcpip_if); + + if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { + _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); + mdns_pcb_deinit_local(tcpip_if, ip_protocol); + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if != MDNS_MAX_INTERFACES && mdns_utils_get_pcb(other_if, ip_protocol)->state == PCB_DUP) { + mdns_utils_get_pcb(other_if, ip_protocol)->state = PCB_OFF; + _mdns_enable_pcb(other_if, ip_protocol); + } + } + mdns_utils_get_pcb(tcpip_if, ip_protocol)->state = PCB_OFF; +} + +/** + * @brief Enable mDNS interface + */ +void _mdns_enable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (!mdns_is_netif_ready(tcpip_if, ip_protocol)) { + if (_mdns_pcb_init(tcpip_if, ip_protocol)) { + mdns_utils_get_pcb(tcpip_if, ip_protocol)->failed_probes = 0; + return; + } + } + _mdns_restart_pcb(tcpip_if, ip_protocol); +} + +/** + * @brief Set interface as duplicate if another is found on the same subnet + */ +void _mdns_dup_interface(mdns_if_t tcpip_if) +{ + uint8_t i; + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if == MDNS_MAX_INTERFACES) { + return; // no other interface found + } + for (i = 0; i < MDNS_IP_PROTOCOL_MAX; i++) { + if (mdns_is_netif_ready(other_if, i)) { + //stop this interface and mark as dup + if (mdns_is_netif_ready(tcpip_if, i)) { + _mdns_clear_pcb_tx_queue_head(tcpip_if, i); + mdns_pcb_deinit_local(tcpip_if, i); + } + mdns_utils_get_pcb(tcpip_if, i)->state = PCB_DUP; +// _mdns_server->interfaces[tcpip_if].pcbs[i].state = PCB_DUP; + _mdns_announce_pcb(other_if, i, NULL, 0, true); + } + } +} + +/** + * @brief Dispatch interface changes based on system events + */ +static inline void post_mdns_disable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) +{ + mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(preset_if), protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_DISABLE_IP4 : MDNS_EVENT_DISABLE_IP6); +} + +static inline void post_mdns_enable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) +{ + mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(preset_if), protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_ENABLE_IP4 : MDNS_EVENT_ENABLE_IP6); +} + +static inline void post_mdns_announce_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) +{ + mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(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 +void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + if (!is_mdns_server()) { + return; + } + + esp_netif_dhcp_status_t dcst; +#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP) + if (event_base == WIFI_EVENT) { + switch (event_id) { + case WIFI_EVENT_STA_CONNECTED: + if (!esp_netif_dhcpc_get_status(esp_netif_from_preset_if(MDNS_IF_STA), &dcst)) { + if (dcst == ESP_NETIF_DHCP_STOPPED) { + post_mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + } + } + break; + case WIFI_EVENT_STA_DISCONNECTED: + post_mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + post_mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6); + break; + case WIFI_EVENT_AP_START: + post_mdns_enable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); + break; + case WIFI_EVENT_AP_STOP: + post_mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); + post_mdns_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) { + switch (event_id) { + case ETHERNET_EVENT_CONNECTED: + if (!esp_netif_dhcpc_get_status(esp_netif_from_preset_if(MDNS_IF_ETH), &dcst)) { + if (dcst == ESP_NETIF_DHCP_STOPPED) { + post_mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + } + } + break; + case ETHERNET_EVENT_DISCONNECTED: + post_mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + post_mdns_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_mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + post_mdns_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_mdns_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 = _mdns_get_if_from_esp_netif(event->esp_netif); + if (mdns_if >= MDNS_MAX_INTERFACES) { + return; + } + post_mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); + post_mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); + mdns_browse_t *browse = mdns_utils_get_browse(); + while (browse) { + _mdns_browse_send(browse, mdns_if); + browse = browse->next; + } + } + 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 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, mdns_preset_if_handle_system_event); +#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, mdns_preset_if_handle_system_event); +#endif +#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH + esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event); +#endif +} + +/* + * Public Methods + * */ + +esp_err_t mdns_netif_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action) +{ + return mdns_post_custom_action_tcpip_if(_mdns_get_if_from_esp_netif(esp_netif), event_action); +} + +esp_err_t mdns_register_netif(esp_netif_t *esp_netif) +{ + if (!is_mdns_server()) { + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = ESP_ERR_NO_MEM; + mdns_service_lock(); + for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; ++i) { + if (s_esp_netifs[i].netif == esp_netif) { + mdns_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_service_unlock(); + return err; +} + +esp_err_t mdns_unregister_netif(esp_netif_t *esp_netif) +{ + if (!is_mdns_server()) { + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = ESP_ERR_NOT_FOUND; + mdns_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_service_lock(); + return err; +} + +esp_err_t mdns_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, mdns_preset_if_handle_system_event, 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, mdns_preset_if_handle_system_event, 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, mdns_preset_if_handle_system_event, 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_get_esp_netif(i), &tmp_addr6) && !_ipv6_address_is_zero(tmp_addr6)) { + _mdns_enable_pcb(i, MDNS_IP_PROTOCOL_V6); + } +#endif +#ifdef CONFIG_LWIP_IPV4 + if (!esp_netif_get_ip_info(_mdns_get_esp_netif(i), &if_ip_info) && if_ip_info.ip.addr) { + _mdns_enable_pcb(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: + unregister_predefined_handlers(); +#endif + return err; +} + +esp_err_t mdns_netif_deinit(void) +{ + for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { + _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V6); + _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V4); + s_esp_netifs[i].duplicate = MDNS_MAX_INTERFACES; + } + return ESP_OK; +} + +esp_err_t mdns_netif_free(void) +{ + for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (int j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + mdns_pcb_deinit_local(i, j); + } + } + return ESP_OK; + +} diff --git a/components/mdns/mdns_packet.c b/components/mdns/mdns_packet.c index 73b13a0572..f5d3f69312 100644 --- a/components/mdns/mdns_packet.c +++ b/components/mdns/mdns_packet.c @@ -12,6 +12,8 @@ #include "esp_log.h" #include "mdns_utils.h" #include "mdns_debug.h" +#include "mdns_netif.h" +#include "mdns_send.h" static const char *TAG = "mdns_packet"; @@ -1006,39 +1008,7 @@ static bool _mdns_name_is_selfhosted(mdns_name_t *name) } -/** - * @brief Find, remove and free answer from the scheduled packets - */ -static void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service) -{ - mdns_srv_item_t s = {NULL, NULL}; - if (!service) { - service = &s; - } - mdns_tx_packet_t *q = mdns_utils_get_tx_packet(); - while (q) { - if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol && q->distributed) { - mdns_out_answer_t *a = q->answers; - if (a) { - if (a->type == type && a->service == service->service) { - q->answers = q->answers->next; - mdns_mem_free(a); - } else { - while (a->next) { - if (a->next->type == type && a->next->service == service->service) { - mdns_out_answer_t *b = a->next; - a->next = b->next; - mdns_mem_free(b); - break; - } - a = a->next; - } - } - } - } - q = q->next; - } -} + /** diff --git a/components/mdns/mdns_responder.c b/components/mdns/mdns_responder.c index a74c48ca5a..e3b2f7af91 100644 --- a/components/mdns/mdns_responder.c +++ b/components/mdns/mdns_responder.c @@ -3,11 +3,53 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include #include "mdns_private.h" #include "mdns_networking.h" -#include "mdns_types.h" +#include "mdns_responder.h" +#include "mdns_netif.h" +#include "mdns_utils.h" +#include "mdns_send.h" -// Response generation -static esp_err_t mdns_send_response(mdns_out_answer_t *answers, mdns_tx_packet_t *packet); -static void mdns_announce_service(mdns_service_t *service, bool bye); -static void mdns_announce_host(bool bye); +/** + * @brief Send announcement on particular PCB + */ +void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) +{ + mdns_pcb_t *_pcb = mdns_utils_get_pcb(tcpip_if, ip_protocol); + size_t i; + if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { + if (PCB_STATE_IS_PROBING(_pcb)) { + _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, len, include_ip); + } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { + mdns_tx_packet_t *p = _mdns_get_next_pcb_packet(tcpip_if, ip_protocol); + if (p) { + for (i = 0; i < len; i++) { + if (!_mdns_alloc_answer(&p->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, false)) { + break; + } + } + if (include_ip) { + _mdns_dealloc_answer(&p->additional, MDNS_TYPE_A, NULL); + _mdns_dealloc_answer(&p->additional, MDNS_TYPE_AAAA, NULL); + _mdns_append_host_list_in_services(&p->answers, services, len, true, false); + } + _pcb->state = PCB_ANNOUNCE_1; + } + } else if (_pcb->state == PCB_RUNNING) { + + if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { + return; + } + + _pcb->state = PCB_ANNOUNCE_1; + mdns_tx_packet_t *p = _mdns_create_announce_packet(tcpip_if, ip_protocol, services, len, include_ip); + if (p) { + _mdns_schedule_tx_packet(p, 0); + } + } + } +} diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index ad918036c7..90f1ebc9c9 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -17,6 +17,8 @@ static const char *TAG = "mdns_send"; static const char *MDNS_SUB_STR = "_sub"; +static mdns_tx_packet_t *s_tx_queue_head; + #ifndef ARRAY_SIZE #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) #endif @@ -1566,3 +1568,357 @@ void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, } } } + +/** + * @brief Find, remove and free answer from the scheduled packets + */ +void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service) +{ + mdns_srv_item_t s = {NULL, NULL}; + if (!service) { + service = &s; + } + mdns_tx_packet_t *q = s_tx_queue_head; + while (q) { + if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol && q->distributed) { + mdns_out_answer_t *a = q->answers; + if (a) { + if (a->type == type && a->service == service->service) { + q->answers = q->answers->next; + mdns_mem_free(a); + } else { + while (a->next) { + if (a->next->type == type && a->next->service == service->service) { + mdns_out_answer_t *b = a->next; + a->next = b->next; + mdns_mem_free(b); + break; + } + a = a->next; + } + } + } + } + q = q->next; + } +} + + +/** + * @brief schedules a packet to be sent after given milliseconds + * + * @param packet the packet + * @param ms_after number of milliseconds after which the packet should be dispatched + */ +void _mdns_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after) +{ + if (!packet) { + return; + } + packet->send_at = (xTaskGetTickCount() * portTICK_PERIOD_MS) + ms_after; + packet->next = NULL; + if (!s_tx_queue_head || s_tx_queue_head->send_at > packet->send_at) { + packet->next = s_tx_queue_head; + s_tx_queue_head = packet; + return; + } + mdns_tx_packet_t *q = s_tx_queue_head; + while (q->next && q->next->send_at <= packet->send_at) { + q = q->next; + } + packet->next = q->next; + q->next = packet; +} + +/** + * @brief free all packets scheduled for sending + */ +void _mdns_clear_tx_queue_head(void) +{ + mdns_tx_packet_t *q; + while (s_tx_queue_head) { + q = s_tx_queue_head; + s_tx_queue_head = s_tx_queue_head->next; + _mdns_free_tx_packet(q); + } +} + +/** + * @brief clear packets scheduled for sending on a specific interface + * + * @param tcpip_if the interface + * @param ip_protocol pcb type V4/V6 + */ +void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t *q, * p; + while (s_tx_queue_head && s_tx_queue_head->tcpip_if == tcpip_if && s_tx_queue_head->ip_protocol == ip_protocol) { + q = s_tx_queue_head; + s_tx_queue_head = s_tx_queue_head->next; + _mdns_free_tx_packet(q); + } + if (s_tx_queue_head) { + q = s_tx_queue_head; + while (q->next) { + if (q->next->tcpip_if == tcpip_if && q->next->ip_protocol == ip_protocol) { + p = q->next; + q->next = p->next; + _mdns_free_tx_packet(p); + } else { + q = q->next; + } + } + } +} + +/** + * @brief get the next packet scheduled for sending on a specific interface + * + * @param tcpip_if the interface + * @param ip_protocol pcb type V4/V6 + */ +mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t *q = s_tx_queue_head; + while (q) { + if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol) { + return q; + } + q = q->next; + } + return NULL; +} + +mdns_tx_packet_t *_mdns_get_next_tx_packet(void) +{ + return s_tx_queue_head; +} + + +/** + * @brief Remove and free service answer from answer list (destination) + */ +static void _mdns_dealloc_scheduled_service_answers(mdns_out_answer_t **destination, mdns_service_t *service) +{ + mdns_out_answer_t *d = *destination; + if (!d) { + return; + } + while (d && d->service == service) { + *destination = d->next; + mdns_mem_free(d); + d = *destination; + } + while (d && d->next) { + mdns_out_answer_t *a = d->next; + if (a->service == service) { + d->next = a->next; + mdns_mem_free(a); + } else { + d = d->next; + } + } +} + +/** + * @brief Find, remove and free answers and scheduled packets for service + */ +void _mdns_remove_scheduled_service_packets(mdns_service_t *service) +{ + if (!service) { + return; + } + mdns_tx_packet_t *p = NULL; + mdns_tx_packet_t *q = s_tx_queue_head; + while (q) { + bool had_answers = (q->answers != NULL); + + _mdns_dealloc_scheduled_service_answers(&(q->answers), service); + _mdns_dealloc_scheduled_service_answers(&(q->additional), service); + _mdns_dealloc_scheduled_service_answers(&(q->servers), service); + + + mdns_pcb_t *_pcb = mdns_utils_get_pcb(q->tcpip_if, q->ip_protocol); + if (mdns_is_netif_ready(q->tcpip_if, q->ip_protocol)) { + if (PCB_STATE_IS_PROBING(_pcb)) { + uint8_t i; + //check if we are probing this service + for (i = 0; i < _pcb->probe_services_len; i++) { + mdns_srv_item_t *s = _pcb->probe_services[i]; + if (s->service == service) { + break; + } + } + if (i < _pcb->probe_services_len) { + if (_pcb->probe_services_len > 1) { + uint8_t n; + for (n = (i + 1); n < _pcb->probe_services_len; n++) { + _pcb->probe_services[n - 1] = _pcb->probe_services[n]; + } + _pcb->probe_services_len--; + } else { + _pcb->probe_services_len = 0; + mdns_mem_free(_pcb->probe_services); + _pcb->probe_services = NULL; + if (!_pcb->probe_ip) { + _pcb->probe_running = false; + _pcb->state = PCB_RUNNING; + } + } + + if (q->questions) { + mdns_out_question_t *qsn = NULL; + mdns_out_question_t *qs = q->questions; + if (qs->type == MDNS_TYPE_ANY + && qs->service && strcmp(qs->service, service->service) == 0 + && qs->proto && strcmp(qs->proto, service->proto) == 0) { + q->questions = q->questions->next; + mdns_mem_free(qs); + } else while (qs->next) { + qsn = qs->next; + if (qsn->type == MDNS_TYPE_ANY + && qsn->service && strcmp(qsn->service, service->service) == 0 + && qsn->proto && strcmp(qsn->proto, service->proto) == 0) { + qs->next = qsn->next; + mdns_mem_free(qsn); + break; + } + qs = qs->next; + } + } + } + } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { + //if answers were cleared, set to running + if (had_answers && q->answers == NULL) { + _pcb->state = PCB_RUNNING; + } + } + } + + p = q; + q = q->next; + if (!p->questions && !p->answers && !p->additional && !p->servers) { + queueDetach(mdns_tx_packet_t, s_tx_queue_head, p); + _mdns_free_tx_packet(p); + } + } +} + +///** +// * @brief Send by for particular services +// */ +//static void _mdns_send_bye(mdns_srv_item_t **services, size_t len, bool include_ip) +//{ +// uint8_t i, j; +// if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { +// return; +// } +// +// for (i = 0; i < MDNS_MAX_INTERFACES; i++) { +// for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { +// mdns_pcb_t *pcb = mdns_utils_get_pcb((mdns_if_t)i, (mdns_ip_protocol_t)j); +// if (mdns_is_netif_ready(i, j) && pcb->state == PCB_RUNNING) { +// _mdns_pcb_send_bye((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); +// } +// } +// } +//} + +static void _mdns_tx_handle_packet(mdns_tx_packet_t *p) +{ + mdns_tx_packet_t *a = NULL; + mdns_out_question_t *q = NULL; + mdns_pcb_t *pcb = mdns_utils_get_pcb(p->tcpip_if, p->ip_protocol); + uint32_t send_after = 1000; + + if (pcb->state == PCB_OFF) { + _mdns_free_tx_packet(p); + return; + } + _mdns_dispatch_tx_packet(p); + + switch (pcb->state) { + case PCB_PROBE_1: + q = p->questions; + while (q) { + q->unicast = false; + q = q->next; + } + //fallthrough + case PCB_PROBE_2: + _mdns_schedule_tx_packet(p, 250); + pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); + break; + case PCB_PROBE_3: + a = _mdns_create_announce_from_probe(p); + if (!a) { + _mdns_schedule_tx_packet(p, 250); + break; + } + pcb->probe_running = false; + pcb->probe_ip = false; + pcb->probe_services_len = 0; + pcb->failed_probes = 0; + mdns_mem_free(pcb->probe_services); + pcb->probe_services = NULL; + _mdns_free_tx_packet(p); + p = a; + send_after = 250; + //fallthrough + case PCB_ANNOUNCE_1: + //fallthrough + case PCB_ANNOUNCE_2: + _mdns_schedule_tx_packet(p, send_after); + pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); + break; + case PCB_ANNOUNCE_3: + pcb->state = PCB_RUNNING; + _mdns_free_tx_packet(p); + break; + default: + _mdns_free_tx_packet(p); + break; + } +} + +void mdns_send_handle_tx_packet(mdns_tx_packet_t *packet) +{ + mdns_tx_packet_t *p = s_tx_queue_head; + // packet to be handled should be at tx head, but must be consistent with the one pushed to action queue + if (p && p == packet && p->queued) { + p->queued = false; // clearing, as the packet might be reused (pushed and transmitted again) + s_tx_queue_head = p->next; + _mdns_tx_handle_packet(p); + } else { + ESP_LOGD(TAG, "Skipping transmit of an unexpected packet!"); + } +} + +/** + * @brief Remove and free answer from answer list (destination) + */ +void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service) +{ + mdns_out_answer_t *d = *destination; + if (!d) { + return; + } + mdns_srv_item_t s = {NULL, NULL}; + if (!service) { + service = &s; + } + if (d->type == type && d->service == service->service) { + *destination = d->next; + mdns_mem_free(d); + return; + } + while (d->next) { + mdns_out_answer_t *a = d->next; + if (a->type == type && a->service == service->service) { + d->next = a->next; + mdns_mem_free(a); + return; + } + d = d->next; + } +} diff --git a/components/mdns/private_include/mdns_netif.h b/components/mdns/private_include/mdns_netif.h index d50ca8cfe5..a52407605c 100644 --- a/components/mdns/private_include/mdns_netif.h +++ b/components/mdns/private_include/mdns_netif.h @@ -13,6 +13,14 @@ extern "C" { #endif bool _mdns_if_is_dup(mdns_if_t tcpip_if); +void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +void _mdns_enable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if); +esp_err_t mdns_netif_init(void); +esp_err_t mdns_netif_deinit(void); +void unregister_predefined_handlers(void); +esp_err_t mdns_netif_free(void); +void _mdns_dup_interface(mdns_if_t tcpip_if); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 149177833a..c2bb9fb6be 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -409,7 +409,7 @@ typedef struct mdns_server_s { mdns_srv_item_t *services; QueueHandle_t action_queue; SemaphoreHandle_t action_sema; - mdns_tx_packet_t *tx_queue_head; +// mdns_tx_packet_t *tx_queue_head; mdns_search_once_t *search_once; esp_timer_handle_t timer_handle; mdns_browse_t *browse; diff --git a/components/mdns/private_include/mdns_responder.h b/components/mdns/private_include/mdns_responder.h new file mode 100644 index 0000000000..1c09a02895 --- /dev/null +++ b/components/mdns/private_include/mdns_responder.h @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "mdns_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); + +#ifdef __cplusplus +} +#endif diff --git a/components/mdns/private_include/mdns_send.h b/components/mdns/private_include/mdns_send.h index 32fe1970b8..89635341f5 100644 --- a/components/mdns/private_include/mdns_send.h +++ b/components/mdns/private_include/mdns_send.h @@ -28,6 +28,14 @@ mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *probe); void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p); void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, mdns_subtype_t *remove_subtypes); bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], size_t services_len, bool flush, bool bye); +void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +void _mdns_clear_tx_queue_head(void); +void _mdns_remove_scheduled_service_packets(mdns_service_t *service); +void mdns_send_handle_tx_packet(mdns_tx_packet_t *packet); +mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +mdns_tx_packet_t *_mdns_get_next_tx_packet(void); +void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service); +void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_utils.h b/components/mdns/private_include/mdns_utils.h index 9bf4409513..a86ce4dc93 100644 --- a/components/mdns/private_include/mdns_utils.h +++ b/components/mdns/private_include/mdns_utils.h @@ -48,6 +48,7 @@ const uint8_t *_mdns_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdn const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len); bool is_mdns_server(void); +mdns_pcb_t *mdns_utils_get_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); const char *mdns_utils_get_global_hostname(void); mdns_srv_item_t *mdns_utils_get_services(void); mdns_host_item_t *mdns_utils_get_hosts(void); @@ -263,7 +264,13 @@ static inline int append_one_txt_record_entry(uint8_t *packet, uint16_t *index, /// -mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if); -void _mdns_dup_interface(mdns_if_t tcpip_if); +//mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if); +//void _mdns_dup_interface(mdns_if_t tcpip_if); esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync); + +esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); + + +void mdns_service_lock(void); +void mdns_service_unlock(void); diff --git a/components/mdns/tests/test_afl_fuzz_host/Makefile b/components/mdns/tests/test_afl_fuzz_host/Makefile index d55193c647..cb499c1c6e 100644 --- a/components/mdns/tests/test_afl_fuzz_host/Makefile +++ b/components/mdns/tests/test_afl_fuzz_host/Makefile @@ -51,7 +51,7 @@ else endif CPP=$(CC) LD=$(CC) -OBJECTS=esp32_mock.o mdns.o test.o esp_netif_mock.o mdns_utils.o mdns_packet.o mdns_browser.o mdns_querier.o mdns_send.o +OBJECTS=esp32_mock.o mdns.o test.o esp_netif_mock.o mdns_utils.o mdns_packet.o mdns_browser.o mdns_querier.o mdns_send.o mdns_responder.o mdns_netif.o OS := $(shell uname) ifeq ($(OS),Darwin) From d50d89c8077bfbd0b4f0071efe9d2e1bd6435619 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 10 Mar 2025 16:24:45 +0100 Subject: [PATCH 05/27] feat(mdns): Querier-search stuff, Responder-pcb stuff --- components/mdns/mdns.c | 649 ++++-------------- components/mdns/mdns_browser.c | 106 ++- components/mdns/mdns_netif.c | 138 +--- components/mdns/mdns_packet.c | 145 +--- components/mdns/mdns_querier.c | 470 +++++++++++++ components/mdns/mdns_responder.c | 400 ++++++++++- components/mdns/mdns_send.c | 249 +------ components/mdns/private_include/mdns_browse.h | 4 + components/mdns/private_include/mdns_netif.h | 2 +- .../mdns/private_include/mdns_private.h | 10 +- .../mdns/private_include/mdns_querier.h | 9 + .../mdns/private_include/mdns_responder.h | 10 + components/mdns/private_include/mdns_send.h | 3 +- components/mdns/private_include/mdns_utils.h | 20 +- .../mdns/tests/test_afl_fuzz_host/Makefile | 5 + .../mdns/tests/test_afl_fuzz_host/mdns_di.h | 39 +- .../test_afl_fuzz_host/mdns_querier_di.h | 30 + .../mdns/tests/test_afl_fuzz_host/test.c | 21 +- 18 files changed, 1242 insertions(+), 1068 deletions(-) create mode 100644 components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 2ff92ee90b..e97a31d3f2 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -10,7 +10,6 @@ #include "freertos/queue.h" #include "freertos/semphr.h" #include "esp_log.h" -#include "esp_event.h" #include "esp_random.h" #include "esp_check.h" #include "mdns.h" @@ -62,11 +61,6 @@ esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions -mdns_pcb_t *mdns_utils_get_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - return &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; -} - const char *mdns_utils_get_global_hostname(void) { return _mdns_server ? _mdns_server->hostname : NULL; @@ -114,15 +108,10 @@ void mdns_utils_set_instance(const char *instance) } } -mdns_search_once_t *mdns_utils_get_search(void) -{ - return _mdns_server->search_once; -} - -mdns_browse_t *mdns_utils_get_browse(void) -{ - return _mdns_server->browse; -} +//mdns_search_once_t *mdns_utils_get_search(void) +//{ +// return _mdns_server->search_once; +//} bool is_mdns_server(void) { @@ -139,30 +128,8 @@ static inline bool _str_null_or_empty(const char *str) // return _mdns_server->tx_queue_head; //} -bool mdns_utils_is_pcb_after_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - return _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state > PCB_INIT; -} - -bool mdns_utils_is_pcb_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - return _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state == PCB_DUP; -} - -bool mdns_utils_is_probing(mdns_rx_packet_t *packet) -{ - return _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running; -} -bool mdns_utils_after_probing(mdns_rx_packet_t *packet) -{ - return _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].state > PCB_PROBE_3; -} -void mdns_utils_probe_failed(mdns_rx_packet_t *packet) -{ - _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; -} @@ -246,148 +213,6 @@ bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) - -/** - * @brief Send probe for additional services on particular PCB - */ -static void _mdns_init_pcb_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) -{ - mdns_pcb_t *pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; - size_t services_final_len = len; - - if (PCB_STATE_IS_PROBING(pcb)) { - services_final_len += pcb->probe_services_len; - } - mdns_srv_item_t **_services = NULL; - if (services_final_len) { - _services = (mdns_srv_item_t **)mdns_mem_malloc(sizeof(mdns_srv_item_t *) * services_final_len); - if (!_services) { - HOOK_MALLOC_FAILED; - return; - } - - size_t i; - for (i = 0; i < len; i++) { - _services[i] = services[i]; - } - if (pcb->probe_services) { - for (i = 0; i < pcb->probe_services_len; i++) { - _services[len + i] = pcb->probe_services[i]; - } - mdns_mem_free(pcb->probe_services); - } - } - - probe_ip = pcb->probe_ip || probe_ip; - - pcb->probe_ip = false; - pcb->probe_services = NULL; - pcb->probe_services_len = 0; - pcb->probe_running = false; - - mdns_tx_packet_t *packet = _mdns_create_probe_packet(tcpip_if, ip_protocol, _services, services_final_len, true, probe_ip); - if (!packet) { - mdns_mem_free(_services); - return; - } - - pcb->probe_ip = probe_ip; - pcb->probe_services = _services; - pcb->probe_services_len = services_final_len; - pcb->probe_running = true; - _mdns_schedule_tx_packet(packet, ((pcb->failed_probes > 5) ? 1000 : 120) + (esp_random() & 0x7F)); - pcb->state = PCB_PROBE_1; -} - -/** - * @brief Send probe for particular services on particular PCB - * - * Tests possible duplication on probing service structure and probes only for new entries. - * - If pcb probing then add only non-probing services and restarts probing - * - If pcb not probing, run probing for all specified services - */ -void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) -{ - mdns_pcb_t *pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; - - _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); - - if (_str_null_or_empty(_mdns_server->hostname)) { - pcb->state = PCB_RUNNING; - return; - } - - if (PCB_STATE_IS_PROBING(pcb)) { - // Looking for already probing services to resolve duplications - mdns_srv_item_t *new_probe_services[len]; - int new_probe_service_len = 0; - bool found; - for (size_t j = 0; j < len; ++j) { - found = false; - for (int i = 0; i < pcb->probe_services_len; ++i) { - if (pcb->probe_services[i] == services[j]) { - found = true; - break; - } - } - if (!found) { - new_probe_services[new_probe_service_len++] = services[j]; - } - } - // init probing for newly added services - _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, - new_probe_service_len ? new_probe_services : NULL, new_probe_service_len, probe_ip); - } else { - // not probing, so init for all services - _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, services, len, probe_ip); - } -} - - - -/** - * @brief Send by for particular services - */ -static void _mdns_send_bye(mdns_srv_item_t **services, size_t len, bool include_ip) -{ - uint8_t i, j; - if (_str_null_or_empty(_mdns_server->hostname)) { - return; - } - - for (i = 0; i < MDNS_MAX_INTERFACES; i++) { - for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - if (mdns_is_netif_ready(i, j) && _mdns_server->interfaces[i].pcbs[j].state == PCB_RUNNING) { - _mdns_pcb_send_bye((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); - } - } - } -} - - - - -/** - * @brief Send probe on all active PCBs - */ -void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe) -{ - uint8_t i, j; - for (i = 0; i < MDNS_MAX_INTERFACES; i++) { - for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - if (mdns_is_netif_ready(i, j)) { - mdns_pcb_t *_pcb = &_mdns_server->interfaces[i].pcbs[j]; - if (clear_old_probe) { - mdns_mem_free(_pcb->probe_services); - _pcb->probe_services = NULL; - _pcb->probe_services_len = 0; - _pcb->probe_running = false; - } - _mdns_init_pcb_probe((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, probe_ip); - } - } - } -} /** * @brief Send announcement on all active PCBs @@ -897,101 +722,7 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) } -/* - * MDNS Search - * */ - -/** - * @brief Free search structure (except the results) - */ -static void _mdns_search_free(mdns_search_once_t *search) -{ - mdns_mem_free(search->instance); - mdns_mem_free(search->service); - mdns_mem_free(search->proto); - vSemaphoreDelete(search->done_semaphore); - mdns_mem_free(search); -} - -/** - * @brief Allocate new search structure - */ -static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, - uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier) -{ - mdns_search_once_t *search = (mdns_search_once_t *)mdns_mem_malloc(sizeof(mdns_search_once_t)); - if (!search) { - HOOK_MALLOC_FAILED; - return NULL; - } - memset(search, 0, sizeof(mdns_search_once_t)); - - search->done_semaphore = xSemaphoreCreateBinary(); - if (!search->done_semaphore) { - mdns_mem_free(search); - return NULL; - } - - if (!_str_null_or_empty(name)) { - search->instance = mdns_mem_strndup(name, MDNS_NAME_BUF_LEN - 1); - if (!search->instance) { - _mdns_search_free(search); - return NULL; - } - } - - if (!_str_null_or_empty(service)) { - search->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); - if (!search->service) { - _mdns_search_free(search); - return NULL; - } - } - - if (!_str_null_or_empty(proto)) { - search->proto = mdns_mem_strndup(proto, MDNS_NAME_BUF_LEN - 1); - if (!search->proto) { - _mdns_search_free(search); - return NULL; - } - } - - search->type = type; - search->unicast = unicast; - search->timeout = timeout; - search->num_results = 0; - search->max_results = max_results; - search->result = NULL; - search->state = SEARCH_INIT; - search->sent_at = 0; - search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS; - search->notifier = notifier; - search->next = NULL; - - return search; -} - -/** - * @brief Mark search as finished and remove it from search chain - */ -void _mdns_search_finish(mdns_search_once_t *search) -{ - search->state = SEARCH_OFF; - queueDetach(mdns_search_once_t, _mdns_server->search_once, search); - if (search->notifier) { - search->notifier(search); - } - xSemaphoreGive(search->done_semaphore); -} -/** - * @brief Add new search to the search chain - */ -static void _mdns_search_add(mdns_search_once_t *search) -{ - search->next = _mdns_server->search_once; - _mdns_server->search_once = search; -} @@ -1166,7 +897,7 @@ static void _mdns_execute_action(mdns_action_t *action) /** * @brief Queue search action */ -static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search) +esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search) { mdns_action_t *action = NULL; @@ -1226,37 +957,7 @@ static void _mdns_scheduler_run(void) MDNS_SERVICE_UNLOCK(); } -/** - * @brief Called from timer task to run active searches - */ -static void _mdns_search_run(void) -{ - MDNS_SERVICE_LOCK(); - mdns_search_once_t *s = _mdns_server->search_once; - uint32_t now = xTaskGetTickCount() * portTICK_PERIOD_MS; - if (!s) { - MDNS_SERVICE_UNLOCK(); - return; - } - while (s) { - if (s->state != SEARCH_OFF) { - if (now > (s->started_at + s->timeout)) { - s->state = SEARCH_OFF; - if (_mdns_send_search_action(ACTION_SEARCH_END, s) != ESP_OK) { - s->state = SEARCH_RUNNING; - } - } else if (s->state == SEARCH_INIT || (now - s->sent_at) > 1000) { - s->state = SEARCH_RUNNING; - s->sent_at = now; - if (_mdns_send_search_action(ACTION_SEARCH_SEND, s) != ESP_OK) { - s->sent_at -= 1000; - } - } - } - s = s->next; - } - MDNS_SERVICE_UNLOCK(); -} + /** * @brief the main MDNS service task. Packets are received and parsed here @@ -1445,10 +1146,6 @@ esp_err_t mdns_init(void) return ESP_ERR_NO_MEM; } memset((uint8_t *)_mdns_server, 0, sizeof(mdns_server_t)); -// // 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; -// } _mdns_server->action_queue = xQueueCreate(MDNS_ACTION_QUEUE_LEN, sizeof(mdns_action_t *)); if (!_mdns_server->action_queue) { @@ -1478,15 +1175,7 @@ esp_err_t mdns_init(void) free_all_and_disable_pcbs: mdns_netif_deinit(); -// for (i = 0; i < MDNS_MAX_INTERFACES; i++) { -// _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V6); -// _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V4); -// s_esp_netifs[i].duplicate = MDNS_MAX_INTERFACES; -// } -//#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH free_action_sema: -// unregister_predefined_handlers(); -//#endif vSemaphoreDelete(_mdns_server->action_sema); free_queue: vQueueDelete(_mdns_server->action_queue); @@ -1510,7 +1199,7 @@ void mdns_free(void) _mdns_service_task_stop(); // at this point, the service task is deleted, so we can destroy the stack size mdns_mem_task_free(_mdns_stack_buffer); - mdns_netif_free(); + mdns_responder_deinit(); mdns_mem_free((char *)_mdns_server->hostname); mdns_mem_free((char *)_mdns_server->instance); if (_mdns_server->action_queue) { @@ -1521,24 +1210,8 @@ void mdns_free(void) vQueueDelete(_mdns_server->action_queue); } _mdns_clear_tx_queue_head(); - while (_mdns_server->search_once) { - mdns_search_once_t *h = _mdns_server->search_once; - _mdns_server->search_once = h->next; - mdns_mem_free(h->instance); - mdns_mem_free(h->service); - mdns_mem_free(h->proto); - vSemaphoreDelete(h->done_semaphore); - if (h->result) { - _mdns_query_results_free(h->result); - } - mdns_mem_free(h); - } - while (_mdns_server->browse) { - mdns_browse_t *b = _mdns_server->browse; - _mdns_server->browse = _mdns_server->browse->next; - _mdns_browse_item_free(b); - - } + mdns_search_free(); + mdns_browse_free(); vSemaphoreDelete(_mdns_server->action_sema); mdns_mem_free(_mdns_server); _mdns_server = NULL; @@ -2488,132 +2161,131 @@ esp_err_t mdns_service_remove_all(void) return ret; } -/* - * MDNS QUERY - * */ -void mdns_query_results_free(mdns_result_t *results) -{ - MDNS_SERVICE_LOCK(); - _mdns_query_results_free(results); - MDNS_SERVICE_UNLOCK(); -} - - -esp_err_t mdns_query_async_delete(mdns_search_once_t *search) -{ - if (!search) { - return ESP_ERR_INVALID_ARG; - } - if (search->state != SEARCH_OFF) { - return ESP_ERR_INVALID_STATE; - } - - MDNS_SERVICE_LOCK(); - _mdns_search_free(search); - MDNS_SERVICE_UNLOCK(); - - return ESP_OK; -} - -bool mdns_query_async_get_results(mdns_search_once_t *search, uint32_t timeout, mdns_result_t **results, uint8_t *num_results) -{ - if (xSemaphoreTake(search->done_semaphore, pdMS_TO_TICKS(timeout)) == pdTRUE) { - if (results) { - *results = search->result; - } - if (num_results) { - *num_results = search->num_results; - } - return true; - } - return false; -} - -mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, const char *proto, uint16_t type, - uint32_t timeout, size_t max_results, mdns_query_notify_t notifier) -{ - mdns_search_once_t *search = NULL; - - if (!_mdns_server || !timeout || _str_null_or_empty(service) != _str_null_or_empty(proto)) { - return NULL; - } - - search = _mdns_search_init(name, service, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, notifier); - if (!search) { - return NULL; - } - - if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { - _mdns_search_free(search); - return NULL; - } - - return search; -} - -esp_err_t mdns_query_generic(const char *name, const char *service, const char *proto, uint16_t type, mdns_query_transmission_type_t transmission_type, uint32_t timeout, size_t max_results, mdns_result_t **results) -{ - mdns_search_once_t *search = NULL; - - *results = NULL; - - if (!_mdns_server) { - return ESP_ERR_INVALID_STATE; - } - - if (!timeout || _str_null_or_empty(service) != _str_null_or_empty(proto)) { - return ESP_ERR_INVALID_ARG; - } - - search = _mdns_search_init(name, service, proto, type, transmission_type == MDNS_QUERY_UNICAST, timeout, max_results, NULL); - if (!search) { - return ESP_ERR_NO_MEM; - } - - if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { - _mdns_search_free(search); - return ESP_ERR_NO_MEM; - } - xSemaphoreTake(search->done_semaphore, portMAX_DELAY); - - *results = search->result; - _mdns_search_free(search); - - return ESP_OK; -} - -esp_err_t mdns_query(const char *name, const char *service_type, const char *proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t **results) -{ - return mdns_query_generic(name, service_type, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, results); -} - -esp_err_t mdns_query_ptr(const char *service, const char *proto, uint32_t timeout, size_t max_results, mdns_result_t **results) -{ - if (_str_null_or_empty(service) || _str_null_or_empty(proto)) { - return ESP_ERR_INVALID_ARG; - } - - return mdns_query(NULL, service, proto, MDNS_TYPE_PTR, timeout, max_results, results); -} - -esp_err_t mdns_query_srv(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) -{ - if (_str_null_or_empty(instance) || _str_null_or_empty(service) || _str_null_or_empty(proto)) { - return ESP_ERR_INVALID_ARG; - } - - return mdns_query(instance, service, proto, MDNS_TYPE_SRV, timeout, 1, result); -} - -esp_err_t mdns_query_txt(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) -{ - if (_str_null_or_empty(instance) || _str_null_or_empty(service) || _str_null_or_empty(proto)) { - return ESP_ERR_INVALID_ARG; - } - - return mdns_query(instance, service, proto, MDNS_TYPE_TXT, timeout, 1, result); -} - +///* +// * MDNS QUERY +// * */ +//void mdns_query_results_free(mdns_result_t *results) +//{ +// MDNS_SERVICE_LOCK(); +// _mdns_query_results_free(results); +// MDNS_SERVICE_UNLOCK(); +//} +// +//esp_err_t mdns_query_async_delete(mdns_search_once_t *search) +//{ +// if (!search) { +// return ESP_ERR_INVALID_ARG; +// } +// if (search->state != SEARCH_OFF) { +// return ESP_ERR_INVALID_STATE; +// } +// +// MDNS_SERVICE_LOCK(); +// _mdns_search_free(search); +// MDNS_SERVICE_UNLOCK(); +// +// return ESP_OK; +//} +// +//bool mdns_query_async_get_results(mdns_search_once_t *search, uint32_t timeout, mdns_result_t **results, uint8_t *num_results) +//{ +// if (xSemaphoreTake(search->done_semaphore, pdMS_TO_TICKS(timeout)) == pdTRUE) { +// if (results) { +// *results = search->result; +// } +// if (num_results) { +// *num_results = search->num_results; +// } +// return true; +// } +// return false; +//} +// +//mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, const char *proto, uint16_t type, +// uint32_t timeout, size_t max_results, mdns_query_notify_t notifier) +//{ +// mdns_search_once_t *search = NULL; +// +// if (!_mdns_server || !timeout || _str_null_or_empty(service) != _str_null_or_empty(proto)) { +// return NULL; +// } +// +// search = _mdns_search_init(name, service, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, notifier); +// if (!search) { +// return NULL; +// } +// +// if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { +// _mdns_search_free(search); +// return NULL; +// } +// +// return search; +//} +// +//esp_err_t mdns_query_generic(const char *name, const char *service, const char *proto, uint16_t type, mdns_query_transmission_type_t transmission_type, uint32_t timeout, size_t max_results, mdns_result_t **results) +//{ +// mdns_search_once_t *search = NULL; +// +// *results = NULL; +// +// if (!_mdns_server) { +// return ESP_ERR_INVALID_STATE; +// } +// +// if (!timeout || _str_null_or_empty(service) != _str_null_or_empty(proto)) { +// return ESP_ERR_INVALID_ARG; +// } +// +// search = _mdns_search_init(name, service, proto, type, transmission_type == MDNS_QUERY_UNICAST, timeout, max_results, NULL); +// if (!search) { +// return ESP_ERR_NO_MEM; +// } +// +// if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { +// _mdns_search_free(search); +// return ESP_ERR_NO_MEM; +// } +// xSemaphoreTake(search->done_semaphore, portMAX_DELAY); +// +// *results = search->result; +// _mdns_search_free(search); +// +// return ESP_OK; +//} +// +//esp_err_t mdns_query(const char *name, const char *service_type, const char *proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t **results) +//{ +// return mdns_query_generic(name, service_type, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, results); +//} +// +//esp_err_t mdns_query_ptr(const char *service, const char *proto, uint32_t timeout, size_t max_results, mdns_result_t **results) +//{ +// if (_str_null_or_empty(service) || _str_null_or_empty(proto)) { +// return ESP_ERR_INVALID_ARG; +// } +// +// return mdns_query(NULL, service, proto, MDNS_TYPE_PTR, timeout, max_results, results); +//} +// +//esp_err_t mdns_query_srv(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) +//{ +// if (_str_null_or_empty(instance) || _str_null_or_empty(service) || _str_null_or_empty(proto)) { +// return ESP_ERR_INVALID_ARG; +// } +// +// return mdns_query(instance, service, proto, MDNS_TYPE_SRV, timeout, 1, result); +//} +// +//esp_err_t mdns_query_txt(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) +//{ +// if (_str_null_or_empty(instance) || _str_null_or_empty(service) || _str_null_or_empty(proto)) { +// return ESP_ERR_INVALID_ARG; +// } +// +// return mdns_query(instance, service, proto, MDNS_TYPE_TXT, timeout, 1, result); +//} +// esp_err_t mdns_lookup_delegated_service(const char *instance, const char *service, const char *proto, size_t max_results, mdns_result_t **result) { @@ -2768,59 +2440,6 @@ esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *brows return ESP_OK; } - - -/** - * @brief Mark browse as finished, remove and free it from browse chain - */ -void _mdns_browse_finish(mdns_browse_t *browse) -{ - browse->state = BROWSE_OFF; - mdns_browse_t *b = _mdns_server->browse; - mdns_browse_t *target_free = NULL; - while (b) { - if (strlen(b->service) == strlen(browse->service) && memcmp(b->service, browse->service, strlen(b->service)) == 0 && - strlen(b->proto) == strlen(browse->proto) && memcmp(b->proto, browse->proto, strlen(b->proto)) == 0) { - target_free = b; - b = b->next; - queueDetach(mdns_browse_t, _mdns_server->browse, target_free); - _mdns_browse_item_free(target_free); - } else { - b = b->next; - } - } - _mdns_browse_item_free(browse); -} - -/** - * @brief Add new browse to the browse chain - */ -void _mdns_browse_add(mdns_browse_t *browse) -{ - browse->state = BROWSE_RUNNING; - mdns_browse_t *queue = _mdns_server->browse; - bool found = false; - // looking for this browse in active browses - while (queue) { - if (strlen(queue->service) == strlen(browse->service) && memcmp(queue->service, browse->service, strlen(queue->service)) == 0 && - strlen(queue->proto) == strlen(browse->proto) && memcmp(queue->proto, browse->proto, strlen(queue->proto)) == 0) { - found = true; - break; - } - queue = queue->next; - } - if (!found) { - browse->next = _mdns_server->browse; - _mdns_server->browse = browse; - } - for (uint8_t interface_idx = 0; interface_idx < MDNS_MAX_INTERFACES; interface_idx++) { - _mdns_browse_send(browse, (mdns_if_t)interface_idx); - } - if (found) { - _mdns_browse_item_free(browse); - } -} - void _mdns_browse_sync(mdns_browse_sync_t *browse_sync) { mdns_browse_t *browse = browse_sync->browse; diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index 6d1c3fd29f..821c90f99d 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -13,8 +13,49 @@ #include "mdns_querier.h" #include "esp_log.h" -static const char *TAG = "mdns_send"; +static const char *TAG = "mdns_browser"; +static mdns_browse_t *s_browse; + +void mdns_browse_send_all(mdns_if_t mdns_if) +{ + mdns_browse_t *browse = s_browse; + while (browse) { + _mdns_browse_send(browse, mdns_if); + browse = browse->next; + } +} + +void mdns_browse_free(void) +{ + while (s_browse) { + mdns_browse_t *b = s_browse; + s_browse = s_browse->next; + _mdns_browse_item_free(b); + } +} + +/** + * @brief Mark browse as finished, remove and free it from browse chain + */ +void _mdns_browse_finish(mdns_browse_t *browse) +{ + browse->state = BROWSE_OFF; + mdns_browse_t *b = s_browse; + mdns_browse_t *target_free = NULL; + while (b) { + if (strlen(b->service) == strlen(browse->service) && memcmp(b->service, browse->service, strlen(b->service)) == 0 && + strlen(b->proto) == strlen(browse->proto) && memcmp(b->proto, browse->proto, strlen(b->proto)) == 0) { + target_free = b; + b = b->next; + queueDetach(mdns_browse_t, s_browse, target_free); + _mdns_browse_item_free(target_free); + } else { + b = b->next; + } + } + _mdns_browse_item_free(browse); +} /** * @brief Send PTR query packet to all available interfaces for browsing. @@ -125,3 +166,66 @@ esp_err_t mdns_browse_delete(const char *service, const char *proto) } return ESP_OK; } + +/** + * @brief Add new browse to the browse chain + */ +void _mdns_browse_add(mdns_browse_t *browse) +{ + browse->state = BROWSE_RUNNING; + mdns_browse_t *queue = s_browse; + bool found = false; + // looking for this browse in active browses + while (queue) { + if (strlen(queue->service) == strlen(browse->service) && memcmp(queue->service, browse->service, strlen(queue->service)) == 0 && + strlen(queue->proto) == strlen(browse->proto) && memcmp(queue->proto, browse->proto, strlen(queue->proto)) == 0) { + found = true; + break; + } + queue = queue->next; + } + if (!found) { + browse->next = s_browse; + s_browse = browse; + } + for (uint8_t interface_idx = 0; interface_idx < MDNS_MAX_INTERFACES; interface_idx++) { + _mdns_browse_send(browse, (mdns_if_t)interface_idx); + } + if (found) { + _mdns_browse_item_free(browse); + } +} + +/** + * @brief Called from packet parser to find matching running search + */ +mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_browse_t *b = s_browse; + // For browse, we only care about the SRV, TXT, A and AAAA + if (type != MDNS_TYPE_SRV && type != MDNS_TYPE_A && type != MDNS_TYPE_AAAA && type != MDNS_TYPE_TXT) { + return NULL; + } + mdns_result_t *r = NULL; + while (b) { + if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { + if (strcasecmp(name->service, b->service) + || strcasecmp(name->proto, b->proto)) { + b = b->next; + continue; + } + return b; + } else if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { + r = b->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { + return b; + } + r = r->next; + } + b = b->next; + continue; + } + } + return b; +} diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c index 859f5c518b..0d90a0a8bd 100644 --- a/components/mdns/mdns_netif.c +++ b/components/mdns/mdns_netif.c @@ -143,7 +143,7 @@ esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) /* * @brief Clean internal mdns interface's pointer */ -static inline void _mdns_clean_netif_ptr(mdns_if_t tcpip_if) +void _mdns_clean_netif_ptr(mdns_if_t tcpip_if) { if (tcpip_if < MDNS_MAX_INTERFACES) { s_esp_netifs[tcpip_if].netif = NULL; @@ -168,125 +168,7 @@ static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *esp_netif) } return MDNS_MAX_INTERFACES; } -/** - * @brief Check if interface is duplicate (two interfaces on the same subnet) - */ -bool _mdns_if_is_dup(mdns_if_t tcpip_if) -{ - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); - if (other_if == MDNS_MAX_INTERFACES) { - return false; - } - mdns_pcb_state_t state_v4 = mdns_utils_get_pcb(tcpip_if, MDNS_IP_PROTOCOL_V4)->state; - mdns_pcb_state_t state_v6 = mdns_utils_get_pcb(tcpip_if, MDNS_IP_PROTOCOL_V6)->state; - mdns_pcb_state_t other_state_v4 = mdns_utils_get_pcb(other_if, MDNS_IP_PROTOCOL_V4)->state; - mdns_pcb_state_t other_state_v6 = mdns_utils_get_pcb(other_if, MDNS_IP_PROTOCOL_V6)->state; - - if (state_v4 == PCB_DUP || state_v6 == PCB_DUP || other_state_v4 == PCB_DUP || other_state_v6 == PCB_DUP) { - return true; - } - return false; -} - -static esp_err_t mdns_pcb_deinit_local(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_proto) -{ - esp_err_t err = _mdns_pcb_deinit(tcpip_if, ip_proto); - mdns_pcb_t *_pcb = mdns_utils_get_pcb(tcpip_if, ip_proto); - if (_pcb == NULL || err != ESP_OK) { - return err; - } - mdns_mem_free(_pcb->probe_services); - _pcb->state = PCB_OFF; - _pcb->probe_ip = false; - _pcb->probe_services = NULL; - _pcb->probe_services_len = 0; - _pcb->probe_running = false; - _pcb->failed_probes = 0; - return ESP_OK; -} - -/** - * @brief Restart the responder on particular PCB - */ -static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - size_t srv_count = 0; - mdns_srv_item_t *a = mdns_utils_get_services(); - while (a) { - srv_count++; - a = a->next; - } - if (srv_count == 0) { - // proble only IP - _mdns_init_pcb_probe(tcpip_if, ip_protocol, NULL, 0, true); - return; - } - mdns_srv_item_t *services[srv_count]; - size_t i = 0; - a = mdns_utils_get_services(); - while (a) { - services[i++] = a; - a = a->next; - } - _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, srv_count, true); -} - -/** - * @brief Disable mDNS interface - */ -void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - _mdns_clean_netif_ptr(tcpip_if); - - if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { - _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); - mdns_pcb_deinit_local(tcpip_if, ip_protocol); - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); - if (other_if != MDNS_MAX_INTERFACES && mdns_utils_get_pcb(other_if, ip_protocol)->state == PCB_DUP) { - mdns_utils_get_pcb(other_if, ip_protocol)->state = PCB_OFF; - _mdns_enable_pcb(other_if, ip_protocol); - } - } - mdns_utils_get_pcb(tcpip_if, ip_protocol)->state = PCB_OFF; -} -/** - * @brief Enable mDNS interface - */ -void _mdns_enable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - if (!mdns_is_netif_ready(tcpip_if, ip_protocol)) { - if (_mdns_pcb_init(tcpip_if, ip_protocol)) { - mdns_utils_get_pcb(tcpip_if, ip_protocol)->failed_probes = 0; - return; - } - } - _mdns_restart_pcb(tcpip_if, ip_protocol); -} - -/** - * @brief Set interface as duplicate if another is found on the same subnet - */ -void _mdns_dup_interface(mdns_if_t tcpip_if) -{ - uint8_t i; - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); - if (other_if == MDNS_MAX_INTERFACES) { - return; // no other interface found - } - for (i = 0; i < MDNS_IP_PROTOCOL_MAX; i++) { - if (mdns_is_netif_ready(other_if, i)) { - //stop this interface and mark as dup - if (mdns_is_netif_ready(tcpip_if, i)) { - _mdns_clear_pcb_tx_queue_head(tcpip_if, i); - mdns_pcb_deinit_local(tcpip_if, i); - } - mdns_utils_get_pcb(tcpip_if, i)->state = PCB_DUP; -// _mdns_server->interfaces[tcpip_if].pcbs[i].state = PCB_DUP; - _mdns_announce_pcb(other_if, i, NULL, 0, true); - } - } -} /** * @brief Dispatch interface changes based on system events @@ -379,11 +261,8 @@ void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, } post_mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); post_mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); - mdns_browse_t *browse = mdns_utils_get_browse(); - while (browse) { - _mdns_browse_send(browse, mdns_if); - browse = browse->next; - } + mdns_browse_send_all(mdns_if); + } break; default: @@ -543,14 +422,3 @@ esp_err_t mdns_netif_deinit(void) } return ESP_OK; } - -esp_err_t mdns_netif_free(void) -{ - for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { - for (int j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - mdns_pcb_deinit_local(i, j); - } - } - return ESP_OK; - -} diff --git a/components/mdns/mdns_packet.c b/components/mdns/mdns_packet.c index f5d3f69312..79a48c81fd 100644 --- a/components/mdns/mdns_packet.c +++ b/components/mdns/mdns_packet.c @@ -14,6 +14,9 @@ #include "mdns_debug.h" #include "mdns_netif.h" #include "mdns_send.h" +#include "mdns_browse.h" +#include "mdns_querier.h" +#include "mdns_responder.h" static const char *TAG = "mdns_packet"; @@ -213,21 +216,7 @@ static int _mdns_txt_item_name_get_len(const uint8_t *data, size_t len) return len; } -/** - * @brief Called from parser to finish any searches that have reached maximum results - */ -static void _mdns_search_finish_done(void) -{ - mdns_search_once_t *search = mdns_utils_get_search(); - mdns_search_once_t *s = NULL; - while (search) { - s = search; - search = search->next; - if (s->max_results && s->num_results >= s->max_results) { - _mdns_search_finish(s); - } - } -} + /** * @brief Called from parser to add TXT data to search result @@ -1122,106 +1111,6 @@ static mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, co } -/** - * @brief Called from packet parser to find matching running search - */ -static mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_result_t *r = NULL; - while (s) { - if (s->state == SEARCH_OFF) { - s = s->next; - continue; - } - - if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { - if ((s->type == MDNS_TYPE_ANY && s->service != NULL) - || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV)) { - s = s->next; - continue; - } - if (s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV) { - if (!strcasecmp(name->host, s->instance)) { - return s; - } - s = s->next; - continue; - } - r = s->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { - return s; - } - r = r->next; - } - s = s->next; - continue; - } - - if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { - if ((s->type == MDNS_TYPE_ANY && s->service == NULL) - || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR)) { - s = s->next; - continue; - } - if (strcasecmp(name->service, s->service) - || strcasecmp(name->proto, s->proto)) { - s = s->next; - continue; - } - if (s->type != MDNS_TYPE_PTR) { - if (s->instance && strcasecmp(name->host, s->instance) == 0) { - return s; - } - s = s->next; - continue; - } - return s; - } - - if (type == MDNS_TYPE_PTR && type == s->type && !strcasecmp(name->service, s->service) && !strcasecmp(name->proto, s->proto)) { - return s; - } - - s = s->next; - } - - return NULL; -} - - -/** - * @brief Called from packet parser to find matching running search - */ -static mdns_browse_t *_mdns_browse_find_from(mdns_browse_t *b, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - // For browse, we only care about the SRV, TXT, A and AAAA - if (type != MDNS_TYPE_SRV && type != MDNS_TYPE_A && type != MDNS_TYPE_AAAA && type != MDNS_TYPE_TXT) { - return NULL; - } - mdns_result_t *r = NULL; - while (b) { - if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { - if (strcasecmp(name->service, b->service) - || strcasecmp(name->proto, b->proto)) { - b = b->next; - continue; - } - return b; - } else if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { - r = b->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { - return b; - } - r = r->next; - } - b = b->next; - continue; - } - } - return b; -} /** @@ -1446,8 +1335,8 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) //skip this record continue; } - search_result = _mdns_search_find_from(mdns_utils_get_search(), name, type, packet->tcpip_if, packet->ip_protocol); - browse_result = _mdns_browse_find_from(mdns_utils_get_browse(), name, type, packet->tcpip_if, packet->ip_protocol); + search_result = _mdns_search_find(name, type, packet->tcpip_if, packet->ip_protocol); + browse_result = _mdns_browse_find(name, type, packet->tcpip_if, packet->ip_protocol); if (browse_result) { if (!out_sync_browse) { // will be freed in function `_mdns_browse_sync` @@ -1618,8 +1507,8 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (service && col && (parsed_packet->probe || parsed_packet->authoritative)) { if (col > 0 || !port) { do_not_reply = true; - if (mdns_utils_is_probing(packet)) { - mdns_utils_probe_failed(packet); + if (mdns_responder_is_probing(packet)) { + mdns_responder_probe_failed(packet); if (!mdns_utils_str_null_or_empty(service->service->instance)) { char *new_instance = _mdns_mangle_name((char *)service->service->instance); if (new_instance) { @@ -1710,10 +1599,10 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else if (service) { // only detect txt collision if service existed col = _mdns_check_txt_collision(service->service, data_ptr, data_len); } - if (col && !mdns_utils_is_probing(packet) && service) { + if (col && !mdns_responder_is_probing(packet) && service) { do_not_reply = true; _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); - } else if (ttl > (MDNS_ANSWER_TXT_TTL / 2) && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_utils_is_probing(packet)) { + } else if (ttl > (MDNS_ANSWER_TXT_TTL / 2) && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_responder_is_probing(packet)) { _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); } } @@ -1754,9 +1643,9 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) goto clear_rx_packet; } else if (col == 1) { do_not_reply = true; - if (mdns_utils_is_probing(packet)) { + if (mdns_responder_is_probing(packet)) { if (col && (parsed_packet->probe || parsed_packet->authoritative)) { - mdns_utils_probe_failed(packet); + mdns_responder_probe_failed(packet); char *new_host = _mdns_mangle_name((char *)mdns_utils_get_global_hostname()); if (new_host) { _mdns_remap_self_service_hostname(mdns_utils_get_global_hostname(), new_host); @@ -1767,7 +1656,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else { _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); } - } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_utils_is_probing(packet)) { + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_responder_is_probing(packet)) { _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); } } @@ -1809,9 +1698,9 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) goto clear_rx_packet; } else if (col == 1) { do_not_reply = true; - if (mdns_utils_is_probing(packet)) { + if (mdns_responder_is_probing(packet)) { if (col && (parsed_packet->probe || parsed_packet->authoritative)) { - mdns_utils_probe_failed(packet); + mdns_responder_probe_failed(packet); char *new_host = _mdns_mangle_name((char *)mdns_utils_get_global_hostname()); if (new_host) { _mdns_remap_self_service_hostname(mdns_utils_get_global_hostname(), new_host); @@ -1822,7 +1711,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else { _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); } - } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_utils_is_probing(packet)) { + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_responder_is_probing(packet)) { _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); } } @@ -1836,7 +1725,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } - if (!do_not_reply && mdns_utils_after_probing(packet) && (parsed_packet->questions || parsed_packet->discovery)) { + if (!do_not_reply && mdns_responder_after_probing(packet) && (parsed_packet->questions || parsed_packet->discovery)) { _mdns_create_answer_from_parsed_packet(parsed_packet); } if (out_sync_browse) { diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index 1338d9b230..5e2273d803 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -3,9 +3,18 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include #include "mdns_private.h" #include "mdns_querier.h" #include "mdns_mem_caps.h" +#include "mdns_utils.h" +#include "mdns_send.h" +#include "esp_log.h" +#include "mdns_responder.h" + +static const char *TAG = "mdns_querier"; + +static mdns_search_once_t *s_search_once; void _mdns_query_results_free(mdns_result_t *results) { @@ -37,3 +46,464 @@ void _mdns_query_results_free(mdns_result_t *results) mdns_mem_free(r); } } + +/** + * @brief Mark search as finished and remove it from search chain + */ +void _mdns_search_finish(mdns_search_once_t *search) +{ + search->state = SEARCH_OFF; + queueDetach(mdns_search_once_t, s_search_once, search); + if (search->notifier) { + search->notifier(search); + } + xSemaphoreGive(search->done_semaphore); +} + +/** + * @brief Add new search to the search chain + */ +void _mdns_search_add(mdns_search_once_t *search) +{ + search->next = s_search_once; + s_search_once = search; +} + +/** + * @brief Called from timer task to run active searches + */ +void _mdns_search_run(void) +{ + mdns_service_lock(); + mdns_search_once_t *s = s_search_once; + uint32_t now = xTaskGetTickCount() * portTICK_PERIOD_MS; + if (!s) { + mdns_service_unlock(); + return; + } + while (s) { + if (s->state != SEARCH_OFF) { + if (now > (s->started_at + s->timeout)) { + s->state = SEARCH_OFF; + if (_mdns_send_search_action(ACTION_SEARCH_END, s) != ESP_OK) { + s->state = SEARCH_RUNNING; + } + } else if (s->state == SEARCH_INIT || (now - s->sent_at) > 1000) { + s->state = SEARCH_RUNNING; + s->sent_at = now; + if (_mdns_send_search_action(ACTION_SEARCH_SEND, s) != ESP_OK) { + s->sent_at -= 1000; + } + } + } + s = s->next; + } + mdns_service_unlock(); +} + +void mdns_search_free(void) +{ + while (s_search_once) { + mdns_search_once_t *h = s_search_once; + s_search_once = h->next; + mdns_mem_free(h->instance); + mdns_mem_free(h->service); + mdns_mem_free(h->proto); + vSemaphoreDelete(h->done_semaphore); + if (h->result) { + _mdns_query_results_free(h->result); + } + mdns_mem_free(h); + } +} + +/** + * @brief Send search packet to all available interfaces + */ +void _mdns_search_send(mdns_search_once_t *search) +{ + mdns_search_once_t *queue = s_search_once; + bool found = false; + // looking for this search in active searches + while (queue) { + if (queue == search) { + found = true; + break; + } + queue = queue->next; + } + + if (!found) { + // no longer active -> skip sending this search + return; + } + + uint8_t i, j; + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + _mdns_search_send_pcb(search, (mdns_if_t)i, (mdns_ip_protocol_t)j); + } + } +} + +/** + * @brief Called from parser to finish any searches that have reached maximum results + */ +void _mdns_search_finish_done(void) +{ + mdns_search_once_t *search = s_search_once; + mdns_search_once_t *s = NULL; + while (search) { + s = search; + search = search->next; + if (s->max_results && s->num_results >= s->max_results) { + _mdns_search_finish(s); + } + } +} + +/** + * @brief Called from packet parser to find matching running search + */ +mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_result_t *r = NULL; + while (s) { + if (s->state == SEARCH_OFF) { + s = s->next; + continue; + } + + if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { + if ((s->type == MDNS_TYPE_ANY && s->service != NULL) + || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV)) { + s = s->next; + continue; + } + if (s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV) { + if (!strcasecmp(name->host, s->instance)) { + return s; + } + s = s->next; + continue; + } + r = s->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { + return s; + } + r = r->next; + } + s = s->next; + continue; + } + + if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { + if ((s->type == MDNS_TYPE_ANY && s->service == NULL) + || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR)) { + s = s->next; + continue; + } + if (strcasecmp(name->service, s->service) + || strcasecmp(name->proto, s->proto)) { + s = s->next; + continue; + } + if (s->type != MDNS_TYPE_PTR) { + if (s->instance && strcasecmp(name->host, s->instance) == 0) { + return s; + } + s = s->next; + continue; + } + return s; + } + + if (type == MDNS_TYPE_PTR && type == s->type && !strcasecmp(name->service, s->service) && !strcasecmp(name->proto, s->proto)) { + return s; + } + + s = s->next; + } + + return NULL; +} + +mdns_search_once_t *_mdns_search_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + return _mdns_search_find_from(s_search_once, name, type, tcpip_if, ip_protocol); +} + +/** + * @brief Create search packet for particular interface + */ +static mdns_tx_packet_t *_mdns_create_search_packet(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_result_t *r = NULL; + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return NULL; + } + + mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); + if (!q) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return NULL; + } + q->next = NULL; + q->unicast = search->unicast; + q->type = search->type; + q->host = search->instance; + q->service = search->service; + q->proto = search->proto; + q->domain = MDNS_UTILS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; + queueToEnd(mdns_out_question_t, packet->questions, q); + + if (search->type == MDNS_TYPE_PTR) { + r = search->result; + while (r) { + //full record on the same interface is available + if (r->esp_netif != _mdns_get_esp_netif(tcpip_if) || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { + r = r->next; + continue; + } + mdns_out_answer_t *a = (mdns_out_answer_t *)mdns_mem_malloc(sizeof(mdns_out_answer_t)); + if (!a) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return NULL; + } + a->type = MDNS_TYPE_PTR; + a->service = NULL; + a->custom_instance = r->instance_name; + a->custom_service = search->service; + a->custom_proto = search->proto; + a->bye = false; + a->flush = false; + a->next = NULL; + queueToEnd(mdns_out_answer_t, packet->answers, a); + r = r->next; + } + } + + return packet; +} + + +/** + * @brief Send search packet to particular interface + */ +void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t *packet = NULL; + if (mdsn_responder_iface_init(tcpip_if, ip_protocol)) { + packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol); + if (!packet) { + return; + } + _mdns_dispatch_tx_packet(packet); + _mdns_free_tx_packet(packet); + } +} + +/* + * MDNS Search + * */ + +/** + * @brief Free search structure (except the results) + */ +void _mdns_search_free(mdns_search_once_t *search) +{ + mdns_mem_free(search->instance); + mdns_mem_free(search->service); + mdns_mem_free(search->proto); + vSemaphoreDelete(search->done_semaphore); + mdns_mem_free(search); +} + +/** + * @brief Allocate new search structure + */ +static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, + uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier) +{ + mdns_search_once_t *search = (mdns_search_once_t *)mdns_mem_malloc(sizeof(mdns_search_once_t)); + if (!search) { + HOOK_MALLOC_FAILED; + return NULL; + } + memset(search, 0, sizeof(mdns_search_once_t)); + + search->done_semaphore = xSemaphoreCreateBinary(); + if (!search->done_semaphore) { + mdns_mem_free(search); + return NULL; + } + + if (!mdns_utils_str_null_or_empty(name)) { + search->instance = mdns_mem_strndup(name, MDNS_NAME_BUF_LEN - 1); + if (!search->instance) { + _mdns_search_free(search); + return NULL; + } + } + + if (!mdns_utils_str_null_or_empty(service)) { + search->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); + if (!search->service) { + _mdns_search_free(search); + return NULL; + } + } + + if (!mdns_utils_str_null_or_empty(proto)) { + search->proto = mdns_mem_strndup(proto, MDNS_NAME_BUF_LEN - 1); + if (!search->proto) { + _mdns_search_free(search); + return NULL; + } + } + + search->type = type; + search->unicast = unicast; + search->timeout = timeout; + search->num_results = 0; + search->max_results = max_results; + search->result = NULL; + search->state = SEARCH_INIT; + search->sent_at = 0; + search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS; + search->notifier = notifier; + search->next = NULL; + + return search; +} + + +/* + * MDNS QUERY + * */ +void mdns_query_results_free(mdns_result_t *results) +{ + mdns_service_lock(); + _mdns_query_results_free(results); + mdns_service_unlock(); +} + +esp_err_t mdns_query_async_delete(mdns_search_once_t *search) +{ + if (!search) { + return ESP_ERR_INVALID_ARG; + } + if (search->state != SEARCH_OFF) { + return ESP_ERR_INVALID_STATE; + } + + mdns_service_lock(); + _mdns_search_free(search); + mdns_service_unlock(); + + return ESP_OK; +} + +bool mdns_query_async_get_results(mdns_search_once_t *search, uint32_t timeout, mdns_result_t **results, uint8_t *num_results) +{ + if (xSemaphoreTake(search->done_semaphore, pdMS_TO_TICKS(timeout)) == pdTRUE) { + if (results) { + *results = search->result; + } + if (num_results) { + *num_results = search->num_results; + } + return true; + } + return false; +} + +mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, size_t max_results, mdns_query_notify_t notifier) +{ + mdns_search_once_t *search = NULL; + + if (!is_mdns_server() || !timeout || mdns_utils_str_null_or_empty(service) != mdns_utils_str_null_or_empty(proto)) { + return NULL; + } + + search = _mdns_search_init(name, service, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, notifier); + if (!search) { + return NULL; + } + + if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { + _mdns_search_free(search); + return NULL; + } + + return search; +} + +esp_err_t mdns_query_generic(const char *name, const char *service, const char *proto, uint16_t type, mdns_query_transmission_type_t transmission_type, uint32_t timeout, size_t max_results, mdns_result_t **results) +{ + mdns_search_once_t *search = NULL; + + *results = NULL; + + if (!is_mdns_server()) { + return ESP_ERR_INVALID_STATE; + } + + if (!timeout || mdns_utils_str_null_or_empty(service) != mdns_utils_str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + search = _mdns_search_init(name, service, proto, type, transmission_type == MDNS_QUERY_UNICAST, timeout, max_results, NULL); + if (!search) { + return ESP_ERR_NO_MEM; + } + + if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { + _mdns_search_free(search); + return ESP_ERR_NO_MEM; + } + xSemaphoreTake(search->done_semaphore, portMAX_DELAY); + + *results = search->result; + _mdns_search_free(search); + + return ESP_OK; +} + +esp_err_t mdns_query(const char *name, const char *service_type, const char *proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t **results) +{ + return mdns_query_generic(name, service_type, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, results); +} + +esp_err_t mdns_query_ptr(const char *service, const char *proto, uint32_t timeout, size_t max_results, mdns_result_t **results) +{ + if (mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + return mdns_query(NULL, service, proto, MDNS_TYPE_PTR, timeout, max_results, results); +} + +esp_err_t mdns_query_srv(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) +{ + if (mdns_utils_str_null_or_empty(instance) || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + return mdns_query(instance, service, proto, MDNS_TYPE_SRV, timeout, 1, result); +} + +esp_err_t mdns_query_txt(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) +{ + if (mdns_utils_str_null_or_empty(instance) || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + return mdns_query(instance, service, proto, MDNS_TYPE_TXT, timeout, 1, result); +} diff --git a/components/mdns/mdns_responder.c b/components/mdns/mdns_responder.c index e3b2f7af91..7690cdc6f0 100644 --- a/components/mdns/mdns_responder.c +++ b/components/mdns/mdns_responder.c @@ -10,13 +10,20 @@ #include "mdns_netif.h" #include "mdns_utils.h" #include "mdns_send.h" +#include "mdns_mem_caps.h" +#include "esp_log.h" +#include "esp_random.h" + +static const char *TAG = "mdns_responder"; + +static mdns_pcb_t s_pcbs[MDNS_MAX_INTERFACES][MDNS_IP_PROTOCOL_MAX]; /** * @brief Send announcement on particular PCB */ void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) { - mdns_pcb_t *_pcb = mdns_utils_get_pcb(tcpip_if, ip_protocol); + mdns_pcb_t *_pcb = &s_pcbs[tcpip_if][ip_protocol]; size_t i; if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { if (PCB_STATE_IS_PROBING(_pcb)) { @@ -53,3 +60,394 @@ void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns } } } + +/** + * @brief Check if interface is duplicate (two interfaces on the same subnet) + */ +bool _mdns_if_is_dup(mdns_if_t tcpip_if) +{ + mdns_if_t ifaces[MDNS_MAX_INTERFACES] = {tcpip_if, _mdns_get_other_if(tcpip_if) }; + if (ifaces[1] == MDNS_MAX_INTERFACES) { + return false; + } + // check both this netif and the potential duplicate on all protocols + // if any of them is in duplicate state, return true + for (int i = 0; i < 2; i++) { + for (int proto = 0; proto < MDNS_IP_PROTOCOL_MAX; proto++) { + if (s_pcbs[ifaces[i]][(mdns_ip_protocol_t) proto].state == PCB_DUP) { + return true; + } + } + } + return false; +} + +static esp_err_t mdns_pcb_deinit_local(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_proto) +{ + esp_err_t err = _mdns_pcb_deinit(tcpip_if, ip_proto); + mdns_pcb_t *_pcb = &s_pcbs[tcpip_if][ip_proto]; + if (_pcb == NULL || err != ESP_OK) { + return err; + } + mdns_mem_free(_pcb->probe_services); + _pcb->state = PCB_OFF; + _pcb->probe_ip = false; + _pcb->probe_services = NULL; + _pcb->probe_services_len = 0; + _pcb->probe_running = false; + _pcb->failed_probes = 0; + return ESP_OK; +} + +/** + * @brief Restart the responder on particular PCB + */ +static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + size_t srv_count = 0; + mdns_srv_item_t *a = mdns_utils_get_services(); + while (a) { + srv_count++; + a = a->next; + } + if (srv_count == 0) { + // proble only IP + _mdns_init_pcb_probe(tcpip_if, ip_protocol, NULL, 0, true); + return; + } + mdns_srv_item_t *services[srv_count]; + size_t i = 0; + a = mdns_utils_get_services(); + while (a) { + services[i++] = a; + a = a->next; + } + _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, srv_count, true); +} + +/** + * @brief Disable mDNS interface + */ +void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + _mdns_clean_netif_ptr(tcpip_if); + + if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { + _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); + mdns_pcb_deinit_local(tcpip_if, ip_protocol); + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if != MDNS_MAX_INTERFACES && s_pcbs[other_if][ip_protocol].state == PCB_DUP) { + s_pcbs[other_if][ip_protocol].state = PCB_OFF; + _mdns_enable_pcb(other_if, ip_protocol); + } + } + s_pcbs[tcpip_if][ip_protocol].state = PCB_OFF; +} + +/** + * @brief Enable mDNS interface + */ +void _mdns_enable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (!mdns_is_netif_ready(tcpip_if, ip_protocol)) { + if (_mdns_pcb_init(tcpip_if, ip_protocol)) { + s_pcbs[tcpip_if][ip_protocol].failed_probes = 0; + return; + } + } + _mdns_restart_pcb(tcpip_if, ip_protocol); +} + +/** + * @brief Set interface as duplicate if another is found on the same subnet + */ +void _mdns_dup_interface(mdns_if_t tcpip_if) +{ + uint8_t i; + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if == MDNS_MAX_INTERFACES) { + return; // no other interface found + } + for (i = 0; i < MDNS_IP_PROTOCOL_MAX; i++) { + if (mdns_is_netif_ready(other_if, i)) { + //stop this interface and mark as dup + if (mdns_is_netif_ready(tcpip_if, i)) { + _mdns_clear_pcb_tx_queue_head(tcpip_if, i); + mdns_pcb_deinit_local(tcpip_if, i); + } + s_pcbs[tcpip_if][i].state = PCB_DUP; +// _mdns_server->interfaces[tcpip_if].pcbs[i].state = PCB_DUP; + _mdns_announce_pcb(other_if, i, NULL, 0, true); + } + } +} + +bool mdns_responder_is_off(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + return s_pcbs[tcpip_if][ip_protocol].state == PCB_OFF; +} + +void mdns_responder_process_tx_packet(mdns_tx_packet_t *p) +{ + mdns_pcb_t *pcb = &s_pcbs[p->tcpip_if][p->ip_protocol]; + mdns_out_question_t *q = NULL; + mdns_tx_packet_t *a = NULL; + uint32_t send_after = 1000; + switch (pcb->state) { + case PCB_PROBE_1: + q = p->questions; + while (q) { + q->unicast = false; + q = q->next; + } + //fallthrough + case PCB_PROBE_2: + _mdns_schedule_tx_packet(p, 250); + pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); + break; + case PCB_PROBE_3: + a = _mdns_create_announce_from_probe(p); + if (!a) { + _mdns_schedule_tx_packet(p, 250); + break; + } + pcb->probe_running = false; + pcb->probe_ip = false; + pcb->probe_services_len = 0; + pcb->failed_probes = 0; + mdns_mem_free(pcb->probe_services); + pcb->probe_services = NULL; + _mdns_free_tx_packet(p); + p = a; + send_after = 250; + //fallthrough + case PCB_ANNOUNCE_1: + //fallthrough + case PCB_ANNOUNCE_2: + _mdns_schedule_tx_packet(p, send_after); + pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); + break; + case PCB_ANNOUNCE_3: + pcb->state = PCB_RUNNING; + _mdns_free_tx_packet(p); + break; + default: + _mdns_free_tx_packet(p); + break; + } +} + +void mdns_responder_check_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_service_t *service, bool removed_answers, bool *should_remove_questions) +{ + mdns_pcb_t *_pcb = &s_pcbs[tcpip_if][ip_protocol]; + + if (PCB_STATE_IS_PROBING(_pcb)) { + uint8_t i; + //check if we are probing this service + for (i = 0; i < _pcb->probe_services_len; i++) { + mdns_srv_item_t *s = _pcb->probe_services[i]; + if (s->service == service) { + break; + } + } + if (i < _pcb->probe_services_len) { + if (_pcb->probe_services_len > 1) { + uint8_t n; + for (n = (i + 1); n < _pcb->probe_services_len; n++) { + _pcb->probe_services[n - 1] = _pcb->probe_services[n]; + } + _pcb->probe_services_len--; + } else { + _pcb->probe_services_len = 0; + mdns_mem_free(_pcb->probe_services); + _pcb->probe_services = NULL; + if (!_pcb->probe_ip) { + _pcb->probe_running = false; + _pcb->state = PCB_RUNNING; + } + } + *should_remove_questions = true; + return; + } + } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { + //if answers were cleared, set to running + if (removed_answers) { + _pcb->state = PCB_RUNNING; + } + } + *should_remove_questions = false; +} + +void mdns_responder_deinit(void) +{ + for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (int j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + mdns_pcb_deinit_local(i, j); + } + } +} + +bool mdsn_responder_iface_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + return mdns_is_netif_ready(tcpip_if, ip_protocol) && s_pcbs[tcpip_if][ip_protocol].state > PCB_INIT; +} + +bool mdns_responder_is_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + return s_pcbs[tcpip_if][ip_protocol].state == PCB_DUP; +} + +bool mdns_responder_is_probing(mdns_rx_packet_t *packet) +{ + return s_pcbs[packet->tcpip_if][packet->ip_protocol].probe_running; +} + +bool mdns_responder_after_probing(mdns_rx_packet_t *packet) +{ + return s_pcbs[packet->tcpip_if][packet->ip_protocol].state > PCB_PROBE_3; +} + +void mdns_responder_probe_failed(mdns_rx_packet_t *packet) +{ + s_pcbs[packet->tcpip_if][packet->ip_protocol].failed_probes++; +} + + + + +/** + * @brief Send probe for additional services on particular PCB + */ +static void _mdns_init_pcb_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) +{ + mdns_pcb_t *pcb = &s_pcbs[tcpip_if][ip_protocol]; + size_t services_final_len = len; + + if (PCB_STATE_IS_PROBING(pcb)) { + services_final_len += pcb->probe_services_len; + } + mdns_srv_item_t **_services = NULL; + if (services_final_len) { + _services = (mdns_srv_item_t **)mdns_mem_malloc(sizeof(mdns_srv_item_t *) * services_final_len); + if (!_services) { + HOOK_MALLOC_FAILED; + return; + } + + size_t i; + for (i = 0; i < len; i++) { + _services[i] = services[i]; + } + if (pcb->probe_services) { + for (i = 0; i < pcb->probe_services_len; i++) { + _services[len + i] = pcb->probe_services[i]; + } + mdns_mem_free(pcb->probe_services); + } + } + + probe_ip = pcb->probe_ip || probe_ip; + + pcb->probe_ip = false; + pcb->probe_services = NULL; + pcb->probe_services_len = 0; + pcb->probe_running = false; + + mdns_tx_packet_t *packet = _mdns_create_probe_packet(tcpip_if, ip_protocol, _services, services_final_len, true, probe_ip); + if (!packet) { + mdns_mem_free(_services); + return; + } + + pcb->probe_ip = probe_ip; + pcb->probe_services = _services; + pcb->probe_services_len = services_final_len; + pcb->probe_running = true; + _mdns_schedule_tx_packet(packet, ((pcb->failed_probes > 5) ? 1000 : 120) + (esp_random() & 0x7F)); + pcb->state = PCB_PROBE_1; +} + +/** + * @brief Send probe for particular services on particular PCB + * + * Tests possible duplication on probing service structure and probes only for new entries. + * - If pcb probing then add only non-probing services and restarts probing + * - If pcb not probing, run probing for all specified services + */ +void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) +{ + mdns_pcb_t *pcb = &s_pcbs[tcpip_if][ip_protocol]; + + _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); + + if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { + pcb->state = PCB_RUNNING; + return; + } + + if (PCB_STATE_IS_PROBING(pcb)) { + // Looking for already probing services to resolve duplications + mdns_srv_item_t *new_probe_services[len]; + int new_probe_service_len = 0; + bool found; + for (size_t j = 0; j < len; ++j) { + found = false; + for (int i = 0; i < pcb->probe_services_len; ++i) { + if (pcb->probe_services[i] == services[j]) { + found = true; + break; + } + } + if (!found) { + new_probe_services[new_probe_service_len++] = services[j]; + } + } + // init probing for newly added services + _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, + new_probe_service_len ? new_probe_services : NULL, new_probe_service_len, probe_ip); + } else { + // not probing, so init for all services + _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, services, len, probe_ip); + } +} + +/** + * @brief Send by for particular services + */ +void _mdns_send_bye(mdns_srv_item_t **services, size_t len, bool include_ip) +{ + uint8_t i, j; + if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { + return; + } + + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + if (mdns_is_netif_ready(i, j) && s_pcbs[i][j].state == PCB_RUNNING) { + _mdns_pcb_send_bye((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); + } + } + } +} + +/** + * @brief Send probe on all active PCBs + */ +void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe) +{ + uint8_t i, j; + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + if (mdns_is_netif_ready(i, j)) { + mdns_pcb_t *_pcb = &s_pcbs[i][j]; + if (clear_old_probe) { + mdns_mem_free(_pcb->probe_services); + _pcb->probe_services = NULL; + _pcb->probe_services_len = 0; + _pcb->probe_running = false; + } + _mdns_init_pcb_probe((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, probe_ip); + } + } + } +} diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index 90f1ebc9c9..802ac99ac9 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -13,6 +13,7 @@ #include "esp_log.h" #include "mdns_debug.h" #include "mdns_netif.h" +#include "mdns_responder.h" static const char *TAG = "mdns_send"; static const char *MDNS_SUB_STR = "_sub"; @@ -44,7 +45,7 @@ static inline void _mdns_set_u16(uint8_t *packet, uint16_t index, uint16_t value /** * @brief Allocate new packet for sending */ -static mdns_tx_packet_t *_mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +mdns_tx_packet_t *_mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_tx_packet_t *packet = (mdns_tx_packet_t *)mdns_mem_malloc(sizeof(mdns_tx_packet_t)); if (!packet) { @@ -1144,7 +1145,7 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an else if (answer->type == MDNS_TYPE_A) { if (answer->host == mdns_utils_get_selfhost()) { esp_netif_ip_info_t if_ip_info; - if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && !mdns_utils_is_pcb_duplicate(tcpip_if, MDNS_IP_PROTOCOL_V4)) { + if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && !mdns_responder_is_duplicate(tcpip_if, MDNS_IP_PROTOCOL_V4)) { return 0; } if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { @@ -1174,7 +1175,7 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an if (answer->host == mdns_utils_get_selfhost()) { struct esp_ip6_addr if_ip6s[NETIF_IPV6_MAX_NUMS]; uint8_t count = 0; - if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && !mdns_utils_is_pcb_duplicate(tcpip_if, MDNS_IP_PROTOCOL_V6)) { + if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && !mdns_responder_is_duplicate(tcpip_if, MDNS_IP_PROTOCOL_V6)) { return 0; } count = esp_netif_get_all_ip6(_mdns_get_esp_netif(tcpip_if), if_ip6s); @@ -1267,108 +1268,8 @@ void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p) _mdns_udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); } -/** - * @brief Create search packet for particular interface - */ -static mdns_tx_packet_t *_mdns_create_search_packet(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_result_t *r = NULL; - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); - if (!packet) { - return NULL; - } - - mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); - if (!q) { - HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); - return NULL; - } - q->next = NULL; - q->unicast = search->unicast; - q->type = search->type; - q->host = search->instance; - q->service = search->service; - q->proto = search->proto; - q->domain = MDNS_UTILS_DEFAULT_DOMAIN; - q->own_dynamic_memory = false; - queueToEnd(mdns_out_question_t, packet->questions, q); - - if (search->type == MDNS_TYPE_PTR) { - r = search->result; - while (r) { - //full record on the same interface is available - if (r->esp_netif != _mdns_get_esp_netif(tcpip_if) || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { - r = r->next; - continue; - } - mdns_out_answer_t *a = (mdns_out_answer_t *)mdns_mem_malloc(sizeof(mdns_out_answer_t)); - if (!a) { - HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); - return NULL; - } - a->type = MDNS_TYPE_PTR; - a->service = NULL; - a->custom_instance = r->instance_name; - a->custom_service = search->service; - a->custom_proto = search->proto; - a->bye = false; - a->flush = false; - a->next = NULL; - queueToEnd(mdns_out_answer_t, packet->answers, a); - r = r->next; - } - } - - return packet; -} - - -/** - * @brief Send search packet to particular interface - */ -void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_tx_packet_t *packet = NULL; - if (mdns_is_netif_ready(tcpip_if, ip_protocol) && mdns_utils_is_pcb_after_init(tcpip_if, ip_protocol)) { - packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol); - if (!packet) { - return; - } - _mdns_dispatch_tx_packet(packet); - _mdns_free_tx_packet(packet); - } -} -/** - * @brief Send search packet to all available interfaces - */ -void _mdns_search_send(mdns_search_once_t *search) -{ - mdns_search_once_t *queue = mdns_utils_get_search(); - bool found = false; - // looking for this search in active searches - while (queue) { - if (queue == search) { - found = true; - break; - } - queue = queue->next; - } - if (!found) { - // no longer active -> skip sending this search - return; - } - - uint8_t i, j; - for (i = 0; i < MDNS_MAX_INTERFACES; i++) { - for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - _mdns_search_send_pcb(search, (mdns_if_t)i, (mdns_ip_protocol_t)j); - } - } -} /** @@ -1737,61 +1638,28 @@ void _mdns_remove_scheduled_service_packets(mdns_service_t *service) _mdns_dealloc_scheduled_service_answers(&(q->additional), service); _mdns_dealloc_scheduled_service_answers(&(q->servers), service); - - mdns_pcb_t *_pcb = mdns_utils_get_pcb(q->tcpip_if, q->ip_protocol); if (mdns_is_netif_ready(q->tcpip_if, q->ip_protocol)) { - if (PCB_STATE_IS_PROBING(_pcb)) { - uint8_t i; - //check if we are probing this service - for (i = 0; i < _pcb->probe_services_len; i++) { - mdns_srv_item_t *s = _pcb->probe_services[i]; - if (s->service == service) { - break; - } - } - if (i < _pcb->probe_services_len) { - if (_pcb->probe_services_len > 1) { - uint8_t n; - for (n = (i + 1); n < _pcb->probe_services_len; n++) { - _pcb->probe_services[n - 1] = _pcb->probe_services[n]; - } - _pcb->probe_services_len--; - } else { - _pcb->probe_services_len = 0; - mdns_mem_free(_pcb->probe_services); - _pcb->probe_services = NULL; - if (!_pcb->probe_ip) { - _pcb->probe_running = false; - _pcb->state = PCB_RUNNING; + bool should_remove_questions = false; + mdns_responder_check_pcb(q->tcpip_if, q->ip_protocol, service, had_answers && q->answers == NULL, &should_remove_questions); + if (should_remove_questions && q->questions) { + mdns_out_question_t *qsn = NULL; + mdns_out_question_t *qs = q->questions; + if (qs->type == MDNS_TYPE_ANY + && qs->service && strcmp(qs->service, service->service) == 0 + && qs->proto && strcmp(qs->proto, service->proto) == 0) { + q->questions = q->questions->next; + mdns_mem_free(qs); + } else while (qs->next) { + qsn = qs->next; + if (qsn->type == MDNS_TYPE_ANY + && qsn->service && strcmp(qsn->service, service->service) == 0 + && qsn->proto && strcmp(qsn->proto, service->proto) == 0) { + qs->next = qsn->next; + mdns_mem_free(qsn); + break; } + qs = qs->next; } - - if (q->questions) { - mdns_out_question_t *qsn = NULL; - mdns_out_question_t *qs = q->questions; - if (qs->type == MDNS_TYPE_ANY - && qs->service && strcmp(qs->service, service->service) == 0 - && qs->proto && strcmp(qs->proto, service->proto) == 0) { - q->questions = q->questions->next; - mdns_mem_free(qs); - } else while (qs->next) { - qsn = qs->next; - if (qsn->type == MDNS_TYPE_ANY - && qsn->service && strcmp(qsn->service, service->service) == 0 - && qsn->proto && strcmp(qsn->proto, service->proto) == 0) { - qs->next = qsn->next; - mdns_mem_free(qsn); - break; - } - qs = qs->next; - } - } - } - } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { - //if answers were cleared, set to running - if (had_answers && q->answers == NULL) { - _pcb->state = PCB_RUNNING; - } } } @@ -1804,81 +1672,14 @@ void _mdns_remove_scheduled_service_packets(mdns_service_t *service) } } -///** -// * @brief Send by for particular services -// */ -//static void _mdns_send_bye(mdns_srv_item_t **services, size_t len, bool include_ip) -//{ -// uint8_t i, j; -// if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { -// return; -// } -// -// for (i = 0; i < MDNS_MAX_INTERFACES; i++) { -// for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { -// mdns_pcb_t *pcb = mdns_utils_get_pcb((mdns_if_t)i, (mdns_ip_protocol_t)j); -// if (mdns_is_netif_ready(i, j) && pcb->state == PCB_RUNNING) { -// _mdns_pcb_send_bye((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); -// } -// } -// } -//} - static void _mdns_tx_handle_packet(mdns_tx_packet_t *p) { - mdns_tx_packet_t *a = NULL; - mdns_out_question_t *q = NULL; - mdns_pcb_t *pcb = mdns_utils_get_pcb(p->tcpip_if, p->ip_protocol); - uint32_t send_after = 1000; - - if (pcb->state == PCB_OFF) { + if (mdns_responder_is_off(p->tcpip_if, p->ip_protocol)) { _mdns_free_tx_packet(p); return; } _mdns_dispatch_tx_packet(p); - - switch (pcb->state) { - case PCB_PROBE_1: - q = p->questions; - while (q) { - q->unicast = false; - q = q->next; - } - //fallthrough - case PCB_PROBE_2: - _mdns_schedule_tx_packet(p, 250); - pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); - break; - case PCB_PROBE_3: - a = _mdns_create_announce_from_probe(p); - if (!a) { - _mdns_schedule_tx_packet(p, 250); - break; - } - pcb->probe_running = false; - pcb->probe_ip = false; - pcb->probe_services_len = 0; - pcb->failed_probes = 0; - mdns_mem_free(pcb->probe_services); - pcb->probe_services = NULL; - _mdns_free_tx_packet(p); - p = a; - send_after = 250; - //fallthrough - case PCB_ANNOUNCE_1: - //fallthrough - case PCB_ANNOUNCE_2: - _mdns_schedule_tx_packet(p, send_after); - pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); - break; - case PCB_ANNOUNCE_3: - pcb->state = PCB_RUNNING; - _mdns_free_tx_packet(p); - break; - default: - _mdns_free_tx_packet(p); - break; - } + mdns_responder_process_tx_packet(p); } void mdns_send_handle_tx_packet(mdns_tx_packet_t *packet) diff --git a/components/mdns/private_include/mdns_browse.h b/components/mdns/private_include/mdns_browse.h index 3962234b21..37e901e275 100644 --- a/components/mdns/private_include/mdns_browse.h +++ b/components/mdns/private_include/mdns_browse.h @@ -19,8 +19,12 @@ void _mdns_browse_sync(mdns_browse_sync_t *browse_sync); void _mdns_browse_finish(mdns_browse_t *browse); void _mdns_browse_add(mdns_browse_t *browse); void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface); +void mdns_browse_free(void); void _mdns_browse_item_free(mdns_browse_t *browse); +mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +void mdns_browse_send_all(mdns_if_t mdns_if); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_netif.h b/components/mdns/private_include/mdns_netif.h index a52407605c..9e1acfe3b1 100644 --- a/components/mdns/private_include/mdns_netif.h +++ b/components/mdns/private_include/mdns_netif.h @@ -19,8 +19,8 @@ mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if); esp_err_t mdns_netif_init(void); esp_err_t mdns_netif_deinit(void); void unregister_predefined_handlers(void); -esp_err_t mdns_netif_free(void); void _mdns_dup_interface(mdns_if_t tcpip_if); +void _mdns_clean_netif_ptr(mdns_if_t tcpip_if); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index c2bb9fb6be..e0c6797bdf 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -401,18 +401,18 @@ typedef struct mdns_browse_sync { } mdns_browse_sync_t; typedef struct mdns_server_s { - struct { - mdns_pcb_t pcbs[MDNS_IP_PROTOCOL_MAX]; - } interfaces[MDNS_MAX_INTERFACES]; +// struct { +// mdns_pcb_t pcbs[MDNS_IP_PROTOCOL_MAX]; +// } interfaces[MDNS_MAX_INTERFACES]; const char *hostname; const char *instance; mdns_srv_item_t *services; QueueHandle_t action_queue; SemaphoreHandle_t action_sema; // mdns_tx_packet_t *tx_queue_head; - mdns_search_once_t *search_once; +// mdns_search_once_t *search_once; esp_timer_handle_t timer_handle; - mdns_browse_t *browse; +// mdns_browse_t *browse; } mdns_server_t; typedef struct { diff --git a/components/mdns/private_include/mdns_querier.h b/components/mdns/private_include/mdns_querier.h index e984dca69e..660642a813 100644 --- a/components/mdns/private_include/mdns_querier.h +++ b/components/mdns/private_include/mdns_querier.h @@ -13,6 +13,15 @@ extern "C" { #endif void _mdns_query_results_free(mdns_result_t *results); +void _mdns_search_add(mdns_search_once_t *search); +void _mdns_search_finish(mdns_search_once_t *search); +void _mdns_search_run(void); +void mdns_search_free(void); +void _mdns_search_finish_done(void); +void _mdns_search_send(mdns_search_once_t *search); +mdns_search_once_t *_mdns_search_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +void _mdns_search_free(mdns_search_once_t *search); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_responder.h b/components/mdns/private_include/mdns_responder.h index 1c09a02895..1d5eb4e888 100644 --- a/components/mdns/private_include/mdns_responder.h +++ b/components/mdns/private_include/mdns_responder.h @@ -13,7 +13,17 @@ extern "C" { #endif void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); +bool mdns_responder_is_off(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +void mdns_responder_process_tx_packet(mdns_tx_packet_t *p); +void mdns_responder_check_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_service_t *service, bool removed_answers, bool *should_remove_questions); +void mdns_responder_deinit(void); +bool mdsn_responder_iface_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +bool mdns_responder_is_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +bool mdns_responder_is_probing(mdns_rx_packet_t *packet); +void mdns_responder_probe_failed(mdns_rx_packet_t *packet); +bool mdns_responder_after_probing(mdns_rx_packet_t *packet); +void _mdns_send_bye(mdns_srv_item_t **services, size_t len, bool include_ip); #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_send.h b/components/mdns/private_include/mdns_send.h index 89635341f5..8dea10a7c3 100644 --- a/components/mdns/private_include/mdns_send.h +++ b/components/mdns/private_include/mdns_send.h @@ -14,8 +14,6 @@ extern "C" { void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -void _mdns_search_send(mdns_search_once_t *search); - void _mdns_free_tx_packet(mdns_tx_packet_t *packet); mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool first, bool include_ip); @@ -36,6 +34,7 @@ mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol mdns_tx_packet_t *_mdns_get_next_tx_packet(void); void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service); void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service); +mdns_tx_packet_t *_mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_utils.h b/components/mdns/private_include/mdns_utils.h index a86ce4dc93..bc588ce52b 100644 --- a/components/mdns/private_include/mdns_utils.h +++ b/components/mdns/private_include/mdns_utils.h @@ -48,7 +48,7 @@ const uint8_t *_mdns_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdn const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len); bool is_mdns_server(void); -mdns_pcb_t *mdns_utils_get_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +//mdns_pcb_t *mdns_utils_get_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); const char *mdns_utils_get_global_hostname(void); mdns_srv_item_t *mdns_utils_get_services(void); mdns_host_item_t *mdns_utils_get_hosts(void); @@ -56,14 +56,14 @@ mdns_host_item_t *mdns_utils_get_selfhost(void); void mdns_utils_set_global_hostname(const char *hostname); const char *mdns_utils_get_instance(void); void mdns_utils_set_instance(const char *instance); -mdns_search_once_t *mdns_utils_get_search(void); -mdns_browse_t *mdns_utils_get_browse(void); -mdns_tx_packet_t *mdns_utils_get_tx_packet(void); -bool mdns_utils_is_probing(mdns_rx_packet_t *packet); -bool mdns_utils_is_pcb_after_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -bool mdns_utils_is_pcb_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -bool mdns_utils_after_probing(mdns_rx_packet_t *packet); -void mdns_utils_probe_failed(mdns_rx_packet_t *packet); +//mdns_search_once_t *mdns_utils_get_search(void); +//mdns_browse_t *mdns_utils_get_browse(void); +//mdns_tx_packet_t *mdns_utils_get_tx_packet(void); +//bool mdns_utils_is_probing(mdns_rx_packet_t *packet); +//bool mdns_utils_is_pcb_after_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +//bool mdns_utils_is_pcb_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +//bool mdns_utils_after_probing(mdns_rx_packet_t *packet); +//void mdns_utils_probe_failed(mdns_rx_packet_t *packet); void _mdns_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after); void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe); @@ -274,3 +274,5 @@ esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions void mdns_service_lock(void); void mdns_service_unlock(void); + +esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); diff --git a/components/mdns/tests/test_afl_fuzz_host/Makefile b/components/mdns/tests/test_afl_fuzz_host/Makefile index cb499c1c6e..8d00b3e346 100644 --- a/components/mdns/tests/test_afl_fuzz_host/Makefile +++ b/components/mdns/tests/test_afl_fuzz_host/Makefile @@ -71,6 +71,11 @@ mdns.o: ../../mdns.c @echo "[CC] $<" @$(CC) $(CFLAGS) -include mdns_mock.h $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@ +mdns_querier.o: ../../mdns_querier.c + @echo "[CC] $<" + @$(CC) $(CFLAGS) -include mdns_mock.h -include mdns_querier_di.h -c $< -o $@ + + %.o: ../../%.c @echo "[CC] $<" @$(CC) $(CFLAGS) -include mdns_mock.h -c $< -o $@ diff --git a/components/mdns/tests/test_afl_fuzz_host/mdns_di.h b/components/mdns/tests/test_afl_fuzz_host/mdns_di.h index ed56960f47..11ecd3466d 100644 --- a/components/mdns/tests/test_afl_fuzz_host/mdns_di.h +++ b/components/mdns/tests/test_afl_fuzz_host/mdns_di.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -11,51 +11,18 @@ #include "mdns.h" #include "mdns_private.h" -void (*mdns_test_static_execute_action)(mdns_action_t *) = NULL; +void (*mdns_test_static_execute_action)(mdns_action_t *) = NULL; mdns_srv_item_t *(*mdns_test_static_mdns_get_service_item)(const char *service, const char *proto, const char *hostname) = NULL; -mdns_search_once_t *(*mdns_test_static_search_init)(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, - uint32_t timeout, uint8_t max_results, - mdns_query_notify_t notifier) = NULL; -esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t *search) = NULL; -void (*mdns_test_static_search_free)(mdns_search_once_t *search) = NULL; +esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t *search) = NULL; static void _mdns_execute_action(mdns_action_t *action); -static mdns_srv_item_t *_mdns_get_service_item(const char *service, const char *proto, const char *hostname); -static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, - uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier); -static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); -static void _mdns_search_free(mdns_search_once_t *search); void mdns_test_init_di(void) { mdns_test_static_execute_action = _mdns_execute_action; - mdns_test_static_mdns_get_service_item = _mdns_get_service_item; - mdns_test_static_search_init = _mdns_search_init; - mdns_test_static_send_search_action = _mdns_send_search_action; - mdns_test_static_search_free = _mdns_search_free; } void mdns_test_execute_action(void *action) { mdns_test_static_execute_action((mdns_action_t *)action); } - -void mdns_test_search_free(mdns_search_once_t *search) -{ - return mdns_test_static_search_free(search); -} - -esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t *search) -{ - return mdns_test_static_send_search_action(type, search); -} - -mdns_search_once_t *mdns_test_search_init(const char *name, const char *service, const char *proto, uint16_t type, uint32_t timeout, uint8_t max_results) -{ - return mdns_test_static_search_init(name, service, proto, type, timeout, type != MDNS_TYPE_PTR, max_results, NULL); -} - -mdns_srv_item_t *mdns_test_mdns_get_service_item(const char *service, const char *proto) -{ - return mdns_test_static_mdns_get_service_item(service, proto, NULL); -} diff --git a/components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h b/components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h new file mode 100644 index 0000000000..7b8badd8a1 --- /dev/null +++ b/components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* + * MDNS Dependecy injection -- preincluded to inject interface test functions into static variables + * + */ + +#include "mdns.h" +#include "mdns_private.h" + +mdns_search_once_t *(*mdns_test_static_search_init)(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, + uint32_t timeout, uint8_t max_results, + mdns_query_notify_t notifier) = NULL; + +static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, + uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier); + +void mdns_querier_test_init_di(void) +{ + mdns_test_static_search_init = _mdns_search_init; +} + + +mdns_search_once_t *mdns_test_search_init(const char *name, const char *service, const char *proto, uint16_t type, uint32_t timeout, uint8_t max_results) +{ + return mdns_test_static_search_init(name, service, proto, type, timeout, type != MDNS_TYPE_PTR, max_results, NULL); +} diff --git a/components/mdns/tests/test_afl_fuzz_host/test.c b/components/mdns/tests/test_afl_fuzz_host/test.c index afbf023843..61336da0e2 100644 --- a/components/mdns/tests/test_afl_fuzz_host/test.c +++ b/components/mdns/tests/test_afl_fuzz_host/test.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,8 @@ #include "esp32_mock.h" #include "mdns.h" #include "mdns_private.h" +#include "mdns_utils.h" +#include "mdns_querier.h" // // Global stuctures containing packet payload, search @@ -23,10 +25,7 @@ mdns_search_once_t *search = NULL; // // Dependency injected test functions void mdns_test_execute_action(void *action); -mdns_srv_item_t *mdns_test_mdns_get_service_item(const char *service, const char *proto); mdns_search_once_t *mdns_test_search_init(const char *name, const char *service, const char *proto, uint16_t type, uint32_t timeout, uint8_t max_results); -esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); -void mdns_test_search_free(mdns_search_once_t *search); void mdns_test_init_di(void); extern mdns_server_t *_mdns_server; @@ -35,8 +34,8 @@ extern mdns_server_t *_mdns_server; static int mdns_test_hostname_set(const char *mdns_hostname) { for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { - _mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V4].state = PCB_RUNNING; // mark the PCB running to exercise mdns in fully operational mode - _mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V6].state = PCB_RUNNING; + // _mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V4].state = PCB_RUNNING; // mark the PCB running to exercise mdns in fully operational mode + // _mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V6].state = PCB_RUNNING; } int ret = mdns_hostname_set(mdns_hostname); mdns_action_t *a = NULL; @@ -84,7 +83,7 @@ static int mdns_test_sub_service_add(const char *sub_name, const char *service_n GetLastItem(&a); mdns_test_execute_action(a); - if (mdns_test_mdns_get_service_item(service_name, proto) == NULL) { + if (_mdns_get_service_item(service_name, proto, NULL) == NULL) { return ESP_FAIL; } int ret = mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name); @@ -103,7 +102,7 @@ static int mdns_test_service_add(const char *service_name, const char *proto, ui GetLastItem(&a); mdns_test_execute_action(a); - if (mdns_test_mdns_get_service_item(service_name, proto) == NULL) { + if (_mdns_get_service_item(service_name, proto, NULL) == NULL) { return ESP_FAIL; } return ESP_OK; @@ -116,8 +115,8 @@ static mdns_result_t *mdns_test_query(const char *name, const char *service, con abort(); } - if (mdns_test_send_search_action(ACTION_SEARCH_ADD, search)) { - mdns_test_search_free(search); + if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { + _mdns_search_free(search); abort(); } @@ -129,7 +128,7 @@ static mdns_result_t *mdns_test_query(const char *name, const char *service, con static void mdns_test_query_free(void) { - mdns_test_search_free(search); + _mdns_search_free(search); } // From ff5cef6d89234fb531e07e53c83f6ea273a33d09 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 11 Mar 2025 14:08:41 +0100 Subject: [PATCH 06/27] feat(mdns): action queue abstraction --- components/mdns/mdns.c | 565 +----------------- components/mdns/mdns_browser.c | 163 +++-- components/mdns/mdns_netif.c | 26 +- components/mdns/mdns_networking_lwip.c | 20 + components/mdns/mdns_networking_socket.c | 21 + components/mdns/mdns_packet.c | 43 +- components/mdns/mdns_querier.c | 187 +++++- components/mdns/mdns_send.c | 224 ++++++- components/mdns/mdns_utils.c | 18 +- components/mdns/private_include/mdns_browse.h | 11 +- .../mdns/private_include/mdns_networking.h | 7 +- .../mdns/private_include/mdns_private.h | 4 + .../mdns/private_include/mdns_querier.h | 10 +- .../mdns/private_include/mdns_receive.h | 19 + components/mdns/private_include/mdns_send.h | 4 +- components/mdns/private_include/mdns_utils.h | 176 +----- .../mdns/tests/test_afl_fuzz_host/mdns_di.h | 2 +- .../test_afl_fuzz_host/mdns_querier_di.h | 17 + .../mdns/tests/test_afl_fuzz_host/test.c | 11 +- 19 files changed, 708 insertions(+), 820 deletions(-) create mode 100644 components/mdns/private_include/mdns_receive.h diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index e97a31d3f2..8784034b7d 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -21,21 +21,10 @@ #include "mdns_browse.h" #include "mdns_netif.h" #include "mdns_send.h" +#include "mdns_receive.h" #include "mdns_querier.h" #include "mdns_responder.h" - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) -#endif - -// Internal size of IPv6 address is defined here as size of AAAA record in mdns packet -// since the ip6_addr_t is defined in lwip and depends on using IPv6 zones -#define _MDNS_SIZEOF_IP6_ADDR (MDNS_ANSWER_AAAA_SIZE) - -//static const char *MDNS_DEFAULT_DOMAIN = "local"; -//static const char *MDNS_SUB_STR = "_sub"; - mdns_server_t *_mdns_server = NULL; static mdns_host_item_t *_mdns_host_list = NULL; static mdns_host_item_t _mdns_self_host; @@ -46,21 +35,8 @@ static volatile TaskHandle_t _mdns_service_task_handle = NULL; static SemaphoreHandle_t _mdns_service_semaphore = NULL; static StackType_t *_mdns_stack_buffer; - -//static bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye); - esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); -//static void _mdns_query_results_free(mdns_result_t *results); - - - - - - - - - const char *mdns_utils_get_global_hostname(void) { return _mdns_server ? _mdns_server->hostname : NULL; @@ -81,7 +57,6 @@ mdns_host_item_t *mdns_utils_get_selfhost(void) return &_mdns_self_host; } - void mdns_utils_set_global_hostname(const char *hostname) { if (_mdns_server) { @@ -108,11 +83,6 @@ void mdns_utils_set_instance(const char *instance) } } -//mdns_search_once_t *mdns_utils_get_search(void) -//{ -// return _mdns_server->search_once; -//} - bool is_mdns_server(void) { return _mdns_server != NULL; @@ -123,18 +93,6 @@ static inline bool _str_null_or_empty(const char *str) return (str == NULL || *str == 0); } -//mdns_tx_packet_t *mdns_utils_get_tx_packet(void) -//{ -// return _mdns_server->tx_queue_head; -//} - - - - - - - - static bool _mdns_can_add_more_services(void) { #if MDNS_MAX_SERVICES == 0 @@ -153,66 +111,13 @@ static bool _mdns_can_add_more_services(void) #endif } -esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) +bool mdns_action_queue(mdns_action_t *action) { - mdns_action_t *action = NULL; - - action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); - if (!action) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; - } - - action->type = ACTION_RX_HANDLE; - action->data.rx_handle.packet = packet; if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - mdns_mem_free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; -} - - - -#ifdef CONFIG_LWIP_IPV6 -/** - * @brief Check if IPv6 address is NULL - */ -bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) -{ - uint8_t i; - uint8_t *data = (uint8_t *)ip6.addr; - for (i = 0; i < _MDNS_SIZEOF_IP6_ADDR; i++) { - if (data[i]) { - return false; - } + return false; } return true; } -#endif /* CONFIG_LWIP_IPV6 */ - - - - - - - - - - - - - - - - - - - - - - - /** * @brief Send announcement on all active PCBs @@ -455,9 +360,6 @@ static mdns_service_t *_mdns_create_service(const char *service, const char *pro return NULL; } - - - static void _mdns_free_subtype(mdns_subtype_t *subtype) { while (subtype) { @@ -499,20 +401,6 @@ static void _mdns_free_service(mdns_service_t *service) mdns_mem_free(service); } - -/* - * Received Packet Handling - * */ - - - - - - - - - - /** * @brief Adds a delegated hostname to the linked list * @param hostname Host name pointer @@ -619,30 +507,6 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) return true; } - - - - - - - - - - - - - - - - - - -void mdns_parse_packet(mdns_rx_packet_t *packet); - - - - - #ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES static inline char nibble_to_hex(int var) { @@ -696,7 +560,7 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) #ifdef CONFIG_LWIP_IPV6 if (action & MDNS_EVENT_IP6_REVERSE_LOOKUP) { esp_ip6_addr_t addr6; - if (!esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(mdns_if), &addr6) && !_ipv6_address_is_zero(addr6)) { + if (!esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(mdns_if), &addr6) && !mdns_utils_ipv6_address_is_zero(addr6)) { uint8_t *paddr = (uint8_t *)&addr6.addr; const char sub[] = "ip6"; const size_t query_name_size = 4 * sizeof(addr6.addr) /* (2 nibbles + 2 dots)/per byte of IP address */ + sizeof(sub); @@ -721,28 +585,6 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) #endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ } - - - - - - - - - - - - - - - - - - - - - - void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) { mdns_srv_item_t *service = _mdns_server->services; @@ -757,18 +599,6 @@ void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new } } -static void _mdns_sync_browse_result_link_free(mdns_browse_sync_t *browse_sync) -{ - mdns_browse_result_sync_t *current = browse_sync->sync_result; - mdns_browse_result_sync_t *need_free; - while (current) { - need_free = current; - current = current->next; - mdns_mem_free(need_free); - } - mdns_mem_free(browse_sync); -} - /** * @brief Free action data */ @@ -782,25 +612,20 @@ static void _mdns_free_action(mdns_action_t *action) mdns_mem_free(action->data.instance); break; case ACTION_SEARCH_ADD: - //fallthrough case ACTION_SEARCH_SEND: - //fallthrough case ACTION_SEARCH_END: - _mdns_search_free(action->data.search_add.search); + mdns_query_action(action, ACTION_CLEANUP); break; case ACTION_BROWSE_ADD: - //fallthrough case ACTION_BROWSE_END: - _mdns_browse_item_free(action->data.browse_add.browse); - break; case ACTION_BROWSE_SYNC: - _mdns_sync_browse_result_link_free(action->data.browse_sync.browse_sync); + mdns_browse_action(action, ACTION_CLEANUP); break; case ACTION_TX_HANDLE: - _mdns_free_tx_packet(action->data.tx_handle.packet); + mdns_send_action(action, ACTION_CLEANUP); break; case ACTION_RX_HANDLE: - _mdns_packet_free(action->data.rx_handle.packet); + mdns_receive_action(action, ACTION_CLEANUP); break; case ACTION_DELEGATE_HOSTNAME_SET_ADDR: case ACTION_DELEGATE_HOSTNAME_ADD: @@ -842,32 +667,21 @@ static void _mdns_execute_action(mdns_action_t *action) break; case ACTION_SEARCH_ADD: - _mdns_search_add(action->data.search_add.search); - break; case ACTION_SEARCH_SEND: - _mdns_search_send(action->data.search_add.search); - break; case ACTION_SEARCH_END: - _mdns_search_finish(action->data.search_add.search); + mdns_query_action(action, ACTION_RUN); break; - case ACTION_BROWSE_ADD: - _mdns_browse_add(action->data.browse_add.browse); - break; case ACTION_BROWSE_SYNC: - _mdns_browse_sync(action->data.browse_sync.browse_sync); - _mdns_sync_browse_result_link_free(action->data.browse_sync.browse_sync); - break; case ACTION_BROWSE_END: - _mdns_browse_finish(action->data.browse_add.browse); + mdns_browse_action(action, ACTION_RUN); break; case ACTION_TX_HANDLE: - mdns_send_handle_tx_packet(action->data.tx_handle.packet); + mdns_send_action(action, ACTION_RUN); break; case ACTION_RX_HANDLE: - mdns_parse_packet(action->data.rx_handle.packet); - _mdns_packet_free(action->data.rx_handle.packet); + mdns_receive_action(action, ACTION_RUN); break; case ACTION_DELEGATE_HOSTNAME_ADD: if (!_mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, @@ -894,71 +708,6 @@ static void _mdns_execute_action(mdns_action_t *action) mdns_mem_free(action); } -/** - * @brief Queue search action - */ -esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search) -{ - mdns_action_t *action = NULL; - - action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); - if (!action) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; - } - - action->type = type; - action->data.search_add.search = search; - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - mdns_mem_free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; -} - -/** - * @brief Called from timer task to run mDNS responder - * - * periodically checks first unqueued packet (from tx head). - * if it is scheduled to be transmitted, then pushes the packet to action queue to be handled. - * - */ -static void _mdns_scheduler_run(void) -{ - MDNS_SERVICE_LOCK(); - mdns_tx_packet_t *p = _mdns_get_next_tx_packet(); - mdns_action_t *action = NULL; - - // find first unqueued packet - while (p && p->queued) { - p = p->next; - } - if (!p) { - MDNS_SERVICE_UNLOCK(); - return; - } - while (p && (int32_t)(p->send_at - (xTaskGetTickCount() * portTICK_PERIOD_MS)) < 0) { - action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); - if (action) { - action->type = ACTION_TX_HANDLE; - action->data.tx_handle.packet = p; - p->queued = true; - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - mdns_mem_free(action); - p->queued = false; - } - } else { - HOOK_MALLOC_FAILED; - break; - } - //Find the next unqued packet - p = p->next; - } - MDNS_SERVICE_UNLOCK(); -} - - - /** * @brief the main MDNS service task. Packets are received and parsed here */ @@ -986,7 +735,7 @@ static void _mdns_service_task(void *pvParameters) static void _mdns_timer_cb(void *arg) { - _mdns_scheduler_run(); + mdns_send_packets(); _mdns_search_run(); } @@ -1101,27 +850,6 @@ static esp_err_t _mdns_service_task_stop(void) return ESP_OK; } -esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action) -{ - if (!_mdns_server || 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 (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - mdns_mem_free(action); - } - return ESP_OK; -} - void mdns_service_lock(void) { MDNS_SERVICE_LOCK(); @@ -2161,131 +1889,6 @@ esp_err_t mdns_service_remove_all(void) return ret; } -///* -// * MDNS QUERY -// * */ -//void mdns_query_results_free(mdns_result_t *results) -//{ -// MDNS_SERVICE_LOCK(); -// _mdns_query_results_free(results); -// MDNS_SERVICE_UNLOCK(); -//} -// -//esp_err_t mdns_query_async_delete(mdns_search_once_t *search) -//{ -// if (!search) { -// return ESP_ERR_INVALID_ARG; -// } -// if (search->state != SEARCH_OFF) { -// return ESP_ERR_INVALID_STATE; -// } -// -// MDNS_SERVICE_LOCK(); -// _mdns_search_free(search); -// MDNS_SERVICE_UNLOCK(); -// -// return ESP_OK; -//} -// -//bool mdns_query_async_get_results(mdns_search_once_t *search, uint32_t timeout, mdns_result_t **results, uint8_t *num_results) -//{ -// if (xSemaphoreTake(search->done_semaphore, pdMS_TO_TICKS(timeout)) == pdTRUE) { -// if (results) { -// *results = search->result; -// } -// if (num_results) { -// *num_results = search->num_results; -// } -// return true; -// } -// return false; -//} -// -//mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, const char *proto, uint16_t type, -// uint32_t timeout, size_t max_results, mdns_query_notify_t notifier) -//{ -// mdns_search_once_t *search = NULL; -// -// if (!_mdns_server || !timeout || _str_null_or_empty(service) != _str_null_or_empty(proto)) { -// return NULL; -// } -// -// search = _mdns_search_init(name, service, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, notifier); -// if (!search) { -// return NULL; -// } -// -// if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { -// _mdns_search_free(search); -// return NULL; -// } -// -// return search; -//} -// -//esp_err_t mdns_query_generic(const char *name, const char *service, const char *proto, uint16_t type, mdns_query_transmission_type_t transmission_type, uint32_t timeout, size_t max_results, mdns_result_t **results) -//{ -// mdns_search_once_t *search = NULL; -// -// *results = NULL; -// -// if (!_mdns_server) { -// return ESP_ERR_INVALID_STATE; -// } -// -// if (!timeout || _str_null_or_empty(service) != _str_null_or_empty(proto)) { -// return ESP_ERR_INVALID_ARG; -// } -// -// search = _mdns_search_init(name, service, proto, type, transmission_type == MDNS_QUERY_UNICAST, timeout, max_results, NULL); -// if (!search) { -// return ESP_ERR_NO_MEM; -// } -// -// if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { -// _mdns_search_free(search); -// return ESP_ERR_NO_MEM; -// } -// xSemaphoreTake(search->done_semaphore, portMAX_DELAY); -// -// *results = search->result; -// _mdns_search_free(search); -// -// return ESP_OK; -//} -// -//esp_err_t mdns_query(const char *name, const char *service_type, const char *proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t **results) -//{ -// return mdns_query_generic(name, service_type, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, results); -//} -// -//esp_err_t mdns_query_ptr(const char *service, const char *proto, uint32_t timeout, size_t max_results, mdns_result_t **results) -//{ -// if (_str_null_or_empty(service) || _str_null_or_empty(proto)) { -// return ESP_ERR_INVALID_ARG; -// } -// -// return mdns_query(NULL, service, proto, MDNS_TYPE_PTR, timeout, max_results, results); -//} -// -//esp_err_t mdns_query_srv(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) -//{ -// if (_str_null_or_empty(instance) || _str_null_or_empty(service) || _str_null_or_empty(proto)) { -// return ESP_ERR_INVALID_ARG; -// } -// -// return mdns_query(instance, service, proto, MDNS_TYPE_SRV, timeout, 1, result); -//} -// -//esp_err_t mdns_query_txt(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) -//{ -// if (_str_null_or_empty(instance) || _str_null_or_empty(service) || _str_null_or_empty(proto)) { -// return ESP_ERR_INVALID_ARG; -// } -// -// return mdns_query(instance, service, proto, MDNS_TYPE_TXT, timeout, 1, result); -//} -// esp_err_t mdns_lookup_delegated_service(const char *instance, const char *service, const char *proto, size_t max_results, mdns_result_t **result) { @@ -2315,145 +1918,3 @@ esp_err_t mdns_lookup_selfhosted_service(const char *instance, const char *servi MDNS_SERVICE_UNLOCK(); return ESP_OK; } - -#ifdef CONFIG_LWIP_IPV4 -esp_err_t mdns_query_a(const char *name, uint32_t timeout, esp_ip4_addr_t *addr) -{ - mdns_result_t *result = NULL; - esp_err_t err; - - if (_str_null_or_empty(name)) { - return ESP_ERR_INVALID_ARG; - } - - if (strstr(name, ".local")) { - ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); - } - - err = mdns_query(name, NULL, NULL, MDNS_TYPE_A, timeout, 1, &result); - - if (err) { - return err; - } - - if (!result) { - return ESP_ERR_NOT_FOUND; - } - - mdns_ip_addr_t *a = result->addr; - while (a) { - if (a->addr.type == ESP_IPADDR_TYPE_V4) { - addr->addr = a->addr.u_addr.ip4.addr; - mdns_query_results_free(result); - return ESP_OK; - } - a = a->next; - } - - mdns_query_results_free(result); - return ESP_ERR_NOT_FOUND; -} -#endif /* CONFIG_LWIP_IPV4 */ - -#ifdef CONFIG_LWIP_IPV6 -esp_err_t mdns_query_aaaa(const char *name, uint32_t timeout, esp_ip6_addr_t *addr) -{ - mdns_result_t *result = NULL; - esp_err_t err; - - if (_str_null_or_empty(name)) { - return ESP_ERR_INVALID_ARG; - } - - if (strstr(name, ".local")) { - ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); - } - - err = mdns_query(name, NULL, NULL, MDNS_TYPE_AAAA, timeout, 1, &result); - - if (err) { - return err; - } - - if (!result) { - return ESP_ERR_NOT_FOUND; - } - - mdns_ip_addr_t *a = result->addr; - while (a) { - if (a->addr.type == ESP_IPADDR_TYPE_V6) { - memcpy(addr->addr, a->addr.u_addr.ip6.addr, 16); - mdns_query_results_free(result); - return ESP_OK; - } - a = a->next; - } - - mdns_query_results_free(result); - return ESP_ERR_NOT_FOUND; -} -#endif /* CONFIG_LWIP_IPV6 */ - - -/** - * @brief Browse sync result action - */ -esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync) -{ - mdns_action_t *action = NULL; - - action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); - if (!action) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; - } - - action->type = type; - action->data.browse_sync.browse_sync = browse_sync; - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - mdns_mem_free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; -} - -/** - * @brief Browse action - */ -esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse) -{ - mdns_action_t *action = NULL; - - action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); - - if (!action) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; - } - - action->type = type; - action->data.browse_add.browse = browse; - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - mdns_mem_free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; -} - -void _mdns_browse_sync(mdns_browse_sync_t *browse_sync) -{ - mdns_browse_t *browse = browse_sync->browse; - mdns_browse_result_sync_t *sync_result = browse_sync->sync_result; - while (sync_result) { - mdns_result_t *result = sync_result->result; - DBG_BROWSE_RESULTS(result, browse_sync->browse); - browse->notifier(result); - if (result->ttl == 0) { - queueDetach(mdns_result_t, browse->result, result); - // Just free current result - result->next = NULL; - mdns_query_results_free(result); - } - sync_result = sync_result->next; - } -} diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index 821c90f99d..09b06dffa7 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -17,50 +17,64 @@ static const char *TAG = "mdns_browser"; static mdns_browse_t *s_browse; -void mdns_browse_send_all(mdns_if_t mdns_if) +/** + * @brief Browse action + */ +static esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse) { - mdns_browse_t *browse = s_browse; - while (browse) { - _mdns_browse_send(browse, mdns_if); - browse = browse->next; + mdns_action_t *action = NULL; + + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; } -} -void mdns_browse_free(void) -{ - while (s_browse) { - mdns_browse_t *b = s_browse; - s_browse = s_browse->next; - _mdns_browse_item_free(b); + action->type = type; + action->data.browse_add.browse = browse; + if (!mdns_action_queue(action)) { + mdns_mem_free(action); + return ESP_ERR_NO_MEM; } + return ESP_OK; } /** - * @brief Mark browse as finished, remove and free it from browse chain + * @brief Free a browse item (Not free the list). */ -void _mdns_browse_finish(mdns_browse_t *browse) +static void _mdns_browse_item_free(mdns_browse_t *browse) { - browse->state = BROWSE_OFF; - mdns_browse_t *b = s_browse; - mdns_browse_t *target_free = NULL; - while (b) { - if (strlen(b->service) == strlen(browse->service) && memcmp(b->service, browse->service, strlen(b->service)) == 0 && - strlen(b->proto) == strlen(browse->proto) && memcmp(b->proto, browse->proto, strlen(b->proto)) == 0) { - target_free = b; - b = b->next; - queueDetach(mdns_browse_t, s_browse, target_free); - _mdns_browse_item_free(target_free); - } else { - b = b->next; + mdns_mem_free(browse->service); + mdns_mem_free(browse->proto); + if (browse->result) { + _mdns_query_results_free(browse->result); + } + mdns_mem_free(browse); +} + +static void _mdns_browse_sync(mdns_browse_sync_t *browse_sync) +{ + mdns_browse_t *browse = browse_sync->browse; + mdns_browse_result_sync_t *sync_result = browse_sync->sync_result; + while (sync_result) { + mdns_result_t *result = sync_result->result; + DBG_BROWSE_RESULTS(result, browse_sync->browse); + browse->notifier(result); + if (result->ttl == 0) { + queueDetach(mdns_result_t, browse->result, result); + // Just free current result + result->next = NULL; + mdns_query_results_free(result); } + sync_result = sync_result->next; } - _mdns_browse_item_free(browse); } /** * @brief Send PTR query packet to all available interfaces for browsing. */ -void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface) +static void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface) { // Using search once for sending the PTR query mdns_search_once_t search = {0}; @@ -78,20 +92,46 @@ void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface) } } +void mdns_browse_send_all(mdns_if_t mdns_if) +{ + mdns_browse_t *browse = s_browse; + while (browse) { + _mdns_browse_send(browse, mdns_if); + browse = browse->next; + } +} + +void mdns_browse_free(void) +{ + while (s_browse) { + mdns_browse_t *b = s_browse; + s_browse = s_browse->next; + _mdns_browse_item_free(b); + } +} + /** - * @brief Free a browse item (Not free the list). + * @brief Mark browse as finished, remove and free it from browse chain */ -void _mdns_browse_item_free(mdns_browse_t *browse) +static void _mdns_browse_finish(mdns_browse_t *browse) { - mdns_mem_free(browse->service); - mdns_mem_free(browse->proto); - if (browse->result) { - _mdns_query_results_free(browse->result); + browse->state = BROWSE_OFF; + mdns_browse_t *b = s_browse; + mdns_browse_t *target_free = NULL; + while (b) { + if (strlen(b->service) == strlen(browse->service) && memcmp(b->service, browse->service, strlen(b->service)) == 0 && + strlen(b->proto) == strlen(browse->proto) && memcmp(b->proto, browse->proto, strlen(b->proto)) == 0) { + target_free = b; + b = b->next; + queueDetach(mdns_browse_t, s_browse, target_free); + _mdns_browse_item_free(target_free); + } else { + b = b->next; + } } - mdns_mem_free(browse); + _mdns_browse_item_free(browse); } - /** * @brief Allocate new browse structure */ @@ -170,7 +210,7 @@ esp_err_t mdns_browse_delete(const char *service, const char *proto) /** * @brief Add new browse to the browse chain */ -void _mdns_browse_add(mdns_browse_t *browse) +static void _mdns_browse_add(mdns_browse_t *browse) { browse->state = BROWSE_RUNNING; mdns_browse_t *queue = s_browse; @@ -229,3 +269,52 @@ mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcp } return b; } + +static void _mdns_sync_browse_result_link_free(mdns_browse_sync_t *browse_sync) +{ + mdns_browse_result_sync_t *current = browse_sync->sync_result; + mdns_browse_result_sync_t *need_free; + while (current) { + need_free = current; + current = current->next; + mdns_mem_free(need_free); + } + mdns_mem_free(browse_sync); +} + +void mdns_browse_action(mdns_action_t *action, mdns_action_subtype_t type) +{ + if (type == ACTION_RUN) { + switch (action->type) { + case ACTION_BROWSE_ADD: + _mdns_browse_add(action->data.browse_add.browse); + break; + case ACTION_BROWSE_SYNC: + _mdns_browse_sync(action->data.browse_sync.browse_sync); + _mdns_sync_browse_result_link_free(action->data.browse_sync.browse_sync); + break; + case ACTION_BROWSE_END: + _mdns_browse_finish(action->data.browse_add.browse); + break; + default: + abort(); + } + return; + } + if (type == ACTION_CLEANUP) { + switch (action->type) { + case ACTION_BROWSE_ADD: + //fallthrough + case ACTION_BROWSE_END: + _mdns_browse_item_free(action->data.browse_add.browse); + break; + case ACTION_BROWSE_SYNC: + _mdns_sync_browse_result_link_free(action->data.browse_sync.browse_sync); + break; + default: + abort(); + } + return; + } + +} diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c index 0d90a0a8bd..d7df488e00 100644 --- a/components/mdns/mdns_netif.c +++ b/components/mdns/mdns_netif.c @@ -18,6 +18,9 @@ #include "mdns_netif.h" #include "mdns_send.h" #include "mdns_responder.h" + +static const char *TAG = "mdns_netif"; + #if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH #include "esp_eth.h" #endif @@ -169,6 +172,27 @@ static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *esp_netif) return MDNS_MAX_INTERFACES; } +static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action) +{ + if (!is_mdns_server() || 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_action_queue(action)) { + mdns_mem_free(action); + } + return ESP_OK; +} + /** * @brief Dispatch interface changes based on system events @@ -395,7 +419,7 @@ esp_err_t mdns_netif_init(void) for (i = 0; i < MDNS_MAX_INTERFACES; i++) { #ifdef CONFIG_LWIP_IPV6 - if (!esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(i), &tmp_addr6) && !_ipv6_address_is_zero(tmp_addr6)) { + if (!esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(i), &tmp_addr6) && !mdns_utils_ipv6_address_is_zero(tmp_addr6)) { _mdns_enable_pcb(i, MDNS_IP_PROTOCOL_V6); } #endif diff --git a/components/mdns/mdns_networking_lwip.c b/components/mdns/mdns_networking_lwip.c index a686727645..957356b58c 100644 --- a/components/mdns/mdns_networking_lwip.c +++ b/components/mdns/mdns_networking_lwip.c @@ -21,6 +21,7 @@ #include "mdns_networking.h" #include "esp_netif_net_stack.h" #include "mdns_mem_caps.h" +#include "mdns_utils.h" /* * MDNS Server Networking @@ -44,6 +45,25 @@ static const char *TAG = "mdns_networking"; static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport); +static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) +{ + mdns_action_t *action = NULL; + + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + + action->type = ACTION_RX_HANDLE; + action->data.rx_handle.packet = packet; + if (!mdns_action_queue(action)) { + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + /** * @brief Low level UDP PCB Initialize */ diff --git a/components/mdns/mdns_networking_socket.c b/components/mdns/mdns_networking_socket.c index 7bcafbb9c3..008caedd6c 100644 --- a/components/mdns/mdns_networking_socket.c +++ b/components/mdns/mdns_networking_socket.c @@ -22,6 +22,7 @@ #include #include "esp_log.h" #include "mdns_mem_caps.h" +#include "mdns_utils.h" #if defined(CONFIG_IDF_TARGET_LINUX) #include @@ -58,6 +59,26 @@ struct pbuf { #define s6_addr32 un.u32_addr #endif // CONFIG_IDF_TARGET_LINUX +static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) +{ + mdns_action_t *action = NULL; + + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + + action->type = ACTION_RX_HANDLE; + action->data.rx_handle.packet = packet; + if (!mdns_action_queue(action)) { + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + + static void __attribute__((constructor)) ctor_networking_socket(void) { for (int i = 0; i < sizeof(s_interfaces) / sizeof(s_interfaces[0]); ++i) { diff --git a/components/mdns/mdns_packet.c b/components/mdns/mdns_packet.c index 79a48c81fd..fe9809dea1 100644 --- a/components/mdns/mdns_packet.c +++ b/components/mdns/mdns_packet.c @@ -20,6 +20,29 @@ static const char *TAG = "mdns_packet"; +/**4 + * @brief Browse sync result action -> TODO: Move to the browser module + */ +static esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync) +{ + mdns_action_t *action = NULL; + + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + + action->type = type; + action->data.browse_sync.browse_sync = browse_sync; + if (!mdns_action_queue(action)) { + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + + /** * @brief Check if parsed name is discovery */ @@ -697,7 +720,7 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) { struct esp_ip6_addr if_ip6; struct esp_ip6_addr other_ip6; - if (_ipv6_address_is_zero(*ip)) { + if (mdns_utils_ipv6_address_is_zero(*ip)) { return 1;//denial! they win } if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(tcpip_if), &if_ip6)) { @@ -1110,8 +1133,9 @@ static mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, co return NULL; } - - +/* + * Received Packet Handling + * */ /** * @brief main packet parser @@ -1780,3 +1804,16 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) mdns_mem_free(browse_result_proto); mdns_mem_free(out_sync_browse); } + +void mdns_receive_action(mdns_action_t *action, mdns_action_subtype_t type) +{ + if (action->type != ACTION_RX_HANDLE) { + abort(); + } + if (type == ACTION_RUN) { + mdns_parse_packet(action->data.rx_handle.packet); + _mdns_packet_free(action->data.rx_handle.packet); + } else if (type == ACTION_CLEANUP) { + _mdns_packet_free(action->data.rx_handle.packet); + } +} diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index 5e2273d803..e53db6ec1f 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -16,6 +16,9 @@ static const char *TAG = "mdns_querier"; static mdns_search_once_t *s_search_once; +static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); +static void _mdns_search_free(mdns_search_once_t *search); + void _mdns_query_results_free(mdns_result_t *results) { mdns_result_t *r; @@ -50,7 +53,7 @@ void _mdns_query_results_free(mdns_result_t *results) /** * @brief Mark search as finished and remove it from search chain */ -void _mdns_search_finish(mdns_search_once_t *search) +static void _mdns_search_finish(mdns_search_once_t *search) { search->state = SEARCH_OFF; queueDetach(mdns_search_once_t, s_search_once, search); @@ -69,6 +72,58 @@ void _mdns_search_add(mdns_search_once_t *search) s_search_once = search; } +/** + * @brief Send search packet to all available interfaces + */ +void _mdns_search_send(mdns_search_once_t *search) +{ + mdns_search_once_t *queue = s_search_once; + bool found = false; + // looking for this search in active searches + while (queue) { + if (queue == search) { + found = true; + break; + } + queue = queue->next; + } + + if (!found) { + // no longer active -> skip sending this search + return; + } + + uint8_t i, j; + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + _mdns_search_send_pcb(search, (mdns_if_t)i, (mdns_ip_protocol_t)j); + } + } +} + +void mdns_query_action(mdns_action_t *action, mdns_action_subtype_t type) +{ + if (type == ACTION_RUN) { + switch (action->type) { + case ACTION_SEARCH_ADD: + _mdns_search_add(action->data.search_add.search); + break; + case ACTION_SEARCH_SEND: + _mdns_search_send(action->data.search_add.search); + break; + case ACTION_SEARCH_END: + _mdns_search_finish(action->data.search_add.search); + break; + default: + abort(); + } + return; + } + if (type == ACTION_CLEANUP) { + _mdns_search_free(action->data.search_add.search); + } +} + /** * @brief Called from timer task to run active searches */ @@ -117,34 +172,7 @@ void mdns_search_free(void) } } -/** - * @brief Send search packet to all available interfaces - */ -void _mdns_search_send(mdns_search_once_t *search) -{ - mdns_search_once_t *queue = s_search_once; - bool found = false; - // looking for this search in active searches - while (queue) { - if (queue == search) { - found = true; - break; - } - queue = queue->next; - } - if (!found) { - // no longer active -> skip sending this search - return; - } - - uint8_t i, j; - for (i = 0; i < MDNS_MAX_INTERFACES; i++) { - for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - _mdns_search_send_pcb(search, (mdns_if_t)i, (mdns_ip_protocol_t)j); - } - } -} /** * @brief Called from parser to finish any searches that have reached maximum results @@ -315,7 +343,7 @@ void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ /** * @brief Free search structure (except the results) */ -void _mdns_search_free(mdns_search_once_t *search) +static void _mdns_search_free(mdns_search_once_t *search) { mdns_mem_free(search->instance); mdns_mem_free(search->service); @@ -507,3 +535,104 @@ esp_err_t mdns_query_txt(const char *instance, const char *service, const char * return mdns_query(instance, service, proto, MDNS_TYPE_TXT, timeout, 1, result); } + +/** + * @brief Queue search action + */ +static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search) +{ + mdns_action_t *action = NULL; + + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + + action->type = type; + action->data.search_add.search = search; + if (!mdns_action_queue(action)) { + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + + +#ifdef CONFIG_LWIP_IPV4 +esp_err_t mdns_query_a(const char *name, uint32_t timeout, esp_ip4_addr_t *addr) +{ + mdns_result_t *result = NULL; + esp_err_t err; + + if (mdns_utils_str_null_or_empty(name)) { + return ESP_ERR_INVALID_ARG; + } + + if (strstr(name, ".local")) { + ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); + } + + err = mdns_query(name, NULL, NULL, MDNS_TYPE_A, timeout, 1, &result); + + if (err) { + return err; + } + + if (!result) { + return ESP_ERR_NOT_FOUND; + } + + mdns_ip_addr_t *a = result->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V4) { + addr->addr = a->addr.u_addr.ip4.addr; + mdns_query_results_free(result); + return ESP_OK; + } + a = a->next; + } + + mdns_query_results_free(result); + return ESP_ERR_NOT_FOUND; +} +#endif /* CONFIG_LWIP_IPV4 */ + +#ifdef CONFIG_LWIP_IPV6 +esp_err_t mdns_query_aaaa(const char *name, uint32_t timeout, esp_ip6_addr_t *addr) +{ + mdns_result_t *result = NULL; + esp_err_t err; + + if (mdns_utils_str_null_or_empty(name)) { + return ESP_ERR_INVALID_ARG; + } + + if (strstr(name, ".local")) { + ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); + } + + err = mdns_query(name, NULL, NULL, MDNS_TYPE_AAAA, timeout, 1, &result); + + if (err) { + return err; + } + + if (!result) { + return ESP_ERR_NOT_FOUND; + } + + mdns_ip_addr_t *a = result->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { + memcpy(addr->addr, a->addr.u_addr.ip6.addr, 16); + mdns_query_results_free(result); + return ESP_OK; + } + a = a->next; + } + + mdns_query_results_free(result); + return ESP_ERR_NOT_FOUND; +} +#endif /* CONFIG_LWIP_IPV6 */ diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index 802ac99ac9..0485af98b8 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -24,6 +24,172 @@ static mdns_tx_packet_t *s_tx_queue_head; #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) #endif + +/** + * @brief appends byte in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 1 on success + */ +static inline uint8_t _mdns_append_u8(uint8_t *packet, uint16_t *index, uint8_t value) +{ + if (*index >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + packet[*index] = value; + *index += 1; + return 1; +} + +/** + * @brief appends uint16_t in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 2 on success + */ +uint8_t _mdns_append_u16(uint8_t *packet, uint16_t *index, uint16_t value) +{ + if ((*index + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, (value >> 8) & 0xFF); + _mdns_append_u8(packet, index, value & 0xFF); + return 2; +} + +/** + * @brief appends uint32_t in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 4 on success + */ +static inline uint8_t _mdns_append_u32(uint8_t *packet, uint16_t *index, uint32_t value) +{ + if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, (value >> 24) & 0xFF); + _mdns_append_u8(packet, index, (value >> 16) & 0xFF); + _mdns_append_u8(packet, index, (value >> 8) & 0xFF); + _mdns_append_u8(packet, index, value & 0xFF); + return 4; +} + +/** + * @brief appends answer type, class, ttl and data length to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param type answer type + * @param ttl answer ttl + * + * @return length of added data: 0 on error or 10 on success + */ +static inline uint8_t _mdns_append_type(uint8_t *packet, uint16_t *index, uint8_t type, bool flush, uint32_t ttl) +{ + if ((*index + 10) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + uint16_t mdns_class = MDNS_CLASS_IN; + if (flush) { + mdns_class = MDNS_CLASS_IN_FLUSH_CACHE; + } + if (type == MDNS_ANSWER_PTR) { + _mdns_append_u16(packet, index, MDNS_TYPE_PTR); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_TXT) { + _mdns_append_u16(packet, index, MDNS_TYPE_TXT); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_SRV) { + _mdns_append_u16(packet, index, MDNS_TYPE_SRV); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_A) { + _mdns_append_u16(packet, index, MDNS_TYPE_A); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_AAAA) { + _mdns_append_u16(packet, index, MDNS_TYPE_AAAA); + _mdns_append_u16(packet, index, mdns_class); + } else { + return 0; + } + _mdns_append_u32(packet, index, ttl); + _mdns_append_u16(packet, index, 0); + return 10; +} + +static inline uint8_t _mdns_append_string_with_len(uint8_t *packet, uint16_t *index, const char *string, uint8_t len) +{ + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, string, len); + *index += len; + return len + 1; +} + +/** + * @brief appends single string to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param string the string to append + * + * @return length of added data: 0 on error or length of the string + 1 on success + */ +static inline uint8_t _mdns_append_string(uint8_t *packet, uint16_t *index, const char *string) +{ + uint8_t len = strlen(string); + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, string, len); + *index += len; + return len + 1; +} + +/** + * @brief appends one TXT record ("key=value" or "key") + * + * @param packet MDNS packet + * @param index offset in the packet + * @param txt one txt record + * + * @return length of added data: length of the added txt value + 1 on success + * 0 if data won't fit the packet + * -1 if invalid TXT entry + */ +int append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt) +{ + if (txt == NULL || txt->key == NULL) { + return -1; + } + size_t key_len = strlen(txt->key); + size_t len = key_len + txt->value_len + (txt->value ? 1 : 0); + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, txt->key, key_len); + if (txt->value) { + packet[*index + key_len] = '='; + memcpy(packet + *index + key_len + 1, txt->value, txt->value_len); + } + *index += len; + return len + 1; +} + + static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char *strings[], uint8_t count, size_t packet_len); /** @@ -1181,7 +1347,7 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an count = esp_netif_get_all_ip6(_mdns_get_esp_netif(tcpip_if), if_ip6s); assert(count <= NETIF_IPV6_MAX_NUMS); for (int i = 0; i < count; i++) { - if (_ipv6_address_is_zero(if_ip6s[i])) { + if (mdns_utils_ipv6_address_is_zero(if_ip6s[i])) { return 0; } if (_mdns_append_aaaa_record(packet, index, mdns_utils_get_global_hostname(), (uint8_t *)if_ip6s[i].addr, @@ -1595,6 +1761,48 @@ mdns_tx_packet_t *_mdns_get_next_tx_packet(void) return s_tx_queue_head; } +/** + * @brief Called from timer task to run mDNS responder + * + * periodically checks first unqueued packet (from tx head). + * if it is scheduled to be transmitted, then pushes the packet to action queue to be handled. + * + */ +void mdns_send_packets(void) +{ + mdns_service_lock(); + mdns_tx_packet_t *p = s_tx_queue_head; + mdns_action_t *action = NULL; + + // find first unqueued packet + while (p && p->queued) { + p = p->next; + } + if (!p) { + mdns_service_unlock(); + return; + } + while (p && (int32_t)(p->send_at - (xTaskGetTickCount() * portTICK_PERIOD_MS)) < 0) { + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (action) { + action->type = ACTION_TX_HANDLE; + action->data.tx_handle.packet = p; + p->queued = true; + if (!mdns_action_queue(action)) { + mdns_mem_free(action); + p->queued = false; + } + } else { + HOOK_MALLOC_FAILED; + break; + } + //Find the next unqued packet + p = p->next; + } + mdns_service_unlock(); +} + + /** * @brief Remove and free service answer from answer list (destination) @@ -1682,7 +1890,7 @@ static void _mdns_tx_handle_packet(mdns_tx_packet_t *p) mdns_responder_process_tx_packet(p); } -void mdns_send_handle_tx_packet(mdns_tx_packet_t *packet) +static void mdns_send_handle_tx_packet(mdns_tx_packet_t *packet) { mdns_tx_packet_t *p = s_tx_queue_head; // packet to be handled should be at tx head, but must be consistent with the one pushed to action queue @@ -1723,3 +1931,15 @@ void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_s d = d->next; } } + +void mdns_send_action(mdns_action_t *action, mdns_action_subtype_t type) +{ + if (action->type != ACTION_TX_HANDLE) { + abort(); + } + if (type == ACTION_RUN) { + mdns_send_handle_tx_packet(action->data.tx_handle.packet); + } else if (type == ACTION_CLEANUP) { + _mdns_free_tx_packet(action->data.tx_handle.packet); + } +} diff --git a/components/mdns/mdns_utils.c b/components/mdns/mdns_utils.c index f128b6f024..8aebad3160 100644 --- a/components/mdns/mdns_utils.c +++ b/components/mdns/mdns_utils.c @@ -146,7 +146,6 @@ bool _mdns_service_match(const mdns_service_t *srv, const char *service, const c (mdns_utils_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); } - /** * @brief finds service from given service type * @param server the server @@ -297,3 +296,20 @@ void free_address_list(mdns_ip_addr_t *address_list) address_list = next; } } + +#ifdef CONFIG_LWIP_IPV6 +/** + * @brief Check if IPv6 address is NULL + */ +bool mdns_utils_ipv6_address_is_zero(esp_ip6_addr_t ip6) +{ + uint8_t i; + uint8_t *data = (uint8_t *)ip6.addr; + for (i = 0; i < _MDNS_SIZEOF_IP6_ADDR; i++) { + if (data[i]) { + return false; + } + } + return true; +} +#endif /* CONFIG_LWIP_IPV6 */ diff --git a/components/mdns/private_include/mdns_browse.h b/components/mdns/private_include/mdns_browse.h index 37e901e275..936298344e 100644 --- a/components/mdns/private_include/mdns_browse.h +++ b/components/mdns/private_include/mdns_browse.h @@ -13,19 +13,16 @@ extern "C" { #endif //void _mdns_browse_item_free(mdns_browse_t *browse); -esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse); -esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync); -void _mdns_browse_sync(mdns_browse_sync_t *browse_sync); -void _mdns_browse_finish(mdns_browse_t *browse); -void _mdns_browse_add(mdns_browse_t *browse); -void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface); +//void _mdns_browse_sync(mdns_browse_sync_t *browse_sync); +//void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface); void mdns_browse_free(void); -void _mdns_browse_item_free(mdns_browse_t *browse); mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); void mdns_browse_send_all(mdns_if_t mdns_if); +void mdns_browse_action(mdns_action_t *action, mdns_action_subtype_t type); + #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h index 83cbe90cc9..a00266ef5c 100644 --- a/components/mdns/private_include/mdns_networking.h +++ b/components/mdns/private_include/mdns_networking.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,12 +13,9 @@ #include "mdns.h" #include "mdns_private.h" - /** - * @brief Queue RX packet action + * @brief Check if the netif on the selected interfacce and protocol is ready */ -esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet); - bool mdns_is_netif_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); /** diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index e0c6797bdf..436afe49ea 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -191,6 +191,10 @@ typedef enum { ACTION_MAX } mdns_action_type_t; +typedef enum { + ACTION_RUN, + ACTION_CLEANUP, +} mdns_action_subtype_t; typedef struct { uint16_t id; diff --git a/components/mdns/private_include/mdns_querier.h b/components/mdns/private_include/mdns_querier.h index 660642a813..deae8ab757 100644 --- a/components/mdns/private_include/mdns_querier.h +++ b/components/mdns/private_include/mdns_querier.h @@ -12,16 +12,16 @@ extern "C" { #endif -void _mdns_query_results_free(mdns_result_t *results); -void _mdns_search_add(mdns_search_once_t *search); -void _mdns_search_finish(mdns_search_once_t *search); void _mdns_search_run(void); void mdns_search_free(void); +void _mdns_query_results_free(mdns_result_t *results); void _mdns_search_finish_done(void); -void _mdns_search_send(mdns_search_once_t *search); +//void _mdns_search_send(mdns_search_once_t *search); mdns_search_once_t *_mdns_search_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -void _mdns_search_free(mdns_search_once_t *search); +//void _mdns_search_free(mdns_search_once_t *search); + +void mdns_query_action(mdns_action_t *action, mdns_action_subtype_t type); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_receive.h b/components/mdns/private_include/mdns_receive.h new file mode 100644 index 0000000000..04e79d90f2 --- /dev/null +++ b/components/mdns/private_include/mdns_receive.h @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "mdns_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void mdns_receive_action(mdns_action_t *action, mdns_action_subtype_t type); + +#ifdef __cplusplus +} +#endif diff --git a/components/mdns/private_include/mdns_send.h b/components/mdns/private_include/mdns_send.h index 8dea10a7c3..89d88a9f2d 100644 --- a/components/mdns/private_include/mdns_send.h +++ b/components/mdns/private_include/mdns_send.h @@ -29,12 +29,12 @@ bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_sr void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); void _mdns_clear_tx_queue_head(void); void _mdns_remove_scheduled_service_packets(mdns_service_t *service); -void mdns_send_handle_tx_packet(mdns_tx_packet_t *packet); mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -mdns_tx_packet_t *_mdns_get_next_tx_packet(void); void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service); void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service); mdns_tx_packet_t *_mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +void mdns_send_packets(void); +void mdns_send_action(mdns_action_t *action, mdns_action_subtype_t type); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_utils.h b/components/mdns/private_include/mdns_utils.h index bc588ce52b..acc9a4a5ef 100644 --- a/components/mdns/private_include/mdns_utils.h +++ b/components/mdns/private_include/mdns_utils.h @@ -72,8 +72,7 @@ void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new void _mdns_restart_all_pcbs(void); void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip); -bool _ipv6_address_is_zero(esp_ip6_addr_t ip6); -void _mdns_search_finish(mdns_search_once_t *search); +bool mdns_utils_ipv6_address_is_zero(esp_ip6_addr_t ip6); void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet); @@ -96,183 +95,16 @@ const char *_mdns_get_service_instance_name(const mdns_service_t *service); esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r); mdns_ip_addr_t *copy_address_list(const mdns_ip_addr_t *address_list); void free_address_list(mdns_ip_addr_t *address_list); - +int append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt); +uint8_t _mdns_append_u16(uint8_t *packet, uint16_t *index, uint16_t value); //--------------------------------------------- -/** - * @brief appends byte in a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param value the value to set - * - * @return length of added data: 0 on error or 1 on success - */ -static inline uint8_t _mdns_append_u8(uint8_t *packet, uint16_t *index, uint8_t value) -{ - if (*index >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - packet[*index] = value; - *index += 1; - return 1; -} - -/** - * @brief appends uint16_t in a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param value the value to set - * - * @return length of added data: 0 on error or 2 on success - */ -static inline uint8_t _mdns_append_u16(uint8_t *packet, uint16_t *index, uint16_t value) -{ - if ((*index + 1) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, (value >> 8) & 0xFF); - _mdns_append_u8(packet, index, value & 0xFF); - return 2; -} - -/** - * @brief appends uint32_t in a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param value the value to set - * - * @return length of added data: 0 on error or 4 on success - */ -static inline uint8_t _mdns_append_u32(uint8_t *packet, uint16_t *index, uint32_t value) -{ - if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, (value >> 24) & 0xFF); - _mdns_append_u8(packet, index, (value >> 16) & 0xFF); - _mdns_append_u8(packet, index, (value >> 8) & 0xFF); - _mdns_append_u8(packet, index, value & 0xFF); - return 4; -} - -/** - * @brief appends answer type, class, ttl and data length to a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param type answer type - * @param ttl answer ttl - * - * @return length of added data: 0 on error or 10 on success - */ -static inline uint8_t _mdns_append_type(uint8_t *packet, uint16_t *index, uint8_t type, bool flush, uint32_t ttl) -{ - if ((*index + 10) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - uint16_t mdns_class = MDNS_CLASS_IN; - if (flush) { - mdns_class = MDNS_CLASS_IN_FLUSH_CACHE; - } - if (type == MDNS_ANSWER_PTR) { - _mdns_append_u16(packet, index, MDNS_TYPE_PTR); - _mdns_append_u16(packet, index, mdns_class); - } else if (type == MDNS_ANSWER_TXT) { - _mdns_append_u16(packet, index, MDNS_TYPE_TXT); - _mdns_append_u16(packet, index, mdns_class); - } else if (type == MDNS_ANSWER_SRV) { - _mdns_append_u16(packet, index, MDNS_TYPE_SRV); - _mdns_append_u16(packet, index, mdns_class); - } else if (type == MDNS_ANSWER_A) { - _mdns_append_u16(packet, index, MDNS_TYPE_A); - _mdns_append_u16(packet, index, mdns_class); - } else if (type == MDNS_ANSWER_AAAA) { - _mdns_append_u16(packet, index, MDNS_TYPE_AAAA); - _mdns_append_u16(packet, index, mdns_class); - } else { - return 0; - } - _mdns_append_u32(packet, index, ttl); - _mdns_append_u16(packet, index, 0); - return 10; -} - -static inline uint8_t _mdns_append_string_with_len(uint8_t *packet, uint16_t *index, const char *string, uint8_t len) -{ - if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, len); - memcpy(packet + *index, string, len); - *index += len; - return len + 1; -} - -/** - * @brief appends single string to a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param string the string to append - * - * @return length of added data: 0 on error or length of the string + 1 on success - */ -static inline uint8_t _mdns_append_string(uint8_t *packet, uint16_t *index, const char *string) -{ - uint8_t len = strlen(string); - if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, len); - memcpy(packet + *index, string, len); - *index += len; - return len + 1; -} - -/** - * @brief appends one TXT record ("key=value" or "key") - * - * @param packet MDNS packet - * @param index offset in the packet - * @param txt one txt record - * - * @return length of added data: length of the added txt value + 1 on success - * 0 if data won't fit the packet - * -1 if invalid TXT entry - */ -static inline int append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt) -{ - if (txt == NULL || txt->key == NULL) { - return -1; - } - size_t key_len = strlen(txt->key); - size_t len = key_len + txt->value_len + (txt->value ? 1 : 0); - if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, len); - memcpy(packet + *index, txt->key, key_len); - if (txt->value) { - packet[*index + key_len] = '='; - memcpy(packet + *index + key_len + 1, txt->value, txt->value_len); - } - *index += len; - return len + 1; -} /// //mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if); //void _mdns_dup_interface(mdns_if_t tcpip_if); -esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync); - -esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); - - void mdns_service_lock(void); void mdns_service_unlock(void); -esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); +bool mdns_action_queue(mdns_action_t *action); diff --git a/components/mdns/tests/test_afl_fuzz_host/mdns_di.h b/components/mdns/tests/test_afl_fuzz_host/mdns_di.h index 11ecd3466d..ee6987c506 100644 --- a/components/mdns/tests/test_afl_fuzz_host/mdns_di.h +++ b/components/mdns/tests/test_afl_fuzz_host/mdns_di.h @@ -13,7 +13,7 @@ void (*mdns_test_static_execute_action)(mdns_action_t *) = NULL; mdns_srv_item_t *(*mdns_test_static_mdns_get_service_item)(const char *service, const char *proto, const char *hostname) = NULL; -esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t *search) = NULL; +// esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t *search) = NULL; static void _mdns_execute_action(mdns_action_t *action); diff --git a/components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h b/components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h index 7b8badd8a1..23908fe40f 100644 --- a/components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h +++ b/components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h @@ -11,16 +11,23 @@ #include "mdns.h" #include "mdns_private.h" +esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t *search) = NULL; +void (*mdns_test_static_search_free)(mdns_search_once_t *search) = NULL; + mdns_search_once_t *(*mdns_test_static_search_init)(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier) = NULL; static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier); +static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); +static void _mdns_search_free(mdns_search_once_t *search); void mdns_querier_test_init_di(void) { mdns_test_static_search_init = _mdns_search_init; + mdns_test_static_send_search_action = _mdns_send_search_action; + mdns_test_static_search_free = _mdns_search_free; } @@ -28,3 +35,13 @@ mdns_search_once_t *mdns_test_search_init(const char *name, const char *service, { return mdns_test_static_search_init(name, service, proto, type, timeout, type != MDNS_TYPE_PTR, max_results, NULL); } + +void mdns_test_search_free(mdns_search_once_t *search) +{ + return mdns_test_static_search_free(search); +} + +esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t *search) +{ + return mdns_test_static_send_search_action(type, search); +} diff --git a/components/mdns/tests/test_afl_fuzz_host/test.c b/components/mdns/tests/test_afl_fuzz_host/test.c index 61336da0e2..f649f562b6 100644 --- a/components/mdns/tests/test_afl_fuzz_host/test.c +++ b/components/mdns/tests/test_afl_fuzz_host/test.c @@ -26,7 +26,11 @@ mdns_search_once_t *search = NULL; // Dependency injected test functions void mdns_test_execute_action(void *action); mdns_search_once_t *mdns_test_search_init(const char *name, const char *service, const char *proto, uint16_t type, uint32_t timeout, uint8_t max_results); +esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); +void mdns_test_search_free(mdns_search_once_t *search); + void mdns_test_init_di(void); +void mdns_querier_test_init_di(void); extern mdns_server_t *_mdns_server; // @@ -115,8 +119,8 @@ static mdns_result_t *mdns_test_query(const char *name, const char *service, con abort(); } - if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { - _mdns_search_free(search); + if (mdns_test_send_search_action(ACTION_SEARCH_ADD, search)) { + mdns_test_search_free(search); abort(); } @@ -128,7 +132,7 @@ static mdns_result_t *mdns_test_query(const char *name, const char *service, con static void mdns_test_query_free(void) { - _mdns_search_free(search); + mdns_test_search_free(search); } // @@ -160,6 +164,7 @@ int main(int argc, char **argv) // Init depencency injected methods mdns_test_init_di(); + mdns_querier_test_init_di(); if (mdns_init()) { abort(); From 62bd74791445e26c398c2585f0e8747c8aa73a3f Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 11 Mar 2025 16:07:30 +0100 Subject: [PATCH 07/27] fix(mdns): Minor cleanup of packet parser --- components/mdns/CMakeLists.txt | 2 +- components/mdns/mdns.c | 2 +- components/mdns/mdns_browser.c | 310 +++++++++- components/mdns/mdns_netif.c | 2 +- components/mdns/mdns_querier.c | 241 ++++++++ .../mdns/{mdns_packet.c => mdns_receive.c} | 542 +----------------- components/mdns/mdns_utils.c | 28 +- components/mdns/private_include/mdns_browse.h | 28 - .../mdns/private_include/mdns_browser.h | 33 ++ .../mdns/private_include/mdns_querier.h | 14 +- components/mdns/private_include/mdns_utils.h | 2 +- .../mdns/tests/test_afl_fuzz_host/Makefile | 2 +- 12 files changed, 602 insertions(+), 604 deletions(-) rename components/mdns/{mdns_packet.c => mdns_receive.c} (73%) delete mode 100644 components/mdns/private_include/mdns_browse.h create mode 100644 components/mdns/private_include/mdns_browser.h diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index a6273c972a..3ad426e9b8 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -12,7 +12,7 @@ endif() set(MDNS_MEMORY "mdns_mem_caps.c") -set(MDNS_CORE "mdns.c" "mdns_packet.c" "mdns_utils.c" "mdns_debug.c" "mdns_browser.c" "mdns_send.c" "mdns_netif.c" +set(MDNS_CORE "mdns.c" "mdns_receive.c" "mdns_utils.c" "mdns_debug.c" "mdns_browser.c" "mdns_send.c" "mdns_netif.c" "mdns_querier.c" "mdns_responder.c") #set(MDNS_CORE "mdns.c" ) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 8784034b7d..7703fb6bad 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -18,7 +18,7 @@ #include "mdns_mem_caps.h" #include "mdns_utils.h" #include "mdns_debug.h" -#include "mdns_browse.h" +#include "mdns_browser.h" #include "mdns_netif.h" #include "mdns_send.h" #include "mdns_receive.h" diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index 09b06dffa7..fd7535af29 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -5,7 +5,7 @@ */ #include #include "mdns_private.h" -#include "mdns_browse.h" +#include "mdns_browser.h" #include "mdns_send.h" #include "mdns_mem_caps.h" #include "mdns_debug.h" @@ -318,3 +318,311 @@ void mdns_browse_action(mdns_action_t *action, mdns_action_subtype_t type) } } + +/** + * @brief Add result to browse, only add when the result is a new one. + */ +static esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r) +{ + mdns_browse_result_sync_t *sync_r = sync_browse->sync_result; + while (sync_r) { + if (sync_r->result == r) { + break; + } + sync_r = sync_r->next; + } + if (!sync_r) { + // Do not find, need to add the result to the list + mdns_browse_result_sync_t *new = (mdns_browse_result_sync_t *)mdns_mem_malloc(sizeof(mdns_browse_result_sync_t)); + + if (!new) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + new->result = r; + new->next = sync_browse->sync_result; + sync_browse->sync_result = new; + } + return ESP_OK; +} + +/** + * @brief Called from parser to add A/AAAA data to search result + */ +void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +{ + if (out_sync_browse->browse == NULL) { + return; + } else { + if (out_sync_browse->browse != browse) { + return; + } + } + mdns_result_t *r = NULL; + mdns_ip_addr_t *r_a = NULL; + if (browse) { + r = browse->result; + while (r) { + if (r->ip_protocol == ip_protocol) { + // Find the target result in browse result. + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + r_a = r->addr; + // Check if the address has already added in result. + while (r_a) { +#ifdef CONFIG_LWIP_IPV4 + if (r_a->addr.type == ip->type && r_a->addr.type == ESP_IPADDR_TYPE_V4 && r_a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { + break; + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (r_a->addr.type == ip->type && r_a->addr.type == ESP_IPADDR_TYPE_V6 && !memcmp(r_a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { + break; + } +#endif + r_a = r_a->next; + } + if (!r_a) { + // The current IP is a new one, add it to the link list. + mdns_ip_addr_t *a = NULL; + a = _mdns_result_addr_create_ip(ip); + if (!a) { + return; + } + a->next = r->addr; + r->addr = a; + if (r->ttl != ttl) { + if (r->ttl == 0) { + r->ttl = ttl; + } else { + _mdns_result_update_ttl(r, ttl); + } + } + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + break; + } + } + } + r = r->next; + } + } +} + +static bool is_txt_item_in_list(mdns_txt_item_t txt, uint8_t txt_value_len, mdns_txt_item_t *txt_list, uint8_t *txt_value_len_list, size_t txt_count) +{ + for (size_t i = 0; i < txt_count; i++) { + if (strcmp(txt.key, txt_list[i].key) == 0) { + if (txt_value_len == txt_value_len_list[i] && memcmp(txt.value, txt_list[i].value, txt_value_len) == 0) { + return true; + } else { + // The key value is unique, so there is no need to continue searching. + return false; + } + } + } + return false; +} + +/** + * @brief Called from parser to add TXT data to search result + */ +void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, + mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +{ + if (out_sync_browse->browse == NULL) { + return; + } else { + if (out_sync_browse->browse != browse) { + return; + } + } + mdns_result_t *r = browse->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && + !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && + !mdns_utils_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && + !mdns_utils_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { + bool should_update = false; + if (r->txt) { + // Check if txt changed + if (txt_count != r->txt_count) { + should_update = true; + } else { + for (size_t txt_index = 0; txt_index < txt_count; txt_index++) { + if (!is_txt_item_in_list(txt[txt_index], txt_value_len[txt_index], r->txt, r->txt_value_len, r->txt_count)) { + should_update = true; + break; + } + } + } + // If the result has a previous txt entry, we delete it and re-add. + for (size_t i = 0; i < r->txt_count; i++) { + mdns_mem_free((char *)(r->txt[i].key)); + mdns_mem_free((char *)(r->txt[i].value)); + } + mdns_mem_free(r->txt); + mdns_mem_free(r->txt_value_len); + } + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + if (r->ttl != ttl) { + uint32_t previous_ttl = r->ttl; + if (r->ttl == 0) { + r->ttl = ttl; + } else { + _mdns_result_update_ttl(r, ttl); + } + if (previous_ttl != r->ttl) { + should_update = true; + } + } + if (should_update) { + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + } + return; + } + r = r->next; + } + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + goto free_txt; + } + memset(r, 0, sizeof(mdns_result_t)); + r->instance_name = mdns_mem_strdup(instance); + r->service_type = mdns_mem_strdup(service); + r->proto = mdns_mem_strdup(proto); + if (!r->instance_name || !r->service_type || !r->proto) { + mdns_mem_free(r->instance_name); + mdns_mem_free(r->service_type); + mdns_mem_free(r->proto); + mdns_mem_free(r); + return; + } + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = browse->result; + browse->result = r; + _mdns_add_browse_result(out_sync_browse, r); + return; + +free_txt: + for (size_t i = 0; i < txt_count; i++) { + mdns_mem_free((char *)(txt[i].key)); + mdns_mem_free((char *)(txt[i].value)); + } + mdns_mem_free(txt); + mdns_mem_free(txt_value_len); + return; +} + +static esp_err_t _mdns_copy_address_in_previous_result(mdns_result_t *result_list, mdns_result_t *r) +{ + while (result_list) { + if (!mdns_utils_str_null_or_empty(result_list->hostname) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(result_list->hostname, r->hostname) && + result_list->ip_protocol == r->ip_protocol && result_list->addr && !r->addr) { + // If there is a same hostname in previous result, we need to copy the address here. + r->addr = copy_address_list(result_list->addr); + if (!r->addr) { + return ESP_ERR_NO_MEM; + } + break; + } else { + result_list = result_list->next; + } + } + return ESP_OK; +} + +/** + * @brief Called from parser to add SRV data to search result + */ +void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, + uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +{ + if (out_sync_browse->browse == NULL) { + return; + } else { + if (out_sync_browse->browse != browse) { + return; + } + } + mdns_result_t *r = browse->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && + !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && + !mdns_utils_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && + !mdns_utils_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { + if (mdns_utils_str_null_or_empty(r->hostname) || strcasecmp(hostname, r->hostname)) { + r->hostname = mdns_mem_strdup(hostname); + r->port = port; + if (!r->hostname) { + HOOK_MALLOC_FAILED; + return; + } + if (!r->addr) { + esp_err_t err = _mdns_copy_address_in_previous_result(browse->result, r); + if (err == ESP_ERR_NO_MEM) { + return; + } + } + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + } + if (r->ttl != ttl) { + uint32_t previous_ttl = r->ttl; + if (r->ttl == 0) { + r->ttl = ttl; + } else { + _mdns_result_update_ttl(r, ttl); + } + if (previous_ttl != r->ttl) { + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + } + } + return; + } + r = r->next; + } + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->hostname = mdns_mem_strdup(hostname); + r->instance_name = mdns_mem_strdup(instance); + r->service_type = mdns_mem_strdup(service); + r->proto = mdns_mem_strdup(proto); + if (!r->hostname || !r->instance_name || !r->service_type || !r->proto) { + HOOK_MALLOC_FAILED; + mdns_mem_free(r->hostname); + mdns_mem_free(r->instance_name); + mdns_mem_free(r->service_type); + mdns_mem_free(r->proto); + mdns_mem_free(r); + return; + } + r->port = port; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = browse->result; + browse->result = r; + _mdns_add_browse_result(out_sync_browse, r); + return; +} diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c index d7df488e00..c22d0ef725 100644 --- a/components/mdns/mdns_netif.c +++ b/components/mdns/mdns_netif.c @@ -14,7 +14,7 @@ #include "mdns_mem_caps.h" #include "mdns_utils.h" #include "mdns_debug.h" -#include "mdns_browse.h" +#include "mdns_browser.h" #include "mdns_netif.h" #include "mdns_send.h" #include "mdns_responder.h" diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index e53db6ec1f..90798d6c46 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -636,3 +636,244 @@ esp_err_t mdns_query_aaaa(const char *name, uint32_t timeout, esp_ip6_addr_t *ad return ESP_ERR_NOT_FOUND; } #endif /* CONFIG_LWIP_IPV6 */ + +/** + * @brief Create linked IP (copy) from parsed one + */ +mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip) +{ + mdns_ip_addr_t *a = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); + if (!a) { + HOOK_MALLOC_FAILED; + return NULL; + } + memset(a, 0, sizeof(mdns_ip_addr_t)); + a->addr.type = ip->type; + if (ip->type == ESP_IPADDR_TYPE_V6) { + memcpy(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16); + } else { + a->addr.u_addr.ip4.addr = ip->u_addr.ip4.addr; + } + return a; +} + +/** + * @brief Called from parser to add TXT data to search result + */ +void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, + size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl) +{ + mdns_result_t *r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { + if (r->txt) { + goto free_txt; + } + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + _mdns_result_update_ttl(r, ttl); + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + goto free_txt; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = search->result; + search->result = r; + search->num_results++; + } + return; + +free_txt: + for (size_t i = 0; i < txt_count; i++) { + mdns_mem_free((char *)(txt[i].key)); + mdns_mem_free((char *)(txt[i].value)); + } + mdns_mem_free(txt); + mdns_mem_free(txt_value_len); +} + +/** + * @brief Chain new IP to search result + */ +static void _mdns_result_add_ip(mdns_result_t *r, esp_ip_addr_t *ip) +{ + mdns_ip_addr_t *a = r->addr; + while (a) { + if (a->addr.type == ip->type) { +#ifdef CONFIG_LWIP_IPV4 + if (a->addr.type == ESP_IPADDR_TYPE_V4 && a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { + return; + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (a->addr.type == ESP_IPADDR_TYPE_V6 && !memcmp(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { + return; + } +#endif + } + a = a->next; + } + a = _mdns_result_addr_create_ip(ip); + if (!a) { + return; + } + a->next = r->addr; + r->addr = a; +} + +/** + * @brief Called from parser to add A/AAAA data to search result + */ +void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) +{ + mdns_result_t *r = NULL; + mdns_ip_addr_t *a = NULL; + + if ((search->type == MDNS_TYPE_A && ip->type == ESP_IPADDR_TYPE_V4) + || (search->type == MDNS_TYPE_AAAA && ip->type == ESP_IPADDR_TYPE_V6) + || search->type == MDNS_TYPE_ANY) { + r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { + _mdns_result_add_ip(r, ip); + _mdns_result_update_ttl(r, ttl); + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return; + } + + memset(r, 0, sizeof(mdns_result_t)); + + a = _mdns_result_addr_create_ip(ip); + if (!a) { + mdns_mem_free(r); + return; + } + a->next = r->addr; + r->hostname = mdns_mem_strdup(hostname); + r->addr = a; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->next = search->result; + r->ttl = ttl; + search->result = r; + search->num_results++; + } + } else if (search->type == MDNS_TYPE_PTR || search->type == MDNS_TYPE_SRV) { + r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + _mdns_result_add_ip(r, ip); + _mdns_result_update_ttl(r, ttl); + break; + } + r = r->next; + } + } +} + +/** + * @brief Called from parser to add SRV data to search result + */ +void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) +{ + mdns_result_t *r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + _mdns_result_update_ttl(r, ttl); + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->hostname = mdns_mem_strdup(hostname); + if (!r->hostname) { + mdns_mem_free(r); + return; + } + if (search->instance) { + r->instance_name = mdns_mem_strdup(search->instance); + } + r->service_type = mdns_mem_strdup(search->service); + r->proto = mdns_mem_strdup(search->proto); + r->port = port; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = search->result; + search->result = r; + search->num_results++; + } +} + +/** + * @brief Called from parser to add PTR data to search result + */ +mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, + const char *service_type, const char *proto, mdns_if_t tcpip_if, + mdns_ip_protocol_t ip_protocol, uint32_t ttl) +{ + mdns_result_t *r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { + _mdns_result_update_ttl(r, ttl); + return r; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return NULL; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->instance_name = mdns_mem_strdup(instance); + r->service_type = mdns_mem_strdup(service_type); + r->proto = mdns_mem_strdup(proto); + if (!r->instance_name) { + mdns_mem_free(r); + return NULL; + } + + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = search->result; + search->result = r; + search->num_results++; + return r; + } + return NULL; +} diff --git a/components/mdns/mdns_packet.c b/components/mdns/mdns_receive.c similarity index 73% rename from components/mdns/mdns_packet.c rename to components/mdns/mdns_receive.c index fe9809dea1..b403e421be 100644 --- a/components/mdns/mdns_packet.c +++ b/components/mdns/mdns_receive.c @@ -14,7 +14,7 @@ #include "mdns_debug.h" #include "mdns_netif.h" #include "mdns_send.h" -#include "mdns_browse.h" +#include "mdns_browser.h" #include "mdns_querier.h" #include "mdns_responder.h" @@ -42,7 +42,6 @@ static esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_s return ESP_OK; } - /** * @brief Check if parsed name is discovery */ @@ -239,59 +238,6 @@ static int _mdns_txt_item_name_get_len(const uint8_t *data, size_t len) return len; } - - -/** - * @brief Called from parser to add TXT data to search result - */ -static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, - size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl) -{ - mdns_result_t *r = search->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { - if (r->txt) { - goto free_txt; - } - r->txt = txt; - r->txt_value_len = txt_value_len; - r->txt_count = txt_count; - _mdns_result_update_ttl(r, ttl); - return; - } - r = r->next; - } - if (!search->max_results || search->num_results < search->max_results) { - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; - goto free_txt; - } - - memset(r, 0, sizeof(mdns_result_t)); - r->txt = txt; - r->txt_value_len = txt_value_len; - r->txt_count = txt_count; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->ttl = ttl; - r->next = search->result; - search->result = r; - search->num_results++; - } - return; - -free_txt: - for (size_t i = 0; i < txt_count; i++) { - mdns_mem_free((char *)(txt[i].key)); - mdns_mem_free((char *)(txt[i].value)); - } - mdns_mem_free(txt); - mdns_mem_free(txt_value_len); -} - - /** * @brief Create TXT result array from parsed TXT data */ @@ -387,295 +333,6 @@ handle_error : mdns_mem_free(txt); } -static bool is_txt_item_in_list(mdns_txt_item_t txt, uint8_t txt_value_len, mdns_txt_item_t *txt_list, uint8_t *txt_value_len_list, size_t txt_count) -{ - for (size_t i = 0; i < txt_count; i++) { - if (strcmp(txt.key, txt_list[i].key) == 0) { - if (txt_value_len == txt_value_len_list[i] && memcmp(txt.value, txt_list[i].value, txt_value_len) == 0) { - return true; - } else { - // The key value is unique, so there is no need to continue searching. - return false; - } - } - } - return false; -} - -/** - * @brief Create linked IP (copy) from parsed one - */ -static mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip) -{ - mdns_ip_addr_t *a = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); - if (!a) { - HOOK_MALLOC_FAILED; - return NULL; - } - memset(a, 0, sizeof(mdns_ip_addr_t)); - a->addr.type = ip->type; - if (ip->type == ESP_IPADDR_TYPE_V6) { - memcpy(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16); - } else { - a->addr.u_addr.ip4.addr = ip->u_addr.ip4.addr; - } - return a; -} - -/** - * @brief Chain new IP to search result - */ -static void _mdns_result_add_ip(mdns_result_t *r, esp_ip_addr_t *ip) -{ - mdns_ip_addr_t *a = r->addr; - while (a) { - if (a->addr.type == ip->type) { -#ifdef CONFIG_LWIP_IPV4 - if (a->addr.type == ESP_IPADDR_TYPE_V4 && a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { - return; - } -#endif -#ifdef CONFIG_LWIP_IPV6 - if (a->addr.type == ESP_IPADDR_TYPE_V6 && !memcmp(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { - return; - } -#endif - } - a = a->next; - } - a = _mdns_result_addr_create_ip(ip); - if (!a) { - return; - } - a->next = r->addr; - r->addr = a; -} - -/** - * @brief Called from parser to add A/AAAA data to search result - */ -static void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) -{ - mdns_result_t *r = NULL; - mdns_ip_addr_t *a = NULL; - - if ((search->type == MDNS_TYPE_A && ip->type == ESP_IPADDR_TYPE_V4) - || (search->type == MDNS_TYPE_AAAA && ip->type == ESP_IPADDR_TYPE_V6) - || search->type == MDNS_TYPE_ANY) { - r = search->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { - _mdns_result_add_ip(r, ip); - _mdns_result_update_ttl(r, ttl); - return; - } - r = r->next; - } - if (!search->max_results || search->num_results < search->max_results) { - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; - return; - } - - memset(r, 0, sizeof(mdns_result_t)); - - a = _mdns_result_addr_create_ip(ip); - if (!a) { - mdns_mem_free(r); - return; - } - a->next = r->addr; - r->hostname = mdns_mem_strdup(hostname); - r->addr = a; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->next = search->result; - r->ttl = ttl; - search->result = r; - search->num_results++; - } - } else if (search->type == MDNS_TYPE_PTR || search->type == MDNS_TYPE_SRV) { - r = search->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { - _mdns_result_add_ip(r, ip); - _mdns_result_update_ttl(r, ttl); - break; - } - r = r->next; - } - } -} - -/** - * @brief Called from parser to add A/AAAA data to search result - */ -static void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) -{ - if (out_sync_browse->browse == NULL) { - return; - } else { - if (out_sync_browse->browse != browse) { - return; - } - } - mdns_result_t *r = NULL; - mdns_ip_addr_t *r_a = NULL; - if (browse) { - r = browse->result; - while (r) { - if (r->ip_protocol == ip_protocol) { - // Find the target result in browse result. - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { - r_a = r->addr; - // Check if the address has already added in result. - while (r_a) { -#ifdef CONFIG_LWIP_IPV4 - if (r_a->addr.type == ip->type && r_a->addr.type == ESP_IPADDR_TYPE_V4 && r_a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { - break; - } -#endif -#ifdef CONFIG_LWIP_IPV6 - if (r_a->addr.type == ip->type && r_a->addr.type == ESP_IPADDR_TYPE_V6 && !memcmp(r_a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { - break; - } -#endif - r_a = r_a->next; - } - if (!r_a) { - // The current IP is a new one, add it to the link list. - mdns_ip_addr_t *a = NULL; - a = _mdns_result_addr_create_ip(ip); - if (!a) { - return; - } - a->next = r->addr; - r->addr = a; - if (r->ttl != ttl) { - if (r->ttl == 0) { - r->ttl = ttl; - } else { - _mdns_result_update_ttl(r, ttl); - } - } - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { - return; - } - break; - } - } - } - r = r->next; - } - } - return; -} - - -/** - * @brief Called from parser to add TXT data to search result - */ -static void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, - mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl, mdns_browse_sync_t *out_sync_browse) -{ - if (out_sync_browse->browse == NULL) { - return; - } else { - if (out_sync_browse->browse != browse) { - return; - } - } - mdns_result_t *r = browse->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && - !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && - !mdns_utils_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && - !mdns_utils_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { - bool should_update = false; - if (r->txt) { - // Check if txt changed - if (txt_count != r->txt_count) { - should_update = true; - } else { - for (size_t txt_index = 0; txt_index < txt_count; txt_index++) { - if (!is_txt_item_in_list(txt[txt_index], txt_value_len[txt_index], r->txt, r->txt_value_len, r->txt_count)) { - should_update = true; - break; - } - } - } - // If the result has a previous txt entry, we delete it and re-add. - for (size_t i = 0; i < r->txt_count; i++) { - mdns_mem_free((char *)(r->txt[i].key)); - mdns_mem_free((char *)(r->txt[i].value)); - } - mdns_mem_free(r->txt); - mdns_mem_free(r->txt_value_len); - } - r->txt = txt; - r->txt_value_len = txt_value_len; - r->txt_count = txt_count; - if (r->ttl != ttl) { - uint32_t previous_ttl = r->ttl; - if (r->ttl == 0) { - r->ttl = ttl; - } else { - _mdns_result_update_ttl(r, ttl); - } - if (previous_ttl != r->ttl) { - should_update = true; - } - } - if (should_update) { - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { - return; - } - } - return; - } - r = r->next; - } - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; - goto free_txt; - } - memset(r, 0, sizeof(mdns_result_t)); - r->instance_name = mdns_mem_strdup(instance); - r->service_type = mdns_mem_strdup(service); - r->proto = mdns_mem_strdup(proto); - if (!r->instance_name || !r->service_type || !r->proto) { - mdns_mem_free(r->instance_name); - mdns_mem_free(r->service_type); - mdns_mem_free(r->proto); - mdns_mem_free(r); - return; - } - r->txt = txt; - r->txt_value_len = txt_value_len; - r->txt_count = txt_count; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->ttl = ttl; - r->next = browse->result; - browse->result = r; - _mdns_add_browse_result(out_sync_browse, r); - return; - -free_txt: - for (size_t i = 0; i < txt_count; i++) { - mdns_mem_free((char *)(txt[i].key)); - mdns_mem_free((char *)(txt[i].value)); - } - mdns_mem_free(txt); - mdns_mem_free(txt_value_len); - return; -} - #ifdef CONFIG_LWIP_IPV4 /** * @brief Detect IPv4 address collision @@ -748,7 +405,6 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) } #endif /* CONFIG_LWIP_IPV6 */ - /** * @brief Detect TXT collision */ @@ -794,7 +450,6 @@ static int _mdns_check_txt_collision(mdns_service_t *service, const uint8_t *dat return 0;//same } - /** * @brief Detect SRV collision */ @@ -852,150 +507,6 @@ static int _mdns_check_srv_collision(mdns_service_t *service, uint16_t priority, return 0;//same } -/** - * @brief Called from parser to add SRV data to search result - */ -static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) -{ - mdns_result_t *r = search->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { - _mdns_result_update_ttl(r, ttl); - return; - } - r = r->next; - } - if (!search->max_results || search->num_results < search->max_results) { - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; - return; - } - - memset(r, 0, sizeof(mdns_result_t)); - r->hostname = mdns_mem_strdup(hostname); - if (!r->hostname) { - mdns_mem_free(r); - return; - } - if (search->instance) { - r->instance_name = mdns_mem_strdup(search->instance); - } - r->service_type = mdns_mem_strdup(search->service); - r->proto = mdns_mem_strdup(search->proto); - r->port = port; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->ttl = ttl; - r->next = search->result; - search->result = r; - search->num_results++; - } -} - -static esp_err_t _mdns_copy_address_in_previous_result(mdns_result_t *result_list, mdns_result_t *r) -{ - while (result_list) { - if (!mdns_utils_str_null_or_empty(result_list->hostname) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(result_list->hostname, r->hostname) && - result_list->ip_protocol == r->ip_protocol && result_list->addr && !r->addr) { - // If there is a same hostname in previous result, we need to copy the address here. - r->addr = copy_address_list(result_list->addr); - if (!r->addr) { - return ESP_ERR_NO_MEM; - } - break; - } else { - result_list = result_list->next; - } - } - return ESP_OK; -} - -/** - * @brief Called from parser to add SRV data to search result - */ -static void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, - uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) -{ - if (out_sync_browse->browse == NULL) { - return; - } else { - if (out_sync_browse->browse != browse) { - return; - } - } - mdns_result_t *r = browse->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && - !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && - !mdns_utils_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && - !mdns_utils_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { - if (mdns_utils_str_null_or_empty(r->hostname) || strcasecmp(hostname, r->hostname)) { - r->hostname = mdns_mem_strdup(hostname); - r->port = port; - if (!r->hostname) { - HOOK_MALLOC_FAILED; - return; - } - if (!r->addr) { - esp_err_t err = _mdns_copy_address_in_previous_result(browse->result, r); - if (err == ESP_ERR_NO_MEM) { - return; - } - } - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { - return; - } - } - if (r->ttl != ttl) { - uint32_t previous_ttl = r->ttl; - if (r->ttl == 0) { - r->ttl = ttl; - } else { - _mdns_result_update_ttl(r, ttl); - } - if (previous_ttl != r->ttl) { - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { - return; - } - } - } - return; - } - r = r->next; - } - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; - return; - } - - memset(r, 0, sizeof(mdns_result_t)); - r->hostname = mdns_mem_strdup(hostname); - r->instance_name = mdns_mem_strdup(instance); - r->service_type = mdns_mem_strdup(service); - r->proto = mdns_mem_strdup(proto); - if (!r->hostname || !r->instance_name || !r->service_type || !r->proto) { - HOOK_MALLOC_FAILED; - mdns_mem_free(r->hostname); - mdns_mem_free(r->instance_name); - mdns_mem_free(r->service_type); - mdns_mem_free(r->proto); - mdns_mem_free(r); - return; - } - r->port = port; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->ttl = ttl; - r->next = browse->result; - browse->result = r; - _mdns_add_browse_result(out_sync_browse, r); - return; -} - - /** * @brief Check if the parsed name is self-hosted, i.e. we should resolve conflicts */ @@ -1019,10 +530,6 @@ static bool _mdns_name_is_selfhosted(mdns_name_t *name) return false; } - - - - /** * @brief Called from parser to check if question matches particular service */ @@ -1090,53 +597,6 @@ static void _mdns_remove_parsed_question(mdns_parsed_packet_t *parsed_packet, ui } } - -/** - * @brief Called from parser to add PTR data to search result - */ -static mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, - const char *service_type, const char *proto, mdns_if_t tcpip_if, - mdns_ip_protocol_t ip_protocol, uint32_t ttl) -{ - mdns_result_t *r = search->result; - while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { - _mdns_result_update_ttl(r, ttl); - return r; - } - r = r->next; - } - if (!search->max_results || search->num_results < search->max_results) { - r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); - if (!r) { - HOOK_MALLOC_FAILED; - return NULL; - } - - memset(r, 0, sizeof(mdns_result_t)); - r->instance_name = mdns_mem_strdup(instance); - r->service_type = mdns_mem_strdup(service_type); - r->proto = mdns_mem_strdup(proto); - if (!r->instance_name) { - mdns_mem_free(r); - return NULL; - } - - r->esp_netif = _mdns_get_esp_netif(tcpip_if); - r->ip_protocol = ip_protocol; - r->ttl = ttl; - r->next = search->result; - search->result = r; - search->num_results++; - return r; - } - return NULL; -} - -/* - * Received Packet Handling - * */ - /** * @brief main packet parser * diff --git a/components/mdns/mdns_utils.c b/components/mdns/mdns_utils.c index 8aebad3160..255d9a4ba9 100644 --- a/components/mdns/mdns_utils.c +++ b/components/mdns/mdns_utils.c @@ -11,7 +11,7 @@ static const char *MDNS_DEFAULT_DOMAIN = "local"; static const char *MDNS_SUB_STR = "_sub"; -static const char *TAG = "mdns_utils"; +//static const char *TAG = "mdns_utils"; /** * @brief reads MDNS FQDN into mdns_name_t structure @@ -237,32 +237,6 @@ bool _mdns_instance_name_match(const char *lhs, const char *rhs) return !strcasecmp(lhs, rhs); } -/** - * @brief Add result to browse, only add when the result is a new one. - */ -esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r) -{ - mdns_browse_result_sync_t *sync_r = sync_browse->sync_result; - while (sync_r) { - if (sync_r->result == r) { - break; - } - sync_r = sync_r->next; - } - if (!sync_r) { - // Do not find, need to add the result to the list - mdns_browse_result_sync_t *new = (mdns_browse_result_sync_t *)mdns_mem_malloc(sizeof(mdns_browse_result_sync_t)); - - if (!new) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; - } - new->result = r; - new->next = sync_browse->sync_result; - sync_browse->sync_result = new; - } - return ESP_OK; -} mdns_ip_addr_t *copy_address_list(const mdns_ip_addr_t *address_list) { diff --git a/components/mdns/private_include/mdns_browse.h b/components/mdns/private_include/mdns_browse.h deleted file mode 100644 index 936298344e..0000000000 --- a/components/mdns/private_include/mdns_browse.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include -#include "mdns_private.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//void _mdns_browse_item_free(mdns_browse_t *browse); -//void _mdns_browse_sync(mdns_browse_sync_t *browse_sync); -//void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface); -void mdns_browse_free(void); - -mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); - -void mdns_browse_send_all(mdns_if_t mdns_if); - -void mdns_browse_action(mdns_action_t *action, mdns_action_subtype_t type); - -#ifdef __cplusplus -} -#endif diff --git a/components/mdns/private_include/mdns_browser.h b/components/mdns/private_include/mdns_browser.h new file mode 100644 index 0000000000..aba3cb57d9 --- /dev/null +++ b/components/mdns/private_include/mdns_browser.h @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "mdns_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void mdns_browse_free(void); + +mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +void mdns_browse_send_all(mdns_if_t mdns_if); + +void mdns_browse_action(mdns_action_t *action, mdns_action_subtype_t type); + +//esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r);; +void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, + mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, + uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +#ifdef __cplusplus +} +#endif diff --git a/components/mdns/private_include/mdns_querier.h b/components/mdns/private_include/mdns_querier.h index deae8ab757..d08e0f08d2 100644 --- a/components/mdns/private_include/mdns_querier.h +++ b/components/mdns/private_include/mdns_querier.h @@ -16,10 +16,20 @@ void _mdns_search_run(void); void mdns_search_free(void); void _mdns_query_results_free(mdns_result_t *results); void _mdns_search_finish_done(void); -//void _mdns_search_send(mdns_search_once_t *search); mdns_search_once_t *_mdns_search_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -//void _mdns_search_free(mdns_search_once_t *search); + +mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip); +void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, + size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl); +void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); +void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); +mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, + const char *service_type, const char *proto, mdns_if_t tcpip_if, + mdns_ip_protocol_t ip_protocol, uint32_t ttl); void mdns_query_action(mdns_action_t *action, mdns_action_subtype_t type); diff --git a/components/mdns/private_include/mdns_utils.h b/components/mdns/private_include/mdns_utils.h index acc9a4a5ef..3141a785bc 100644 --- a/components/mdns/private_include/mdns_utils.h +++ b/components/mdns/private_include/mdns_utils.h @@ -92,7 +92,7 @@ bool _mdns_instance_name_match(const char *lhs, const char *rhs); const char *_mdns_get_default_instance_name(void); const char *_mdns_get_service_instance_name(const mdns_service_t *service); -esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r); + mdns_ip_addr_t *copy_address_list(const mdns_ip_addr_t *address_list); void free_address_list(mdns_ip_addr_t *address_list); int append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt); diff --git a/components/mdns/tests/test_afl_fuzz_host/Makefile b/components/mdns/tests/test_afl_fuzz_host/Makefile index 8d00b3e346..a247f61cee 100644 --- a/components/mdns/tests/test_afl_fuzz_host/Makefile +++ b/components/mdns/tests/test_afl_fuzz_host/Makefile @@ -51,7 +51,7 @@ else endif CPP=$(CC) LD=$(CC) -OBJECTS=esp32_mock.o mdns.o test.o esp_netif_mock.o mdns_utils.o mdns_packet.o mdns_browser.o mdns_querier.o mdns_send.o mdns_responder.o mdns_netif.o +OBJECTS=esp32_mock.o mdns.o test.o esp_netif_mock.o mdns_utils.o mdns_receive.o mdns_browser.o mdns_querier.o mdns_send.o mdns_responder.o mdns_netif.o OS := $(shell uname) ifeq ($(OS),Darwin) From 21a5dc57d50b21ad9a3f5e69f755b99480ef6fe4 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 12 Mar 2025 12:30:24 +0100 Subject: [PATCH 08/27] fix(mdns): Cleanup and split interfaces between modules --- components/mdns/mdns.c | 44 ++++---- components/mdns/mdns_browser.c | 16 +-- components/mdns/mdns_netif.c | 16 +-- components/mdns/mdns_querier.c | 64 ++++------- components/mdns/mdns_receive.c | 87 ++++++++------- components/mdns/mdns_responder.c | 51 +++++---- components/mdns/mdns_send.c | 21 ++-- components/mdns/mdns_utils.c | 23 +++- .../mdns/private_include/mdns_browser.h | 54 ++++++++-- components/mdns/private_include/mdns_debug.h | 19 ++++ components/mdns/private_include/mdns_netif.h | 40 +++++-- .../mdns/private_include/mdns_private.h | 9 -- .../mdns/private_include/mdns_querier.h | 95 ++++++++++++---- .../mdns/private_include/mdns_receive.h | 7 +- .../mdns/private_include/mdns_responder.h | 102 +++++++++++++++--- components/mdns/private_include/mdns_utils.h | 1 + 16 files changed, 444 insertions(+), 205 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 7703fb6bad..4d9df9c01c 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -127,7 +127,7 @@ static void _mdns_announce_all_pcbs(mdns_srv_item_t **services, size_t len, bool uint8_t i, j; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - _mdns_announce_pcb((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); + mdns_priv_pcb_announce((mdns_if_t) i, (mdns_ip_protocol_t) j, services, len, include_ip); } } } @@ -154,7 +154,7 @@ static void _mdns_send_final_bye(bool include_ip) services[i++] = a; a = a->next; } - _mdns_send_bye(services, srv_count, include_ip); + mdns_responder_send_bye_service(services, srv_count, include_ip); } /** @@ -182,7 +182,7 @@ static void _mdns_send_bye_all_pcbs_no_instance(bool include_ip) } a = a->next; } - _mdns_send_bye(services, srv_count, include_ip); + mdns_responder_send_bye_service(services, srv_count, include_ip); } /** @@ -470,7 +470,7 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) while (srv) { if (strcasecmp(srv->service->hostname, hostname) == 0) { mdns_srv_item_t *to_free = srv; - _mdns_send_bye(&srv, 1, false); + mdns_responder_send_bye_service(&srv, 1, false); _mdns_remove_scheduled_service_packets(srv->service); if (prev_srv == NULL) { _mdns_server->services = srv->next; @@ -523,22 +523,22 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) return; } if (action & MDNS_EVENT_ENABLE_IP4) { - _mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); + mdns_priv_pcb_enable(mdns_if, MDNS_IP_PROTOCOL_V4); } if (action & MDNS_EVENT_ENABLE_IP6) { - _mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); + mdns_priv_pcb_enable(mdns_if, MDNS_IP_PROTOCOL_V6); } if (action & MDNS_EVENT_DISABLE_IP4) { - _mdns_disable_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); + mdns_priv_pcb_disable(mdns_if, MDNS_IP_PROTOCOL_V4); } if (action & MDNS_EVENT_DISABLE_IP6) { - _mdns_disable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); + mdns_priv_pcb_disable(mdns_if, MDNS_IP_PROTOCOL_V6); } if (action & MDNS_EVENT_ANNOUNCE_IP4) { - _mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4, NULL, 0, true); + mdns_priv_pcb_announce(mdns_if, MDNS_IP_PROTOCOL_V4, NULL, 0, true); } if (action & MDNS_EVENT_ANNOUNCE_IP6) { - _mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V6, NULL, 0, true); + mdns_priv_pcb_announce(mdns_if, MDNS_IP_PROTOCOL_V6, NULL, 0, true); } #ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES @@ -614,7 +614,7 @@ static void _mdns_free_action(mdns_action_t *action) case ACTION_SEARCH_ADD: case ACTION_SEARCH_SEND: case ACTION_SEARCH_END: - mdns_query_action(action, ACTION_CLEANUP); + mdns_priv_query_action(action, ACTION_CLEANUP); break; case ACTION_BROWSE_ADD: case ACTION_BROWSE_END: @@ -625,7 +625,7 @@ static void _mdns_free_action(mdns_action_t *action) mdns_send_action(action, ACTION_CLEANUP); break; case ACTION_RX_HANDLE: - mdns_receive_action(action, ACTION_CLEANUP); + mdns_priv_receive_action(action, ACTION_CLEANUP); break; case ACTION_DELEGATE_HOSTNAME_SET_ADDR: case ACTION_DELEGATE_HOSTNAME_ADD: @@ -669,7 +669,7 @@ static void _mdns_execute_action(mdns_action_t *action) case ACTION_SEARCH_ADD: case ACTION_SEARCH_SEND: case ACTION_SEARCH_END: - mdns_query_action(action, ACTION_RUN); + mdns_priv_query_action(action, ACTION_RUN); break; case ACTION_BROWSE_ADD: case ACTION_BROWSE_SYNC: @@ -681,7 +681,7 @@ static void _mdns_execute_action(mdns_action_t *action) mdns_send_action(action, ACTION_RUN); break; case ACTION_RX_HANDLE: - mdns_receive_action(action, ACTION_RUN); + mdns_priv_receive_action(action, ACTION_RUN); break; case ACTION_DELEGATE_HOSTNAME_ADD: if (!_mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, @@ -736,7 +736,7 @@ static void _mdns_service_task(void *pvParameters) static void _mdns_timer_cb(void *arg) { mdns_send_packets(); - _mdns_search_run(); + mdns_priv_query_start_stop(); } static esp_err_t _mdns_start_timer(void) @@ -920,14 +920,14 @@ void mdns_free(void) } // Unregister handlers before destroying the mdns internals to avoid receiving async events while deinit - unregister_predefined_handlers(); + mdns_netif_unregister_predefined_handlers(); mdns_service_remove_all(); free_delegated_hostnames(); _mdns_service_task_stop(); // at this point, the service task is deleted, so we can destroy the stack size mdns_mem_task_free(_mdns_stack_buffer); - mdns_responder_deinit(); + mdns_priv_pcb_deinit(); mdns_mem_free((char *)_mdns_server->hostname); mdns_mem_free((char *)_mdns_server->instance); if (_mdns_server->action_queue) { @@ -938,7 +938,7 @@ void mdns_free(void) vQueueDelete(_mdns_server->action_queue); } _mdns_clear_tx_queue_head(); - mdns_search_free(); + mdns_priv_query_free(); mdns_browse_free(); vSemaphoreDelete(_mdns_server->action_sema); mdns_mem_free(_mdns_server); @@ -1336,7 +1336,7 @@ static mdns_result_t *_mdns_lookup_service(const char *instance, const char *ser } return results; handle_error: - _mdns_query_results_free(results); + mdns_priv_query_results_free(results); return NULL; } @@ -1783,7 +1783,7 @@ esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, cons ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); if (s->service->instance) { - _mdns_send_bye(&s, 1, false); + mdns_responder_send_bye_service(&s, 1, false); mdns_mem_free((char *)s->service->instance); } s->service->instance = mdns_mem_strndup(instance, MDNS_NAME_BUF_LEN - 1); @@ -1823,7 +1823,7 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service } else { _mdns_server->services = a->next; } - _mdns_send_bye(&a, 1, false); + mdns_responder_send_bye_service(&a, 1, false); _mdns_remove_scheduled_service_packets(a->service); _mdns_free_service(a->service); mdns_mem_free(a); @@ -1840,7 +1840,7 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service } else { _mdns_server->services = a->next; } - _mdns_send_bye(&a, 1, false); + mdns_responder_send_bye_service(&a, 1, false); _mdns_remove_scheduled_service_packets(a->service); _mdns_free_service(a->service); mdns_mem_free(a); diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index fd7535af29..69583fb074 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -48,7 +48,7 @@ static void _mdns_browse_item_free(mdns_browse_t *browse) mdns_mem_free(browse->service); mdns_mem_free(browse->proto); if (browse->result) { - _mdns_query_results_free(browse->result); + mdns_priv_query_results_free(browse->result); } mdns_mem_free(browse); } @@ -349,8 +349,8 @@ static esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_r /** * @brief Called from parser to add A/AAAA data to search result */ -void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +void mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) { if (out_sync_browse->browse == NULL) { return; @@ -428,9 +428,9 @@ static bool is_txt_item_in_list(mdns_txt_item_t txt, uint8_t txt_value_len, mdns /** * @brief Called from parser to add TXT data to search result */ -void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, - mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +void mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, + mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl, mdns_browse_sync_t *out_sync_browse) { if (out_sync_browse->browse == NULL) { return; @@ -547,8 +547,8 @@ static esp_err_t _mdns_copy_address_in_previous_result(mdns_result_t *result_lis /** * @brief Called from parser to add SRV data to search result */ -void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, - uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +void mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, + uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) { if (out_sync_browse->browse == NULL) { return; diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c index c22d0ef725..7f5b2af4f0 100644 --- a/components/mdns/mdns_netif.c +++ b/components/mdns/mdns_netif.c @@ -72,7 +72,7 @@ static mdns_interfaces_t s_esp_netifs[MDNS_MAX_INTERFACES] = { * @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_get_other_if(mdns_if_t tcpip_if) +mdns_if_t mdns_netif_get_other_interface(mdns_if_t tcpip_if) { if (tcpip_if < MDNS_MAX_INTERFACES) { return s_esp_netifs[tcpip_if].duplicate; @@ -146,7 +146,7 @@ esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) /* * @brief Clean internal mdns interface's pointer */ -void _mdns_clean_netif_ptr(mdns_if_t tcpip_if) +void mdns_netif_disable(mdns_if_t tcpip_if) { if (tcpip_if < MDNS_MAX_INTERFACES) { s_esp_netifs[tcpip_if].netif = NULL; @@ -315,7 +315,7 @@ static inline void set_default_duplicated_interfaces(void) } } -void unregister_predefined_handlers(void) +void mdns_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, mdns_preset_if_handle_system_event); @@ -420,19 +420,19 @@ esp_err_t mdns_netif_init(void) for (i = 0; i < MDNS_MAX_INTERFACES; i++) { #ifdef CONFIG_LWIP_IPV6 if (!esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(i), &tmp_addr6) && !mdns_utils_ipv6_address_is_zero(tmp_addr6)) { - _mdns_enable_pcb(i, MDNS_IP_PROTOCOL_V6); + mdns_priv_pcb_enable(i, MDNS_IP_PROTOCOL_V6); } #endif #ifdef CONFIG_LWIP_IPV4 if (!esp_netif_get_ip_info(_mdns_get_esp_netif(i), &if_ip_info) && if_ip_info.ip.addr) { - _mdns_enable_pcb(i, MDNS_IP_PROTOCOL_V4); + 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: - unregister_predefined_handlers(); + mdns_netif_unregister_predefined_handlers(); #endif return err; } @@ -440,8 +440,8 @@ esp_err_t mdns_netif_init(void) esp_err_t mdns_netif_deinit(void) { for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { - _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V6); - _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V4); + 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; diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index 90798d6c46..4d336c5211 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -19,7 +19,7 @@ static mdns_search_once_t *s_search_once; static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); static void _mdns_search_free(mdns_search_once_t *search); -void _mdns_query_results_free(mdns_result_t *results) +void mdns_priv_query_results_free(mdns_result_t *results) { mdns_result_t *r; mdns_ip_addr_t *a; @@ -101,7 +101,7 @@ void _mdns_search_send(mdns_search_once_t *search) } } -void mdns_query_action(mdns_action_t *action, mdns_action_subtype_t type) +void mdns_priv_query_action(mdns_action_t *action, mdns_action_subtype_t type) { if (type == ACTION_RUN) { switch (action->type) { @@ -127,7 +127,7 @@ void mdns_query_action(mdns_action_t *action, mdns_action_subtype_t type) /** * @brief Called from timer task to run active searches */ -void _mdns_search_run(void) +void mdns_priv_query_start_stop(void) { mdns_service_lock(); mdns_search_once_t *s = s_search_once; @@ -156,7 +156,7 @@ void _mdns_search_run(void) mdns_service_unlock(); } -void mdns_search_free(void) +void mdns_priv_query_free(void) { while (s_search_once) { mdns_search_once_t *h = s_search_once; @@ -166,18 +166,16 @@ void mdns_search_free(void) mdns_mem_free(h->proto); vSemaphoreDelete(h->done_semaphore); if (h->result) { - _mdns_query_results_free(h->result); + mdns_priv_query_results_free(h->result); } mdns_mem_free(h); } } - - /** * @brief Called from parser to finish any searches that have reached maximum results */ -void _mdns_search_finish_done(void) +void mdns_priv_query_done(void) { mdns_search_once_t *search = s_search_once; mdns_search_once_t *s = NULL; @@ -193,7 +191,7 @@ void _mdns_search_finish_done(void) /** * @brief Called from packet parser to find matching running search */ -mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +mdns_search_once_t *mdns_priv_query_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_result_t *r = NULL; while (s) { @@ -257,9 +255,9 @@ mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *s, mdns_name_t *n return NULL; } -mdns_search_once_t *_mdns_search_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +mdns_search_once_t *mdns_priv_query_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { - return _mdns_search_find_from(s_search_once, name, type, tcpip_if, ip_protocol); + return mdns_priv_query_find_from(s_search_once, name, type, tcpip_if, ip_protocol); } /** @@ -326,7 +324,7 @@ static mdns_tx_packet_t *_mdns_create_search_packet(mdns_search_once_t *search, void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_tx_packet_t *packet = NULL; - if (mdsn_responder_iface_init(tcpip_if, ip_protocol)) { + if (mdsn_priv_pcb_is_inited(tcpip_if, ip_protocol)) { packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol); if (!packet) { return; @@ -417,7 +415,7 @@ static mdns_search_once_t *_mdns_search_init(const char *name, const char *servi void mdns_query_results_free(mdns_result_t *results) { mdns_service_lock(); - _mdns_query_results_free(results); + mdns_priv_query_results_free(results); mdns_service_unlock(); } @@ -637,32 +635,12 @@ esp_err_t mdns_query_aaaa(const char *name, uint32_t timeout, esp_ip6_addr_t *ad } #endif /* CONFIG_LWIP_IPV6 */ -/** - * @brief Create linked IP (copy) from parsed one - */ -mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip) -{ - mdns_ip_addr_t *a = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); - if (!a) { - HOOK_MALLOC_FAILED; - return NULL; - } - memset(a, 0, sizeof(mdns_ip_addr_t)); - a->addr.type = ip->type; - if (ip->type == ESP_IPADDR_TYPE_V6) { - memcpy(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16); - } else { - a->addr.u_addr.ip4.addr = ip->u_addr.ip4.addr; - } - return a; -} - /** * @brief Called from parser to add TXT data to search result */ -void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, - size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl) +void mdns_priv_query_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, + size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl) { mdns_result_t *r = search->result; while (r) { @@ -739,8 +717,8 @@ static void _mdns_result_add_ip(mdns_result_t *r, esp_ip_addr_t *ip) /** * @brief Called from parser to add A/AAAA data to search result */ -void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) +void mdns_priv_query_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) { mdns_result_t *r = NULL; mdns_ip_addr_t *a = NULL; @@ -797,8 +775,8 @@ void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname /** * @brief Called from parser to add SRV data to search result */ -void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) +void mdns_priv_query_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) { mdns_result_t *r = search->result; while (r) { @@ -839,9 +817,9 @@ void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostnam /** * @brief Called from parser to add PTR data to search result */ -mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, - const char *service_type, const char *proto, mdns_if_t tcpip_if, - mdns_ip_protocol_t ip_protocol, uint32_t ttl) +mdns_result_t *mdns_priv_query_result_add_ptr(mdns_search_once_t *search, const char *instance, + const char *service_type, const char *proto, mdns_if_t tcpip_if, + mdns_ip_protocol_t ip_protocol, uint32_t ttl) { mdns_result_t *r = search->result; while (r) { diff --git a/components/mdns/mdns_receive.c b/components/mdns/mdns_receive.c index b403e421be..d0c70a59a6 100644 --- a/components/mdns/mdns_receive.c +++ b/components/mdns/mdns_receive.c @@ -352,7 +352,7 @@ static int _mdns_check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) return -1;//we win } else if (ret < 0) { //is it the other interface? - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); if (other_if == MDNS_MAX_INTERFACES) { return 1;//AP interface! They win } @@ -362,7 +362,7 @@ static int _mdns_check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) if (ip->addr != other_ip_info.ip.addr) { return 1;//IPv4 not ours! They win } - _mdns_dup_interface(tcpip_if); + mdns_priv_pcb_set_duplicate(tcpip_if); return 2;//they win } return 0;//same @@ -388,7 +388,7 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) return -1;//we win } else if (ret < 0) { //is it the other interface? - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); if (other_if == MDNS_MAX_INTERFACES) { return 1;//AP interface! They win } @@ -398,7 +398,7 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) if (memcmp((uint8_t *)&other_ip6.addr, (uint8_t *)ip->addr, _MDNS_SIZEOF_IP6_ADDR)) { return 1;//IPv6 not ours! They win } - _mdns_dup_interface(tcpip_if); + mdns_priv_pcb_set_duplicate(tcpip_if); return 2;//they win } return 0;//same @@ -819,7 +819,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) //skip this record continue; } - search_result = _mdns_search_find(name, type, packet->tcpip_if, packet->ip_protocol); + search_result = mdns_priv_query_find(name, type, packet->tcpip_if, packet->ip_protocol); browse_result = _mdns_browse_find(name, type, packet->tcpip_if, packet->ip_protocol); if (browse_result) { if (!out_sync_browse) { @@ -866,8 +866,8 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) continue;//error } if (search_result) { - _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, - packet->tcpip_if, packet->ip_protocol, ttl); + mdns_priv_query_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { if (name->host[0]) { service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL); @@ -937,8 +937,8 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) result = result->next; } if (!result) { - result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, - packet->tcpip_if, packet->ip_protocol, ttl); + result = mdns_priv_query_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); if (!result) { continue;//error } @@ -956,8 +956,9 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) uint16_t port = mdns_utils_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); if (browse_result) { - _mdns_browse_result_add_srv(browse_result, name->host, browse_result_instance, browse_result_service, - browse_result_proto, port, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + mdns_browse_result_add_srv(browse_result, name->host, browse_result_instance, browse_result_service, + browse_result_proto, port, packet->tcpip_if, packet->ip_protocol, ttl, + out_sync_browse); } if (search_result) { if (search_result->type == MDNS_TYPE_PTR) { @@ -966,7 +967,8 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) result->hostname = mdns_mem_strdup(name->host); } } else { - _mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol, ttl); + mdns_priv_query_result_add_srv(search_result, name->host, port, packet->tcpip_if, + packet->ip_protocol, ttl); } } else if (ours) { if (parsed_packet->questions && !parsed_packet->probe) { @@ -991,8 +993,8 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (service && col && (parsed_packet->probe || parsed_packet->authoritative)) { if (col > 0 || !port) { do_not_reply = true; - if (mdns_responder_is_probing(packet)) { - mdns_responder_probe_failed(packet); + if (mdns_priv_pcb_is_probing(packet)) { + mdns_priv_pcb_set_probe_failed(packet); if (!mdns_utils_str_null_or_empty(service->service->instance)) { char *new_instance = _mdns_mangle_name((char *)service->service->instance); if (new_instance) { @@ -1031,8 +1033,10 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) mdns_result_t *result = NULL; if (browse_result) { _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); - _mdns_browse_result_add_txt(browse_result, browse_result_instance, browse_result_service, browse_result_proto, - txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + mdns_browse_result_add_txt(browse_result, browse_result_instance, browse_result_service, + browse_result_proto, + txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, + ttl, out_sync_browse); } if (search_result) { if (search_result->type == MDNS_TYPE_PTR) { @@ -1046,8 +1050,9 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) result = result->next; } if (!result) { - result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, - packet->tcpip_if, packet->ip_protocol, ttl); + result = mdns_priv_query_result_add_ptr(search_result, name->host, name->service, + name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); if (!result) { continue;//error } @@ -1063,7 +1068,8 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else { _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); if (txt_count) { - _mdns_search_result_add_txt(search_result, txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, ttl); + mdns_priv_query_result_add_txt(search_result, txt, txt_value_len, txt_count, + packet->tcpip_if, packet->ip_protocol, ttl); } } } else if (ours) { @@ -1083,10 +1089,11 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else if (service) { // only detect txt collision if service existed col = _mdns_check_txt_collision(service->service, data_ptr, data_len); } - if (col && !mdns_responder_is_probing(packet) && service) { + if (col && !mdns_priv_pcb_is_probing(packet) && service) { do_not_reply = true; _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); - } else if (ttl > (MDNS_ANSWER_TXT_TTL / 2) && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_responder_is_probing(packet)) { + } else if (ttl > (MDNS_ANSWER_TXT_TTL / 2) && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( + packet)) { _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); } } @@ -1098,13 +1105,16 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) ip6.type = ESP_IPADDR_TYPE_V6; memcpy(ip6.u_addr.ip6.addr, data_ptr, MDNS_ANSWER_AAAA_SIZE); if (browse_result) { - _mdns_browse_result_add_ip(browse_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + mdns_browse_result_add_ip(browse_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, + ttl, out_sync_browse); } if (search_result) { //check for more applicable searches (PTR & A/AAAA at the same time) while (search_result) { - _mdns_search_result_add_ip(search_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, ttl); - search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); + mdns_priv_query_result_add_ip(search_result, name->host, &ip6, packet->tcpip_if, + packet->ip_protocol, ttl); + search_result = mdns_priv_query_find_from(search_result->next, name, type, packet->tcpip_if, + packet->ip_protocol); } } else if (ours) { if (parsed_packet->questions && !parsed_packet->probe) { @@ -1127,9 +1137,9 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) goto clear_rx_packet; } else if (col == 1) { do_not_reply = true; - if (mdns_responder_is_probing(packet)) { + if (mdns_priv_pcb_is_probing(packet)) { if (col && (parsed_packet->probe || parsed_packet->authoritative)) { - mdns_responder_probe_failed(packet); + mdns_priv_pcb_set_probe_failed(packet); char *new_host = _mdns_mangle_name((char *)mdns_utils_get_global_hostname()); if (new_host) { _mdns_remap_self_service_hostname(mdns_utils_get_global_hostname(), new_host); @@ -1140,7 +1150,8 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else { _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); } - } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_responder_is_probing(packet)) { + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( + packet)) { _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); } } @@ -1153,13 +1164,16 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) ip.type = ESP_IPADDR_TYPE_V4; memcpy(&(ip.u_addr.ip4.addr), data_ptr, 4); if (browse_result) { - _mdns_browse_result_add_ip(browse_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + mdns_browse_result_add_ip(browse_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, + ttl, out_sync_browse); } if (search_result) { //check for more applicable searches (PTR & A/AAAA at the same time) while (search_result) { - _mdns_search_result_add_ip(search_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, ttl); - search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); + mdns_priv_query_result_add_ip(search_result, name->host, &ip, packet->tcpip_if, + packet->ip_protocol, ttl); + search_result = mdns_priv_query_find_from(search_result->next, name, type, packet->tcpip_if, + packet->ip_protocol); } } else if (ours) { if (parsed_packet->questions && !parsed_packet->probe) { @@ -1182,9 +1196,9 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) goto clear_rx_packet; } else if (col == 1) { do_not_reply = true; - if (mdns_responder_is_probing(packet)) { + if (mdns_priv_pcb_is_probing(packet)) { if (col && (parsed_packet->probe || parsed_packet->authoritative)) { - mdns_responder_probe_failed(packet); + mdns_priv_pcb_set_probe_failed(packet); char *new_host = _mdns_mangle_name((char *)mdns_utils_get_global_hostname()); if (new_host) { _mdns_remap_self_service_hostname(mdns_utils_get_global_hostname(), new_host); @@ -1195,7 +1209,8 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else { _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); } - } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_responder_is_probing(packet)) { + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( + packet)) { _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); } } @@ -1205,11 +1220,11 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } //end while if (parsed_packet->authoritative) { - _mdns_search_finish_done(); + mdns_priv_query_done(); } } - if (!do_not_reply && mdns_responder_after_probing(packet) && (parsed_packet->questions || parsed_packet->discovery)) { + if (!do_not_reply && mdns_priv_pcb_is_after_probing(packet) && (parsed_packet->questions || parsed_packet->discovery)) { _mdns_create_answer_from_parsed_packet(parsed_packet); } if (out_sync_browse) { @@ -1265,7 +1280,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) mdns_mem_free(out_sync_browse); } -void mdns_receive_action(mdns_action_t *action, mdns_action_subtype_t type) +void mdns_priv_receive_action(mdns_action_t *action, mdns_action_subtype_t type) { if (action->type != ACTION_RX_HANDLE) { abort(); diff --git a/components/mdns/mdns_responder.c b/components/mdns/mdns_responder.c index 7690cdc6f0..9c69d67523 100644 --- a/components/mdns/mdns_responder.c +++ b/components/mdns/mdns_responder.c @@ -16,12 +16,21 @@ static const char *TAG = "mdns_responder"; +typedef struct { + mdns_pcb_state_t state; + mdns_srv_item_t **probe_services; + uint8_t probe_services_len; + uint8_t probe_ip; + uint8_t probe_running; + uint16_t failed_probes; +} mdns_pcb_t; + static mdns_pcb_t s_pcbs[MDNS_MAX_INTERFACES][MDNS_IP_PROTOCOL_MAX]; /** * @brief Send announcement on particular PCB */ -void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) +void mdns_priv_pcb_announce(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) { mdns_pcb_t *_pcb = &s_pcbs[tcpip_if][ip_protocol]; size_t i; @@ -64,9 +73,9 @@ void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns /** * @brief Check if interface is duplicate (two interfaces on the same subnet) */ -bool _mdns_if_is_dup(mdns_if_t tcpip_if) +bool mdns_priv_pcb_check_for_duplicates(mdns_if_t tcpip_if) { - mdns_if_t ifaces[MDNS_MAX_INTERFACES] = {tcpip_if, _mdns_get_other_if(tcpip_if) }; + mdns_if_t ifaces[MDNS_MAX_INTERFACES] = {tcpip_if, mdns_netif_get_other_interface(tcpip_if) }; if (ifaces[1] == MDNS_MAX_INTERFACES) { return false; } @@ -128,17 +137,17 @@ static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol /** * @brief Disable mDNS interface */ -void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +void mdns_priv_pcb_disable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { - _mdns_clean_netif_ptr(tcpip_if); + mdns_netif_disable(tcpip_if); if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); mdns_pcb_deinit_local(tcpip_if, ip_protocol); - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); if (other_if != MDNS_MAX_INTERFACES && s_pcbs[other_if][ip_protocol].state == PCB_DUP) { s_pcbs[other_if][ip_protocol].state = PCB_OFF; - _mdns_enable_pcb(other_if, ip_protocol); + mdns_priv_pcb_enable(other_if, ip_protocol); } } s_pcbs[tcpip_if][ip_protocol].state = PCB_OFF; @@ -147,7 +156,7 @@ void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) /** * @brief Enable mDNS interface */ -void _mdns_enable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +void mdns_priv_pcb_enable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { if (!mdns_is_netif_ready(tcpip_if, ip_protocol)) { if (_mdns_pcb_init(tcpip_if, ip_protocol)) { @@ -161,10 +170,10 @@ void _mdns_enable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) /** * @brief Set interface as duplicate if another is found on the same subnet */ -void _mdns_dup_interface(mdns_if_t tcpip_if) +void mdns_priv_pcb_set_duplicate(mdns_if_t tcpip_if) { uint8_t i; - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); if (other_if == MDNS_MAX_INTERFACES) { return; // no other interface found } @@ -177,17 +186,17 @@ void _mdns_dup_interface(mdns_if_t tcpip_if) } s_pcbs[tcpip_if][i].state = PCB_DUP; // _mdns_server->interfaces[tcpip_if].pcbs[i].state = PCB_DUP; - _mdns_announce_pcb(other_if, i, NULL, 0, true); + mdns_priv_pcb_announce(other_if, i, NULL, 0, true); } } } -bool mdns_responder_is_off(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +bool mdns_priv_pcb_is_off(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { return s_pcbs[tcpip_if][ip_protocol].state == PCB_OFF; } -void mdns_responder_process_tx_packet(mdns_tx_packet_t *p) +void mdns_priv_pcb_schedule_tx_packet(mdns_tx_packet_t *p) { mdns_pcb_t *pcb = &s_pcbs[p->tcpip_if][p->ip_protocol]; mdns_out_question_t *q = NULL; @@ -237,7 +246,7 @@ void mdns_responder_process_tx_packet(mdns_tx_packet_t *p) } } -void mdns_responder_check_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_service_t *service, bool removed_answers, bool *should_remove_questions) +void mdns_priv_pcb_check_probing_services(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_service_t *service, bool removed_answers, bool *should_remove_questions) { mdns_pcb_t *_pcb = &s_pcbs[tcpip_if][ip_protocol]; @@ -278,7 +287,7 @@ void mdns_responder_check_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol *should_remove_questions = false; } -void mdns_responder_deinit(void) +void mdns_priv_pcb_deinit(void) { for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { for (int j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { @@ -287,27 +296,27 @@ void mdns_responder_deinit(void) } } -bool mdsn_responder_iface_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +bool mdsn_priv_pcb_is_inited(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { return mdns_is_netif_ready(tcpip_if, ip_protocol) && s_pcbs[tcpip_if][ip_protocol].state > PCB_INIT; } -bool mdns_responder_is_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +bool mdns_priv_pcb_is_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { return s_pcbs[tcpip_if][ip_protocol].state == PCB_DUP; } -bool mdns_responder_is_probing(mdns_rx_packet_t *packet) +bool mdns_priv_pcb_is_probing(mdns_rx_packet_t *packet) { return s_pcbs[packet->tcpip_if][packet->ip_protocol].probe_running; } -bool mdns_responder_after_probing(mdns_rx_packet_t *packet) +bool mdns_priv_pcb_is_after_probing(mdns_rx_packet_t *packet) { return s_pcbs[packet->tcpip_if][packet->ip_protocol].state > PCB_PROBE_3; } -void mdns_responder_probe_failed(mdns_rx_packet_t *packet) +void mdns_priv_pcb_set_probe_failed(mdns_rx_packet_t *packet) { s_pcbs[packet->tcpip_if][packet->ip_protocol].failed_probes++; } @@ -414,7 +423,7 @@ void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, md /** * @brief Send by for particular services */ -void _mdns_send_bye(mdns_srv_item_t **services, size_t len, bool include_ip) +void mdns_responder_send_bye_service(mdns_srv_item_t **services, size_t len, bool include_ip) { uint8_t i, j; if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index 0485af98b8..465029069a 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -1311,7 +1311,8 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an else if (answer->type == MDNS_TYPE_A) { if (answer->host == mdns_utils_get_selfhost()) { esp_netif_ip_info_t if_ip_info; - if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && !mdns_responder_is_duplicate(tcpip_if, MDNS_IP_PROTOCOL_V4)) { + if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && !mdns_priv_pcb_is_duplicate(tcpip_if, + MDNS_IP_PROTOCOL_V4)) { return 0; } if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { @@ -1320,10 +1321,10 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an if (_mdns_append_a_record(packet, index, mdns_utils_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { return 0; } - if (!_mdns_if_is_dup(tcpip_if)) { + if (!mdns_priv_pcb_check_for_duplicates(tcpip_if)) { return 1; } - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &if_ip_info)) { return 1; } @@ -1341,7 +1342,8 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an if (answer->host == mdns_utils_get_selfhost()) { struct esp_ip6_addr if_ip6s[NETIF_IPV6_MAX_NUMS]; uint8_t count = 0; - if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && !mdns_responder_is_duplicate(tcpip_if, MDNS_IP_PROTOCOL_V6)) { + if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && !mdns_priv_pcb_is_duplicate(tcpip_if, + MDNS_IP_PROTOCOL_V6)) { return 0; } count = esp_netif_get_all_ip6(_mdns_get_esp_netif(tcpip_if), if_ip6s); @@ -1355,11 +1357,11 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an return 0; } } - if (!_mdns_if_is_dup(tcpip_if)) { + if (!mdns_priv_pcb_check_for_duplicates(tcpip_if)) { return count; } - mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); struct esp_ip6_addr other_ip6; if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &other_ip6)) { return count; @@ -1848,7 +1850,8 @@ void _mdns_remove_scheduled_service_packets(mdns_service_t *service) if (mdns_is_netif_ready(q->tcpip_if, q->ip_protocol)) { bool should_remove_questions = false; - mdns_responder_check_pcb(q->tcpip_if, q->ip_protocol, service, had_answers && q->answers == NULL, &should_remove_questions); + mdns_priv_pcb_check_probing_services(q->tcpip_if, q->ip_protocol, service, + had_answers && q->answers == NULL, &should_remove_questions); if (should_remove_questions && q->questions) { mdns_out_question_t *qsn = NULL; mdns_out_question_t *qs = q->questions; @@ -1882,12 +1885,12 @@ void _mdns_remove_scheduled_service_packets(mdns_service_t *service) static void _mdns_tx_handle_packet(mdns_tx_packet_t *p) { - if (mdns_responder_is_off(p->tcpip_if, p->ip_protocol)) { + if (mdns_priv_pcb_is_off(p->tcpip_if, p->ip_protocol)) { _mdns_free_tx_packet(p); return; } _mdns_dispatch_tx_packet(p); - mdns_responder_process_tx_packet(p); + mdns_priv_pcb_schedule_tx_packet(p); } static void mdns_send_handle_tx_packet(mdns_tx_packet_t *packet) diff --git a/components/mdns/mdns_utils.c b/components/mdns/mdns_utils.c index 255d9a4ba9..86e73e1a7e 100644 --- a/components/mdns/mdns_utils.c +++ b/components/mdns/mdns_utils.c @@ -11,7 +11,7 @@ static const char *MDNS_DEFAULT_DOMAIN = "local"; static const char *MDNS_SUB_STR = "_sub"; -//static const char *TAG = "mdns_utils"; +static const char *TAG = "mdns_utils"; /** * @brief reads MDNS FQDN into mdns_name_t structure @@ -287,3 +287,24 @@ bool mdns_utils_ipv6_address_is_zero(esp_ip6_addr_t ip6) return true; } #endif /* CONFIG_LWIP_IPV6 */ + + +/** + * @brief Create linked IP (copy) from parsed one + */ +mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip) +{ + mdns_ip_addr_t *a = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); + if (!a) { + HOOK_MALLOC_FAILED; + return NULL; + } + memset(a, 0, sizeof(mdns_ip_addr_t)); + a->addr.type = ip->type; + if (ip->type == ESP_IPADDR_TYPE_V6) { + memcpy(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16); + } else { + a->addr.u_addr.ip4.addr = ip->u_addr.ip4.addr; + } + return a; +} diff --git a/components/mdns/private_include/mdns_browser.h b/components/mdns/private_include/mdns_browser.h index aba3cb57d9..d76ab4e409 100644 --- a/components/mdns/private_include/mdns_browser.h +++ b/components/mdns/private_include/mdns_browser.h @@ -12,22 +12,60 @@ extern "C" { #endif +/** + * @brief Free browse item queue + * + * @note Called from mdns_free() + */ void mdns_browse_free(void); +/** + * @brief Looks for the name/type in active browse items + * + * @note Called from the packet parser (mdns_receive.c) + * + * @return browse results + */ mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +/** + * @brief Send out all browse queries + * + * @note Called from the network events (mdns_netif.c) + * @note Calls (indirectly) _mdns_search_send_pcb() from mdns_querier.c, which sends out the query + */ void mdns_browse_send_all(mdns_if_t mdns_if); +/** + * @brief Perform action from mdns service queue + * + * @note Called from the _mdns_service_task() in mdns.c + */ void mdns_browse_action(mdns_action_t *action, mdns_action_subtype_t type); -//esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r);; -void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, - mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl, mdns_browse_sync_t *out_sync_browse); -void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); -void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, - uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); + +/** + * @brief Add a TXT record to the browse result + * + * @note Called from the packet parser (mdns_receive.c) + */ +void mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, + mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +/** + * @brief Add an IP record to the browse result + * + * @note Called from the packet parser (mdns_receive.c) + */ +void mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +/** + * @brief Add a SRV record to the browse result + * + * @note Called from the packet parser (mdns_receive.c) + */ +void mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, + uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_debug.h b/components/mdns/private_include/mdns_debug.h index 1de04b24ed..496c61cde5 100644 --- a/components/mdns/private_include/mdns_debug.h +++ b/components/mdns/private_include/mdns_debug.h @@ -14,6 +14,8 @@ extern "C" { #ifdef CONFIG_MDNS_ENABLE_DEBUG_PRINTS +/* Define the debug macros for the mDNS module + */ #define DBG_BROWSE_RESULTS(result, browse) mdns_debug_printf_browse_result(result, browse) #define DBG_BROWSE_RESULTS_WITH_MSG(result, ...) do { \ @@ -25,13 +27,30 @@ extern "C" { #define DBG_RX_PACKET(packet, data, len) mdns_debug_rx_packet(packet, data, len) +/** + * @brief Print the browse results + */ void mdns_debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t); + +/** + * @brief Print all the browse results + */ void mdns_debug_printf_browse_result_all(mdns_result_t *r_t); + +/** + * @brief Print the tx packet + */ void mdns_debug_tx_packet(mdns_tx_packet_t *p, uint8_t packet[MDNS_MAX_PACKET_SIZE], uint16_t index); + +/** + * @brief Print the rx packet + */ void mdns_debug_rx_packet(mdns_rx_packet_t *packet, const uint8_t* data, uint16_t len); #else +/* Define the dummy debug macros if debugging is OFF + */ #define DBG_BROWSE_RESULTS(result, browse) #define DBG_BROWSE_RESULTS_WITH_MSG(result, ...) #define DBG_TX_PACKET(packet, data, len) diff --git a/components/mdns/private_include/mdns_netif.h b/components/mdns/private_include/mdns_netif.h index 9e1acfe3b1..770657a6e0 100644 --- a/components/mdns/private_include/mdns_netif.h +++ b/components/mdns/private_include/mdns_netif.h @@ -12,15 +12,41 @@ extern "C" { #endif -bool _mdns_if_is_dup(mdns_if_t tcpip_if); -void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -void _mdns_enable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if); +/** + * @brief Initialize the mDNS network interfaces + * + * @note Called from mdns_init() in mdns.c + */ esp_err_t mdns_netif_init(void); + +/** + * @brief Deinitialize the mDNS network interfaces + * + * @note Called from mdns_init() in mdns.c + */ esp_err_t mdns_netif_deinit(void); -void unregister_predefined_handlers(void); -void _mdns_dup_interface(mdns_if_t tcpip_if); -void _mdns_clean_netif_ptr(mdns_if_t tcpip_if); + +/** + * @brief Unregister predefined (default) network interfaces + * + * @note Called from mdns_free() in mdns.c + * + */ +void mdns_netif_unregister_predefined_handlers(void); + +/** + * @brief Clean the internal netif for the particular interface + * + * @note Called from mdns_responder on disabling pcbs + */ +void mdns_netif_disable(mdns_if_t tcpip_if); + +/** + * @brief Returns potentially duplicated interface + * + * @note Called from multiple places where Rx and Tx packets are processed + */ +mdns_if_t mdns_netif_get_other_interface(mdns_if_t tcpip_if); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 436afe49ea..90315f2a1e 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -341,15 +341,6 @@ typedef struct mdns_tx_packet_s { uint16_t id; } mdns_tx_packet_t; -typedef struct { - mdns_pcb_state_t state; - mdns_srv_item_t **probe_services; - uint8_t probe_services_len; - uint8_t probe_ip; - uint8_t probe_running; - uint16_t failed_probes; -} mdns_pcb_t; - typedef enum { SEARCH_OFF, SEARCH_INIT, diff --git a/components/mdns/private_include/mdns_querier.h b/components/mdns/private_include/mdns_querier.h index d08e0f08d2..891dad9973 100644 --- a/components/mdns/private_include/mdns_querier.h +++ b/components/mdns/private_include/mdns_querier.h @@ -12,26 +12,81 @@ extern "C" { #endif -void _mdns_search_run(void); -void mdns_search_free(void); -void _mdns_query_results_free(mdns_result_t *results); -void _mdns_search_finish_done(void); -mdns_search_once_t *_mdns_search_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); - -mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip); -void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, - size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl); -void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); -void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); -mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, - const char *service_type, const char *proto, mdns_if_t tcpip_if, - mdns_ip_protocol_t ip_protocol, uint32_t ttl); - -void mdns_query_action(mdns_action_t *action, mdns_action_subtype_t type); +/** + * @brief Start or stop requested queries + * @note Called periodically from timer task in mdns.c + */ +void mdns_priv_query_start_stop(void); + +/** + * @brief Free search item queue + * @note Called from mdns_free() + */ +void mdns_priv_query_free(void); + +/** + * @brief Free search results + * @note Called from multiple modules (browser, querier, core) + */ +void mdns_priv_query_results_free(mdns_result_t *results); + +/** + * @brief Complete the query if max results reached + * @note Called from the packet parser + */ +void mdns_priv_query_done(void); + +/** +* @brief Looks for the name/type in active search items +* +* @note Called from the packet parser (mdns_receive.c) +* +* @return search results +*/ +mdns_search_once_t *mdns_priv_query_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Looks for the name/type in the search items + * + * @note Called from the packet parser (mdns_receive.c) + */ +mdns_search_once_t *mdns_priv_query_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Add TXT item to the search results + * @note Called from the packet parser (mdns_receive.c) + */ +void mdns_priv_query_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, + size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl); +/** + * @brief Add IP (A/AAAA records) to the search results + * @note Called from the packet parser (mdns_receive.c) + */ +void mdns_priv_query_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); + +/** + * @brief Add SRV record to the search results + * @note Called from the packet parser (mdns_receive.c) + */ +void mdns_priv_query_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); + +/** + * @brief Add PTR record to the search results + * @note Called from the packet parser (mdns_receive.c) + */ +mdns_result_t *mdns_priv_query_result_add_ptr(mdns_search_once_t *search, const char *instance, + const char *service_type, const char *proto, mdns_if_t tcpip_if, + mdns_ip_protocol_t ip_protocol, uint32_t ttl); + +/** + * @brief Perform action from mdns service queue + * + * @note Called from the _mdns_service_task() in mdns.c + */ +void mdns_priv_query_action(mdns_action_t *action, mdns_action_subtype_t type); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_receive.h b/components/mdns/private_include/mdns_receive.h index 04e79d90f2..03cad700e3 100644 --- a/components/mdns/private_include/mdns_receive.h +++ b/components/mdns/private_include/mdns_receive.h @@ -12,7 +12,12 @@ extern "C" { #endif -void mdns_receive_action(mdns_action_t *action, mdns_action_subtype_t type); +/** +* @brief Perform action from mdns service queue +* +* @note Called from the _mdns_service_task() in mdns.c +*/ +void mdns_priv_receive_action(mdns_action_t *action, mdns_action_subtype_t type); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_responder.h b/components/mdns/private_include/mdns_responder.h index 1d5eb4e888..44a577a8bb 100644 --- a/components/mdns/private_include/mdns_responder.h +++ b/components/mdns/private_include/mdns_responder.h @@ -12,18 +12,96 @@ extern "C" { #endif -void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); -bool mdns_responder_is_off(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -void mdns_responder_process_tx_packet(mdns_tx_packet_t *p); -void mdns_responder_check_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_service_t *service, bool removed_answers, bool *should_remove_questions); -void mdns_responder_deinit(void); -bool mdsn_responder_iface_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -bool mdns_responder_is_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -bool mdns_responder_is_probing(mdns_rx_packet_t *packet); -void mdns_responder_probe_failed(mdns_rx_packet_t *packet); -bool mdns_responder_after_probing(mdns_rx_packet_t *packet); - -void _mdns_send_bye(mdns_srv_item_t **services, size_t len, bool include_ip); +/** + * @brief Disable the PCB for the selected interface and protocol + * @note Called from the main module (deinit and event handler) + */ +void mdns_priv_pcb_disable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Enable the PCB for the selected interface and protocol + * @note Called from the main module (deinit and event handler) + */ +void mdns_priv_pcb_enable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Set the interface as duplicate + * @note Called from the packet parser when checking for collisions + */ +void mdns_priv_pcb_set_duplicate(mdns_if_t tcpip_if); + +/** + * @brief Send announcement on particular PCB + * @note Called mainly from mdns.c to send announcements on all interfaces + */ +void mdns_priv_pcb_announce(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); + +/** + * @brief Checks if the PCB is OFF + * @note Called from mdns_send.c + */ +bool mdns_priv_pcb_is_off(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Schedules TX packets for various PCB states of probing and announcing + * @note Called from mdns_send.c + */ +void mdns_priv_pcb_schedule_tx_packet(mdns_tx_packet_t *p); + +/** + * @brief Update probing services on certain service removal + * @note Called from mdns_send.c upon removing scheduled packets for a service + */ +void mdns_priv_pcb_check_probing_services(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_service_t *service, bool removed_answers, bool *should_remove_questions); + +/** + * @brief Deinit pcbs + * @note Called from mdns_free() + */ +void mdns_priv_pcb_deinit(void); + +/** + * @brief Checks if the netif and PCB is initialized + * @note Called from mdns_send.c + */ +bool mdsn_priv_pcb_is_inited(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Checks if PCB is duplicated + * @note Called from mdns_send.c + */ +bool mdns_priv_pcb_is_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Checks if PCB is probing + * @note Called from mdns_receive.c + */ +bool mdns_priv_pcb_is_probing(mdns_rx_packet_t *packet); + +/** + * @brief Set probe failed to PCB + * @note Called from mdns_receive.c + */ +void mdns_priv_pcb_set_probe_failed(mdns_rx_packet_t *packet); + +/** + * @brief Checks if PCB completed probing + * @note Called from mdns_receive.c + */ +bool mdns_priv_pcb_is_after_probing(mdns_rx_packet_t *packet); + +/** + * @brief Checks if the selected interface has a duplicate + * @note Called from mdns_send.c + */ +bool mdns_priv_pcb_check_for_duplicates(mdns_if_t tcpip_if); + +/** + * @brief Sends bye for particular services on particular PCB + * @note Called from mdns.c + */ +void mdns_responder_send_bye_service(mdns_srv_item_t **services, size_t len, bool include_ip); + #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_utils.h b/components/mdns/private_include/mdns_utils.h index 3141a785bc..a220c4be5d 100644 --- a/components/mdns/private_include/mdns_utils.h +++ b/components/mdns/private_include/mdns_utils.h @@ -108,3 +108,4 @@ void mdns_service_lock(void); void mdns_service_unlock(void); bool mdns_action_queue(mdns_action_t *action); +mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip); From 28128a8656d09cec93096b3d9ddd0d3cc3606035 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 19 Mar 2025 10:48:44 +0100 Subject: [PATCH 09/27] feat(mdns): Add fuzzing job with AFL++ --- .github/workflows/mdns__host-tests.yml | 41 +++++++++++++++++++ components/mdns/mdns_receive.c | 10 +++-- components/mdns/mdns_utils.c | 4 +- .../mdns/tests/test_afl_fuzz_host/Makefile | 18 ++++++-- .../tests/test_afl_fuzz_host/esp32_mock.h | 5 +-- .../mdns/tests/test_afl_fuzz_host/test.c | 19 ++------- 6 files changed, 69 insertions(+), 28 deletions(-) diff --git a/.github/workflows/mdns__host-tests.yml b/.github/workflows/mdns__host-tests.yml index d26b68c9af..b0ad0a788a 100644 --- a/.github/workflows/mdns__host-tests.yml +++ b/.github/workflows/mdns__host-tests.yml @@ -68,3 +68,44 @@ jobs: diff -q $file /tmp/$file || exit 1 echo "OK" done + + + fuzz_test: + if: contains(github.event.pull_request.labels.*.name, 'mdns-fuzz') || github.event_name == 'push' + name: Fuzzer tests for mdns lib + strategy: + matrix: + idf_ver: ["latest"] + + runs-on: ubuntu-22.04 + container: aflplusplus/aflplusplus + steps: + - name: Checkout esp-protocols + uses: actions/checkout@v4 + + - name: Checkout ESP-IDF + uses: actions/checkout@v4 + with: + repository: espressif/esp-idf + path: idf + submodules: recursive + + - name: Install Necessary Libs + run: | + apt-get update -y + apt-get install -y libbsd-dev + + - name: Run AFL++ + shell: bash + run: | + export IDF_PATH=$GITHUB_WORKSPACE/idf + cd components/mdns/tests/test_afl_fuzz_host/ + make fuzz + + - name: Upload Crash Artifacts + if: failure() + uses: actions/upload-artifact@v4 + with: + name: fuzz-crashes + path: components/mdns/tests/test_afl_fuzz_host/out/default/crashes.tar.gz + if-no-files-found: ignore diff --git a/components/mdns/mdns_receive.c b/components/mdns/mdns_receive.c index d0c70a59a6..0230359132 100644 --- a/components/mdns/mdns_receive.c +++ b/components/mdns/mdns_receive.c @@ -273,7 +273,7 @@ static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_it memset(txt_value_len, 0, num_items); size_t txt_num = 0; - while (i < len) { + while (i < len && txt_num < num_items) { partLen = data[i++]; if (!partLen) { break; @@ -284,11 +284,11 @@ static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_it } int name_len = _mdns_txt_item_name_get_len(data + i, partLen); - if (name_len < 0) {//invalid item (no name) + if (name_len < 0) { //invalid item (no name) i += partLen; continue; } - char *key = (char *)mdns_mem_malloc(name_len + 1); + char *key = (char *) mdns_mem_malloc(name_len + 1); if (!key) { HOOK_MALLOC_FAILED; goto handle_error;//error @@ -305,7 +305,7 @@ static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_it int new_value_len = partLen - name_len - 1; if (new_value_len > 0) { - char *value = (char *)mdns_mem_malloc(new_value_len + 1); + char *value = (char *) mdns_mem_malloc(new_value_len + 1); if (!value) { HOOK_MALLOC_FAILED; goto handle_error;//error @@ -315,6 +315,8 @@ static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_it *value_len = new_value_len; i += new_value_len; t->value = value; + } else { + t->value = NULL; } } diff --git a/components/mdns/mdns_utils.c b/components/mdns/mdns_utils.c index 86e73e1a7e..46d12d1de8 100644 --- a/components/mdns/mdns_utils.c +++ b/components/mdns/mdns_utils.c @@ -202,12 +202,12 @@ bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instanc const char *_mdns_get_default_instance_name(void) { const char* instance = mdns_utils_get_instance(); - if (mdns_utils_str_null_or_empty(instance)) { + if (!mdns_utils_str_null_or_empty(instance)) { return instance; } const char* host = mdns_utils_get_global_hostname(); - if (mdns_utils_str_null_or_empty(host)) { + if (!mdns_utils_str_null_or_empty(host)) { return host; } return NULL; diff --git a/components/mdns/tests/test_afl_fuzz_host/Makefile b/components/mdns/tests/test_afl_fuzz_host/Makefile index a247f61cee..aa30b09f5c 100644 --- a/components/mdns/tests/test_afl_fuzz_host/Makefile +++ b/components/mdns/tests/test_afl_fuzz_host/Makefile @@ -1,7 +1,8 @@ TEST_NAME=test FUZZ=afl-fuzz COMPONENTS_DIR=$(IDF_PATH)/components -COMPILER_ICLUDE_DIR=$(shell echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf) +# Use ESP32 toolchain include path if available, otherwise fall back to system includes for host-based compilation +COMPILER_INCLUDE_DIR=$(shell if command -v xtensa-esp32-elf-gcc >/dev/null 2>&1; then echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf; else echo /usr; fi) CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversion -Wno-macro-redefined -Wno-int-to-void-pointer-cast -DHOOK_MALLOC_FAILED -DESP_EVENT_H_ -D__ESP_LOG_H__ \ -I. -I../.. -I../../include -I../../private_include -I ./build/config \ @@ -34,7 +35,7 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi -I$(COMPONENTS_DIR)/soc/src/esp32/include \ -I$(COMPONENTS_DIR)/xtensa/include \ -I$(COMPONENTS_DIR)/xtensa/esp32/include \ - -I$(COMPILER_ICLUDE_DIR)/include + -I$(COMPILER_INCLUDE_DIR)/include MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h @@ -85,7 +86,18 @@ $(TEST_NAME): $(OBJECTS) @$(LD) $(OBJECTS) -o $@ $(LDLIBS) fuzz: $(TEST_NAME) - @$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) + # timeout returns 124 if time limit is reached, original return code otherwise + # pass only if: fuzzing was running smoothly until timeout AND no crash found + @timeout 10m $(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) || \ + if [ $$? -eq 124 ]; then \ + if [ -n "$$(find out/default/crashes -type f 2>/dev/null)" ]; then \ + echo "Crashes found!"; \ + tar -czf out/default/crashes.tar.gz -C out/default crashes; \ + exit 1; \ + fi \ + else \ + exit 1; \ + fi clean: @rm -rf *.o *.SYM $(TEST_NAME) out diff --git a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h index a8193625ad..70a2037ffa 100644 --- a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h @@ -55,8 +55,7 @@ #define pdMS_TO_TICKS(a) a #define xSemaphoreTake(s,d) true -#define xTaskDelete(a) -#define vTaskDelete(a) free(a) +#define vTaskDelete(a) free(NULL) #define xSemaphoreGive(s) #define xQueueCreateMutex(s) #define _mdns_pcb_init(a,b) true @@ -66,7 +65,7 @@ #define vSemaphoreDelete(s) free(s) #define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U #define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1) -#define xTaskCreateStaticPinnedToCore(a,b,c,d,e,f,g,h) true +#define xTaskCreateStaticPinnedToCore(a,b,c,d,e,f,g,h) ((void*)1) #define vTaskDelay(m) usleep((m)*0) #define esp_random() (rand()%UINT32_MAX) diff --git a/components/mdns/tests/test_afl_fuzz_host/test.c b/components/mdns/tests/test_afl_fuzz_host/test.c index f649f562b6..50c78de83a 100644 --- a/components/mdns/tests/test_afl_fuzz_host/test.c +++ b/components/mdns/tests/test_afl_fuzz_host/test.c @@ -81,30 +81,20 @@ static int mdns_test_service_txt_set(const char *service, const char *proto, ui static int mdns_test_sub_service_add(const char *sub_name, const char *service_name, const char *proto, uint32_t port) { if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { - // This is expected failure as the service thread is not running + return ESP_FAIL; } - mdns_action_t *a = NULL; - GetLastItem(&a); - mdns_test_execute_action(a); if (_mdns_get_service_item(service_name, proto, NULL) == NULL) { return ESP_FAIL; } - int ret = mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name); - a = NULL; - GetLastItem(&a); - mdns_test_execute_action(a); - return ret; + return mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name); } static int mdns_test_service_add(const char *service_name, const char *proto, uint32_t port) { if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { - // This is expected failure as the service thread is not running + return ESP_FAIL; } - mdns_action_t *a = NULL; - GetLastItem(&a); - mdns_test_execute_action(a); if (_mdns_get_service_item(service_name, proto, NULL) == NULL) { return ESP_FAIL; @@ -270,9 +260,6 @@ int main(int argc, char **argv) } #ifndef MDNS_NO_SERVICES mdns_service_remove_all(); - mdns_action_t *a = NULL; - GetLastItem(&a); - mdns_test_execute_action(a); #endif ForceTaskDelete(); mdns_free(); From 3e5946a682d83b3479cc2733ca11acb0c0608cbe Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 21 Mar 2025 15:42:01 +0100 Subject: [PATCH 10/27] fix(mdns): Rename and cleanup --- components/mdns/mdns.c | 106 ++++++------ components/mdns/mdns_browser.c | 29 ++-- components/mdns/mdns_debug.c | 10 +- components/mdns/mdns_netif.c | 38 ++--- components/mdns/mdns_networking_lwip.c | 6 +- components/mdns/mdns_networking_socket.c | 5 +- components/mdns/mdns_querier.c | 74 +++++---- components/mdns/mdns_receive.c | 130 +++++++-------- components/mdns/mdns_responder.c | 44 ++--- components/mdns/mdns_send.c | 154 ++++++++---------- components/mdns/mdns_utils.c | 120 ++++---------- components/mdns/private_include/mdns_netif.h | 13 ++ .../mdns/private_include/mdns_private.h | 76 ++++++++- .../mdns/private_include/mdns_querier.h | 14 ++ .../mdns/private_include/mdns_responder.h | 15 ++ components/mdns/private_include/mdns_send.h | 96 +++++++++++ components/mdns/private_include/mdns_utils.h | 143 +++++++++------- 17 files changed, 603 insertions(+), 470 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 4d9df9c01c..235b2a840f 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -37,27 +37,27 @@ static StackType_t *_mdns_stack_buffer; esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); -const char *mdns_utils_get_global_hostname(void) +const char *mdns_priv_get_global_hostname(void) { return _mdns_server ? _mdns_server->hostname : NULL; } -mdns_srv_item_t *mdns_utils_get_services(void) +mdns_srv_item_t *mdns_priv_get_services(void) { return _mdns_server->services; } -mdns_host_item_t *mdns_utils_get_hosts(void) +mdns_host_item_t *mdns_priv_get_hosts(void) { return _mdns_host_list; } -mdns_host_item_t *mdns_utils_get_selfhost(void) +mdns_host_item_t *priv_get_self_host(void) { return &_mdns_self_host; } -void mdns_utils_set_global_hostname(const char *hostname) +void mdns_priv_set_global_hostname(const char *hostname) { if (_mdns_server) { if (_mdns_server->hostname) { @@ -68,12 +68,12 @@ void mdns_utils_set_global_hostname(const char *hostname) } } -const char *mdns_utils_get_instance(void) +const char *mdns_priv_get_instance(void) { return _mdns_server ? _mdns_server->instance : NULL; } -void mdns_utils_set_instance(const char *instance) +void mdns_priv_set_instance(const char *instance) { if (_mdns_server) { if (_mdns_server->instance) { @@ -83,7 +83,7 @@ void mdns_utils_set_instance(const char *instance) } } -bool is_mdns_server(void) +bool mdns_priv_is_server_init(void) { return _mdns_server != NULL; } @@ -111,7 +111,7 @@ static bool _mdns_can_add_more_services(void) #endif } -bool mdns_action_queue(mdns_action_t *action) +bool mdns_priv_queue_action(mdns_action_t *action) { if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { return false; @@ -185,10 +185,7 @@ static void _mdns_send_bye_all_pcbs_no_instance(bool include_ip) mdns_responder_send_bye_service(services, srv_count, include_ip); } -/** - * @brief Restart the responder on all services without instance - */ -void _mdns_restart_all_pcbs_no_instance(void) +void mdns_priv_restart_all_pcbs_no_instance(void) { size_t srv_count = 0; mdns_srv_item_t *a = _mdns_server->services; @@ -210,13 +207,10 @@ void _mdns_restart_all_pcbs_no_instance(void) } a = a->next; } - _mdns_probe_all_pcbs(services, srv_count, false, true); + mdns_responder_probe_all_pcbs(services, srv_count, false, true); } -/** - * @brief Restart the responder on all active PCBs - */ -void _mdns_restart_all_pcbs(void) +void mdns_priv_restart_all_pcbs(void) { _mdns_clear_tx_queue_head(); size_t srv_count = 0; @@ -226,7 +220,7 @@ void _mdns_restart_all_pcbs(void) a = a->next; } if (srv_count == 0) { - _mdns_probe_all_pcbs(NULL, 0, true, true); + mdns_responder_probe_all_pcbs(NULL, 0, true, true); return; } mdns_srv_item_t *services[srv_count]; @@ -237,7 +231,7 @@ void _mdns_restart_all_pcbs(void) a = a->next; } - _mdns_probe_all_pcbs(services, srv_count, true, true); + mdns_responder_probe_all_pcbs(services, srv_count, true, true); } @@ -410,7 +404,7 @@ static void _mdns_free_service(mdns_service_t *service) */ static bool _mdns_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *address_list) { - if (_hostname_is_ours(hostname)) { + if (mdns_utils_hostname_is_ours(hostname)) { return false; } @@ -438,7 +432,7 @@ static bool _mdns_delegate_hostname_set_address(const char *hostname, mdns_ip_ad while (host != NULL) { if (strcasecmp(hostname, host->hostname) == 0) { // free previous address list - free_address_list(host->address_list); + mdns_utils_free_address_list(host->address_list); // set current address list to the host host->address_list = address_list; return true; @@ -454,7 +448,7 @@ static void free_delegated_hostnames(void) { mdns_host_item_t *host = _mdns_host_list; while (host != NULL) { - free_address_list(host->address_list); + mdns_utils_free_address_list(host->address_list); mdns_mem_free((char *)host->hostname); mdns_host_item_t *item = host; host = host->next; @@ -495,7 +489,7 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) } else { prev_host->next = host->next; } - free_address_list(host->address_list); + mdns_utils_free_address_list(host->address_list); mdns_mem_free((char *)host->hostname); mdns_mem_free(host); break; @@ -545,7 +539,7 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) #ifdef CONFIG_LWIP_IPV4 if (action & MDNS_EVENT_IP4_REVERSE_LOOKUP) { esp_netif_ip_info_t if_ip_info; - if (esp_netif_get_ip_info(_mdns_get_esp_netif(mdns_if), &if_ip_info) == ESP_OK) { + if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(mdns_if), &if_ip_info) == ESP_OK) { esp_ip4_addr_t *ip = &if_ip_info.ip; char *reverse_query_name = NULL; if (asprintf(&reverse_query_name, "%d.%d.%d.%d.in-addr", @@ -560,7 +554,7 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) #ifdef CONFIG_LWIP_IPV6 if (action & MDNS_EVENT_IP6_REVERSE_LOOKUP) { esp_ip6_addr_t addr6; - if (!esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(mdns_if), &addr6) && !mdns_utils_ipv6_address_is_zero(addr6)) { + if (!esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(mdns_if), &addr6) && !mdns_utils_ipv6_address_is_zero(addr6)) { uint8_t *paddr = (uint8_t *)&addr6.addr; const char sub[] = "ip6"; const size_t query_name_size = 4 * sizeof(addr6.addr) /* (2 nibbles + 2 dots)/per byte of IP address */ + sizeof(sub); @@ -585,7 +579,7 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) #endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ } -void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) +void mdns_priv_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) { mdns_srv_item_t *service = _mdns_server->services; @@ -630,7 +624,7 @@ static void _mdns_free_action(mdns_action_t *action) case ACTION_DELEGATE_HOSTNAME_SET_ADDR: case ACTION_DELEGATE_HOSTNAME_ADD: mdns_mem_free((char *)action->data.delegate_hostname.hostname); - free_address_list(action->data.delegate_hostname.address_list); + mdns_utils_free_address_list(action->data.delegate_hostname.address_list); break; case ACTION_DELEGATE_HOSTNAME_REMOVE: mdns_mem_free((char *)action->data.delegate_hostname.hostname); @@ -652,18 +646,18 @@ static void _mdns_execute_action(mdns_action_t *action) break; case ACTION_HOSTNAME_SET: _mdns_send_bye_all_pcbs_no_instance(true); - _mdns_remap_self_service_hostname(_mdns_server->hostname, action->data.hostname_set.hostname); + mdns_priv_remap_self_service_hostname(_mdns_server->hostname, action->data.hostname_set.hostname); mdns_mem_free((char *)_mdns_server->hostname); _mdns_server->hostname = action->data.hostname_set.hostname; _mdns_self_host.hostname = action->data.hostname_set.hostname; - _mdns_restart_all_pcbs(); + mdns_priv_restart_all_pcbs(); xSemaphoreGive(_mdns_server->action_sema); break; case ACTION_INSTANCE_SET: _mdns_send_bye_all_pcbs_no_instance(false); mdns_mem_free((char *)_mdns_server->instance); _mdns_server->instance = action->data.instance; - _mdns_restart_all_pcbs_no_instance(); + mdns_priv_restart_all_pcbs_no_instance(); break; case ACTION_SEARCH_ADD: @@ -687,14 +681,14 @@ static void _mdns_execute_action(mdns_action_t *action) if (!_mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, action->data.delegate_hostname.address_list)) { mdns_mem_free((char *)action->data.delegate_hostname.hostname); - free_address_list(action->data.delegate_hostname.address_list); + mdns_utils_free_address_list(action->data.delegate_hostname.address_list); } xSemaphoreGive(_mdns_server->action_sema); break; case ACTION_DELEGATE_HOSTNAME_SET_ADDR: if (!_mdns_delegate_hostname_set_address(action->data.delegate_hostname.hostname, action->data.delegate_hostname.address_list)) { - free_address_list(action->data.delegate_hostname.address_list); + mdns_utils_free_address_list(action->data.delegate_hostname.address_list); } mdns_mem_free((char *)action->data.delegate_hostname.hostname); break; @@ -850,12 +844,12 @@ static esp_err_t _mdns_service_task_stop(void) return ESP_OK; } -void mdns_service_lock(void) +void mdns_priv_service_lock(void) { MDNS_SERVICE_LOCK(); } -void mdns_service_unlock(void) +void mdns_priv_service_unlock(void) { MDNS_SERVICE_UNLOCK(); } @@ -1014,7 +1008,7 @@ esp_err_t mdns_delegate_hostname_add(const char *hostname, const mdns_ip_addr_t } action->type = ACTION_DELEGATE_HOSTNAME_ADD; action->data.delegate_hostname.hostname = new_hostname; - action->data.delegate_hostname.address_list = copy_address_list(address_list); + action->data.delegate_hostname.address_list = mdns_utils_copy_address_list(address_list); if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { mdns_mem_free(new_hostname); mdns_mem_free(action); @@ -1074,7 +1068,7 @@ esp_err_t mdns_delegate_hostname_set_address(const char *hostname, const mdns_ip } action->type = ACTION_DELEGATE_HOSTNAME_SET_ADDR; action->data.delegate_hostname.hostname = new_hostname; - action->data.delegate_hostname.address_list = copy_address_list(address_list); + action->data.delegate_hostname.address_list = mdns_utils_copy_address_list(address_list); if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { mdns_mem_free(new_hostname); mdns_mem_free(action); @@ -1087,7 +1081,7 @@ bool mdns_hostname_exists(const char *hostname) { bool ret = false; MDNS_SERVICE_LOCK(); - ret = _hostname_is_ours(hostname); + ret = mdns_utils_hostname_is_ours(hostname); MDNS_SERVICE_UNLOCK(); return ret; } @@ -1140,7 +1134,7 @@ esp_err_t mdns_service_add_for_host(const char *instance, const char *service, c ESP_GOTO_ON_FALSE(_mdns_can_add_more_services(), ESP_ERR_NO_MEM, err, TAG, "Cannot add more services, please increase CONFIG_MDNS_MAX_SERVICES (%d)", CONFIG_MDNS_MAX_SERVICES); - mdns_srv_item_t *item = _mdns_get_service_item_instance(instance, service, proto, hostname); + mdns_srv_item_t *item = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(!item, ESP_ERR_INVALID_ARG, err, TAG, "Service already exists"); s = _mdns_create_service(service, proto, hostname, port, instance, num_items, txt); @@ -1154,7 +1148,7 @@ esp_err_t mdns_service_add_for_host(const char *instance, const char *service, c item->next = _mdns_server->services; _mdns_server->services = item; - _mdns_probe_all_pcbs(&item, 1, false, false); + mdns_responder_probe_all_pcbs(&item, 1, false, false); MDNS_SERVICE_UNLOCK(); return ESP_OK; @@ -1180,7 +1174,7 @@ bool mdns_service_exists(const char *service_type, const char *proto, const char { bool ret = false; MDNS_SERVICE_LOCK(); - ret = _mdns_get_service_item(service_type, proto, hostname) != NULL; + ret = mdns_utils_get_service_item(service_type, proto, hostname) != NULL; MDNS_SERVICE_UNLOCK(); return ret; } @@ -1190,7 +1184,7 @@ bool mdns_service_exists_with_instance(const char *instance, const char *service { bool ret = false; MDNS_SERVICE_LOCK(); - ret = _mdns_get_service_item_instance(instance, service_type, proto, hostname) != NULL; + ret = mdns_utils_get_service_item_instance(instance, service_type, proto, hostname) != NULL; MDNS_SERVICE_UNLOCK(); return ret; } @@ -1253,7 +1247,7 @@ static mdns_ip_addr_t *_copy_delegated_host_address_list(char *hostname) mdns_host_item_t *host = _mdns_host_list; while (host) { if (strcasecmp(host->hostname, hostname) == 0) { - return copy_address_list(host->address_list); + return mdns_utils_copy_address_list(host->address_list); } host = host->next; } @@ -1278,7 +1272,7 @@ static mdns_result_t *_mdns_lookup_service(const char *instance, const char *ser bool is_service_delegated = _str_null_or_empty(_mdns_server->hostname) || strcasecmp(_mdns_server->hostname, srv->hostname); if ((selfhost && is_service_selfhosted) || (!selfhost && is_service_delegated)) { if (!strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && - (_str_null_or_empty(instance) || _mdns_instance_name_match(srv->instance, instance))) { + (_str_null_or_empty(instance) || mdns_utils_instance_name_match(srv->instance, instance))) { mdns_result_t *item = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); if (!item) { HOOK_MALLOC_FAILED; @@ -1347,7 +1341,7 @@ esp_err_t mdns_service_port_set_for_host(const char *instance, const char *servi const char *hostname = host ? host : _mdns_server->hostname; ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && port, ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); - mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); + mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); s->service->port = port; @@ -1374,7 +1368,7 @@ esp_err_t mdns_service_txt_set_for_host(const char *instance, const char *servic const char *hostname = host ? host : _mdns_server->hostname; ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !(num_items && txt_items == NULL), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); - mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); + mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); mdns_txt_linked_item_t *new_txt = NULL; @@ -1415,7 +1409,7 @@ esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(key) && !((!value_arg && value_len)), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); - mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); + mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); mdns_service_t *srv = s->service; @@ -1495,7 +1489,7 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(key), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); - mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); + mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); mdns_service_t *srv = s->service; @@ -1578,7 +1572,7 @@ esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(subtype), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); - mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_name, service, proto, hostname); + mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_name, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); ret = _mdns_service_subtype_remove_for_host(s, subtype); @@ -1636,7 +1630,7 @@ esp_err_t mdns_service_subtype_add_multiple_items_for_host(const char *instance_ ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && (num_items > 0), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); - mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_name, service, proto, hostname); + mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_name, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); for (; cur_index < num_items; cur_index++) { @@ -1731,7 +1725,7 @@ esp_err_t mdns_service_subtype_update_multiple_items_for_host(const char *instan ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service_type) && !_str_null_or_empty(proto), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); - mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_name, service_type, proto, hostname); + mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_name, service_type, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); mdns_subtype_t *goodbye_subtype = _mdns_service_find_subtype_needed_sendbye(s->service, subtype, num_items); @@ -1779,7 +1773,7 @@ esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, cons ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(instance) && strlen(instance) <= (MDNS_NAME_BUF_LEN - 1), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); - mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_old, service, proto, hostname); + mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_old, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); if (s->service->instance) { @@ -1788,7 +1782,7 @@ esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, cons } s->service->instance = mdns_mem_strndup(instance, MDNS_NAME_BUF_LEN - 1); ESP_GOTO_ON_FALSE(s->service->instance, ESP_ERR_NO_MEM, err, TAG, "Out of memory"); - _mdns_probe_all_pcbs(&s, 1, false, false); + mdns_responder_probe_all_pcbs(&s, 1, false, false); err: MDNS_SERVICE_UNLOCK(); @@ -1810,14 +1804,14 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service const char *hostname = host ? host : _mdns_server->hostname; ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); - mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); + mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); mdns_srv_item_t *a = _mdns_server->services; mdns_srv_item_t *b = a; if (instance) { while (a) { - if (_mdns_service_match_instance(a->service, instance, service, proto, hostname)) { + if (mdns_utils_service_match_instance(a->service, instance, service, proto, hostname)) { if (_mdns_server->services != a) { b->next = a->next; } else { @@ -1834,7 +1828,7 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service } } else { while (a) { - if (_mdns_service_match(a->service, service, proto, hostname)) { + if (mdns_utils_service_match(a->service, service, proto, hostname)) { if (_mdns_server->services != a) { b->next = a->next; } else { diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index 69583fb074..03fa753a7d 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -11,6 +11,7 @@ #include "mdns_debug.h" #include "mdns_utils.h" #include "mdns_querier.h" +#include "mdns_netif.h" #include "esp_log.h" static const char *TAG = "mdns_browser"; @@ -33,7 +34,7 @@ static esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t action->type = type; action->data.browse_add.browse = browse; - if (!mdns_action_queue(action)) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(action); return ESP_ERR_NO_MEM; } @@ -170,7 +171,7 @@ mdns_browse_t *mdns_browse_new(const char *service, const char *proto, mdns_brow { mdns_browse_t *browse = NULL; - if (is_mdns_server() || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + if (mdns_priv_is_server_init() || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { return NULL; } @@ -191,7 +192,7 @@ esp_err_t mdns_browse_delete(const char *service, const char *proto) { mdns_browse_t *browse = NULL; - if (!is_mdns_server() || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + if (!mdns_priv_is_server_init() || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { return ESP_FAIL; } @@ -258,7 +259,7 @@ mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcp } else if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { r = b->result; while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { + if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { return b; } r = r->next; @@ -366,7 +367,7 @@ void mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ while (r) { if (r->ip_protocol == ip_protocol) { // Find the target result in browse result. - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { r_a = r->addr; // Check if the address has already added in result. while (r_a) { @@ -385,7 +386,7 @@ void mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ if (!r_a) { // The current IP is a new one, add it to the link list. mdns_ip_addr_t *a = NULL; - a = _mdns_result_addr_create_ip(ip); + a = mdns_priv_result_addr_create_ip(ip); if (!a) { return; } @@ -395,7 +396,7 @@ void mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ if (r->ttl == 0) { r->ttl = ttl; } else { - _mdns_result_update_ttl(r, ttl); + mdns_priv_query_update_result_ttl(r, ttl); } } if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { @@ -441,7 +442,7 @@ void mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, con } mdns_result_t *r = browse->result; while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && + if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && !mdns_utils_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && !mdns_utils_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { @@ -474,7 +475,7 @@ void mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, con if (r->ttl == 0) { r->ttl = ttl; } else { - _mdns_result_update_ttl(r, ttl); + mdns_priv_query_update_result_ttl(r, ttl); } if (previous_ttl != r->ttl) { should_update = true; @@ -508,7 +509,7 @@ void mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, con r->txt = txt; r->txt_value_len = txt_value_len; r->txt_count = txt_count; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = browse->result; @@ -532,7 +533,7 @@ static esp_err_t _mdns_copy_address_in_previous_result(mdns_result_t *result_lis if (!mdns_utils_str_null_or_empty(result_list->hostname) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(result_list->hostname, r->hostname) && result_list->ip_protocol == r->ip_protocol && result_list->addr && !r->addr) { // If there is a same hostname in previous result, we need to copy the address here. - r->addr = copy_address_list(result_list->addr); + r->addr = mdns_utils_copy_address_list(result_list->addr); if (!r->addr) { return ESP_ERR_NO_MEM; } @@ -559,7 +560,7 @@ void mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, con } mdns_result_t *r = browse->result; while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && + if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && !mdns_utils_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && !mdns_utils_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { @@ -585,7 +586,7 @@ void mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, con if (r->ttl == 0) { r->ttl = ttl; } else { - _mdns_result_update_ttl(r, ttl); + mdns_priv_query_update_result_ttl(r, ttl); } if (previous_ttl != r->ttl) { if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { @@ -618,7 +619,7 @@ void mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, con return; } r->port = port; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = browse->result; diff --git a/components/mdns/mdns_debug.c b/components/mdns/mdns_debug.c index 04c96ea84e..6a485a41fb 100644 --- a/components/mdns/mdns_debug.c +++ b/components/mdns/mdns_debug.c @@ -45,7 +45,7 @@ void static dbg_packet(const uint8_t *data, size_t len) uint8_t qs = header.questions; while (qs--) { - content = _mdns_parse_fqdn(data, content, name, len); + content = mdns_utils_parse_fqdn(data, content, name, len); if (!content || content + MDNS_CLASS_OFFSET + 1 >= data + len) { header.answers = 0; header.additional = 0; @@ -96,7 +96,7 @@ void static dbg_packet(const uint8_t *data, size_t len) while (content < (data + len)) { - content = _mdns_parse_fqdn(data, content, name, len); + content = mdns_utils_parse_fqdn(data, content, name, len); if (!content) { dbg_printf("ERROR: parse mdns records\n"); break; @@ -164,13 +164,13 @@ void static dbg_packet(const uint8_t *data, size_t len) dbg_printf("%" PRIu32, ttl); dbg_printf("[%u] ", data_len); if (type == MDNS_TYPE_PTR) { - if (!_mdns_parse_fqdn(data, data_ptr, name, len)) { + if (!mdns_utils_parse_fqdn(data, data_ptr, name, len)) { dbg_printf("ERROR: parse PTR\n"); continue; } dbg_printf("%s.%s.%s.%s.\n", name->host, name->service, name->proto, name->domain); } else if (type == MDNS_TYPE_SRV) { - if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { + if (!mdns_utils_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { dbg_printf("ERROR: parse SRV\n"); continue; } @@ -208,7 +208,7 @@ void static dbg_packet(const uint8_t *data, size_t len) dbg_printf(IPSTR "\n", IP2STR(&ip)); } else if (type == MDNS_TYPE_NSEC) { const uint8_t *old_ptr = data_ptr; - const uint8_t *new_ptr = _mdns_parse_fqdn(data, data_ptr, name, len); + const uint8_t *new_ptr = mdns_utils_parse_fqdn(data, data_ptr, name, len); if (new_ptr) { dbg_printf("%s.%s.%s.%s. ", name->host, name->service, name->proto, name->domain); size_t diff = new_ptr - old_ptr; diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c index 7f5b2af4f0..13c1cef6d3 100644 --- a/components/mdns/mdns_netif.c +++ b/components/mdns/mdns_netif.c @@ -117,19 +117,7 @@ static inline esp_netif_t *esp_netif_from_preset_if(mdns_predef_if_t predef_if) } } -/** - * @brief Gets the actual esp_netif pointer from the internal network interface list - * - * The supplied ordinal number could - * - point to a predef netif -> "STA", "AP", "ETH" - * - if no entry in the list (NULL) -> check if the system added this netif - * - point to a custom netif -> just return the entry in the list - * - users is responsible for the lifetime of this netif (to be valid between mdns-init -> deinit) - * - * @param tcpip_if Ordinal number of the interface - * @return Pointer ot the esp_netif object if the interface is available, NULL otherwise - */ -esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) +esp_netif_t *mdns_netif_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) { @@ -174,7 +162,7 @@ static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *esp_netif) static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action) { - if (!is_mdns_server() || mdns_if >= MDNS_MAX_INTERFACES) { + if (!mdns_priv_is_server_init() || mdns_if >= MDNS_MAX_INTERFACES) { return ESP_ERR_INVALID_STATE; } @@ -187,7 +175,7 @@ static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_ action->data.sys_event.event_action = event_action; action->data.sys_event.interface = mdns_if; - if (!mdns_action_queue(action)) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(action); } return ESP_OK; @@ -216,7 +204,7 @@ static inline void post_mdns_announce_pcb(mdns_predef_if_t preset_if, mdns_ip_pr void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { - if (!is_mdns_server()) { + if (!mdns_priv_is_server_init()) { return; } @@ -339,15 +327,15 @@ esp_err_t mdns_netif_action(esp_netif_t *esp_netif, mdns_event_actions_t event_a esp_err_t mdns_register_netif(esp_netif_t *esp_netif) { - if (!is_mdns_server()) { + if (!mdns_priv_is_server_init()) { return ESP_ERR_INVALID_STATE; } esp_err_t err = ESP_ERR_NO_MEM; - mdns_service_lock(); + mdns_priv_service_lock(); for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; ++i) { if (s_esp_netifs[i].netif == esp_netif) { - mdns_service_unlock(); + mdns_priv_service_unlock(); return ESP_ERR_INVALID_STATE; } } @@ -359,18 +347,18 @@ esp_err_t mdns_register_netif(esp_netif_t *esp_netif) break; } } - mdns_service_unlock(); + mdns_priv_service_unlock(); return err; } esp_err_t mdns_unregister_netif(esp_netif_t *esp_netif) { - if (!is_mdns_server()) { + if (!mdns_priv_is_server_init()) { return ESP_ERR_INVALID_STATE; } esp_err_t err = ESP_ERR_NOT_FOUND; - mdns_service_lock(); + 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; @@ -378,7 +366,7 @@ esp_err_t mdns_unregister_netif(esp_netif_t *esp_netif) break; } } - mdns_service_lock(); + mdns_priv_service_lock(); return err; } @@ -419,12 +407,12 @@ esp_err_t mdns_netif_init(void) for (i = 0; i < MDNS_MAX_INTERFACES; i++) { #ifdef CONFIG_LWIP_IPV6 - if (!esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(i), &tmp_addr6) && !mdns_utils_ipv6_address_is_zero(tmp_addr6)) { + if (!esp_netif_get_ip6_linklocal(mdns_netif_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_get_esp_netif(i), &if_ip_info) && if_ip_info.ip.addr) { + if (!esp_netif_get_ip_info(mdns_netif_get_esp_netif(i), &if_ip_info) && if_ip_info.ip.addr) { mdns_priv_pcb_enable(i, MDNS_IP_PROTOCOL_V4); } #endif diff --git a/components/mdns/mdns_networking_lwip.c b/components/mdns/mdns_networking_lwip.c index 957356b58c..4c9085878f 100644 --- a/components/mdns/mdns_networking_lwip.c +++ b/components/mdns/mdns_networking_lwip.c @@ -107,7 +107,7 @@ static void _udp_pcb_main_deinit(void) static esp_err_t _udp_join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protocol, bool join) { struct netif *netif = NULL; - esp_netif_t *tcpip_if = _mdns_get_esp_netif(if_inx); + esp_netif_t *tcpip_if = mdns_netif_get_esp_netif(if_inx); if (!esp_netif_is_netif_up(tcpip_if)) { // Network interface went down before event propagated, skipping IGMP config @@ -208,7 +208,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip struct netif *netif = NULL; bool found = false; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { - netif = esp_netif_get_netif_impl(_mdns_get_esp_netif(i)); + netif = esp_netif_get_netif_impl(mdns_netif_get_esp_netif(i)); if (s_interfaces[i].proto && netif && netif == ip_current_input_netif()) { #if LWIP_IPV4 if (packet->src.type == IPADDR_TYPE_V4) { @@ -353,7 +353,7 @@ static err_t _mdns_udp_pcb_write_api(struct tcpip_api_call_data *api_call_msg) { void *nif = NULL; mdns_api_call_t *msg = (mdns_api_call_t *)api_call_msg; - nif = esp_netif_get_netif_impl(_mdns_get_esp_netif(msg->tcpip_if)); + nif = esp_netif_get_netif_impl(mdns_netif_get_esp_netif(msg->tcpip_if)); if (!nif || !mdns_is_netif_ready(msg->tcpip_if, msg->ip_protocol) || _pcb_main == NULL) { pbuf_free(msg->pbt); msg->err = ERR_IF; diff --git a/components/mdns/mdns_networking_socket.c b/components/mdns/mdns_networking_socket.c index 008caedd6c..6d967d8025 100644 --- a/components/mdns/mdns_networking_socket.c +++ b/components/mdns/mdns_networking_socket.c @@ -23,6 +23,7 @@ #include "esp_log.h" #include "mdns_mem_caps.h" #include "mdns_utils.h" +#include "mdns_netif.h" #if defined(CONFIG_IDF_TARGET_LINUX) #include @@ -71,7 +72,7 @@ static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) action->type = ACTION_RX_HANDLE; action->data.rx_handle.packet = packet; - if (!mdns_action_queue(action)) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(action); return ESP_ERR_NO_MEM; } @@ -373,7 +374,7 @@ static bool create_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) return true; } int sock = s_interfaces[tcpip_if].sock; - esp_netif_t *netif = _mdns_get_esp_netif(tcpip_if); + esp_netif_t *netif = mdns_netif_get_esp_netif(tcpip_if); if (sock < 0) { sock = create_socket(netif); } diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index 4d336c5211..3fe29f7bb7 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -11,6 +11,7 @@ #include "mdns_send.h" #include "esp_log.h" #include "mdns_responder.h" +#include "mdns_netif.h" static const char *TAG = "mdns_querier"; @@ -129,11 +130,11 @@ void mdns_priv_query_action(mdns_action_t *action, mdns_action_subtype_t type) */ void mdns_priv_query_start_stop(void) { - mdns_service_lock(); + mdns_priv_service_lock(); mdns_search_once_t *s = s_search_once; uint32_t now = xTaskGetTickCount() * portTICK_PERIOD_MS; if (!s) { - mdns_service_unlock(); + mdns_priv_service_unlock(); return; } while (s) { @@ -153,7 +154,7 @@ void mdns_priv_query_start_stop(void) } s = s->next; } - mdns_service_unlock(); + mdns_priv_service_unlock(); } void mdns_priv_query_free(void) @@ -215,7 +216,7 @@ mdns_search_once_t *mdns_priv_query_find_from(mdns_search_once_t *s, mdns_name_t } r = s->result; while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { + if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { return s; } r = r->next; @@ -291,7 +292,7 @@ static mdns_tx_packet_t *_mdns_create_search_packet(mdns_search_once_t *search, r = search->result; while (r) { //full record on the same interface is available - if (r->esp_netif != _mdns_get_esp_netif(tcpip_if) || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { + if (r->esp_netif != mdns_netif_get_esp_netif(tcpip_if) || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { r = r->next; continue; } @@ -414,9 +415,9 @@ static mdns_search_once_t *_mdns_search_init(const char *name, const char *servi * */ void mdns_query_results_free(mdns_result_t *results) { - mdns_service_lock(); + mdns_priv_service_lock(); mdns_priv_query_results_free(results); - mdns_service_unlock(); + mdns_priv_service_unlock(); } esp_err_t mdns_query_async_delete(mdns_search_once_t *search) @@ -428,9 +429,9 @@ esp_err_t mdns_query_async_delete(mdns_search_once_t *search) return ESP_ERR_INVALID_STATE; } - mdns_service_lock(); + mdns_priv_service_lock(); _mdns_search_free(search); - mdns_service_unlock(); + mdns_priv_service_unlock(); return ESP_OK; } @@ -454,7 +455,7 @@ mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, { mdns_search_once_t *search = NULL; - if (!is_mdns_server() || !timeout || mdns_utils_str_null_or_empty(service) != mdns_utils_str_null_or_empty(proto)) { + if (!mdns_priv_is_server_init() || !timeout || mdns_utils_str_null_or_empty(service) != mdns_utils_str_null_or_empty(proto)) { return NULL; } @@ -477,7 +478,7 @@ esp_err_t mdns_query_generic(const char *name, const char *service, const char * *results = NULL; - if (!is_mdns_server()) { + if (!mdns_priv_is_server_init()) { return ESP_ERR_INVALID_STATE; } @@ -549,7 +550,7 @@ static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_o action->type = type; action->data.search_add.search = search; - if (!mdns_action_queue(action)) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(action); return ESP_ERR_NO_MEM; } @@ -644,14 +645,14 @@ void mdns_priv_query_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t { mdns_result_t *r = search->result; while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { + if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { if (r->txt) { goto free_txt; } r->txt = txt; r->txt_value_len = txt_value_len; r->txt_count = txt_count; - _mdns_result_update_ttl(r, ttl); + mdns_priv_query_update_result_ttl(r, ttl); return; } r = r->next; @@ -667,7 +668,7 @@ void mdns_priv_query_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t r->txt = txt; r->txt_value_len = txt_value_len; r->txt_count = txt_count; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = search->result; @@ -706,7 +707,7 @@ static void _mdns_result_add_ip(mdns_result_t *r, esp_ip_addr_t *ip) } a = a->next; } - a = _mdns_result_addr_create_ip(ip); + a = mdns_priv_result_addr_create_ip(ip); if (!a) { return; } @@ -728,9 +729,9 @@ void mdns_priv_query_result_add_ip(mdns_search_once_t *search, const char *hostn || search->type == MDNS_TYPE_ANY) { r = search->result; while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { + if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { _mdns_result_add_ip(r, ip); - _mdns_result_update_ttl(r, ttl); + mdns_priv_query_update_result_ttl(r, ttl); return; } r = r->next; @@ -744,7 +745,7 @@ void mdns_priv_query_result_add_ip(mdns_search_once_t *search, const char *hostn memset(r, 0, sizeof(mdns_result_t)); - a = _mdns_result_addr_create_ip(ip); + a = mdns_priv_result_addr_create_ip(ip); if (!a) { mdns_mem_free(r); return; @@ -752,7 +753,7 @@ void mdns_priv_query_result_add_ip(mdns_search_once_t *search, const char *hostn a->next = r->addr; r->hostname = mdns_mem_strdup(hostname); r->addr = a; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->next = search->result; r->ttl = ttl; @@ -762,9 +763,9 @@ void mdns_priv_query_result_add_ip(mdns_search_once_t *search, const char *hostn } else if (search->type == MDNS_TYPE_PTR || search->type == MDNS_TYPE_SRV) { r = search->result; while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { _mdns_result_add_ip(r, ip); - _mdns_result_update_ttl(r, ttl); + mdns_priv_query_update_result_ttl(r, ttl); break; } r = r->next; @@ -780,8 +781,8 @@ void mdns_priv_query_result_add_srv(mdns_search_once_t *search, const char *host { mdns_result_t *r = search->result; while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { - _mdns_result_update_ttl(r, ttl); + if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + mdns_priv_query_update_result_ttl(r, ttl); return; } r = r->next; @@ -805,7 +806,7 @@ void mdns_priv_query_result_add_srv(mdns_search_once_t *search, const char *host r->service_type = mdns_mem_strdup(search->service); r->proto = mdns_mem_strdup(search->proto); r->port = port; - r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = search->result; @@ -823,8 +824,8 @@ mdns_result_t *mdns_priv_query_result_add_ptr(mdns_search_once_t *search, const { mdns_result_t *r = search->result; while (r) { - if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { - _mdns_result_update_ttl(r, ttl); + if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { + mdns_priv_query_update_result_ttl(r, ttl); return r; } r = r->next; @@ -845,7 +846,7 @@ mdns_result_t *mdns_priv_query_result_add_ptr(mdns_search_once_t *search, const return NULL; } - r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = search->result; @@ -855,3 +856,20 @@ mdns_result_t *mdns_priv_query_result_add_ptr(mdns_search_once_t *search, const } return NULL; } + +mdns_ip_addr_t *mdns_priv_result_addr_create_ip(esp_ip_addr_t *ip) +{ + mdns_ip_addr_t *a = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); + if (!a) { + HOOK_MALLOC_FAILED; + return NULL; + } + memset(a, 0, sizeof(mdns_ip_addr_t)); + a->addr.type = ip->type; + if (ip->type == ESP_IPADDR_TYPE_V6) { + memcpy(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16); + } else { + a->addr.u_addr.ip4.addr = ip->u_addr.ip4.addr; + } + return a; +} diff --git a/components/mdns/mdns_receive.c b/components/mdns/mdns_receive.c index 0230359132..1727f6b510 100644 --- a/components/mdns/mdns_receive.c +++ b/components/mdns/mdns_receive.c @@ -35,7 +35,7 @@ static esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_s action->type = type; action->data.browse_sync.browse_sync = browse_sync; - if (!mdns_action_queue(action)) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(action); return ESP_ERR_NO_MEM; } @@ -58,9 +58,9 @@ static bool _mdns_name_is_discovery(mdns_name_t *name, uint16_t type) static mdns_srv_item_t *_mdns_get_service_item_subtype(const char *subtype, const char *service, const char *proto) { - mdns_srv_item_t *s = mdns_utils_get_services(); + mdns_srv_item_t *s = mdns_priv_get_services(); while (s) { - if (_mdns_service_match(s->service, service, proto, NULL)) { + if (mdns_utils_service_match(s->service, service, proto, NULL)) { mdns_subtype_t *subtype_item = s->service->subtype; while (subtype_item) { if (!strcasecmp(subtype_item->subtype, subtype)) { @@ -91,8 +91,8 @@ static bool _mdns_name_is_ours(mdns_name_t *name) //if service and proto are empty, host must match out hostname if (mdns_utils_str_null_or_empty(name->service) && mdns_utils_str_null_or_empty(name->proto)) { if (!mdns_utils_str_null_or_empty(name->host) - && !mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname()) - && _hostname_is_ours(name->host)) { + && !mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname()) + && mdns_utils_hostname_is_ours(name->host)) { return true; } return false; @@ -109,9 +109,9 @@ static bool _mdns_name_is_ours(mdns_name_t *name) if (name->sub) { service = _mdns_get_service_item_subtype(name->host, name->service, name->proto); } else if (mdns_utils_str_null_or_empty(name->host)) { - service = _mdns_get_service_item(name->service, name->proto, NULL); + service = mdns_utils_get_service_item(name->service, name->proto, NULL); } else { - service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL); + service = mdns_utils_get_service_item_instance(name->host, name->service, name->proto, NULL); } if (!service) { return false; @@ -123,7 +123,7 @@ static bool _mdns_name_is_ours(mdns_name_t *name) } //OK we have host in the name. find what is the instance of the service - const char *instance = _mdns_get_service_instance_name(service->service); + const char *instance = mdns_utils_get_service_instance_name(service->service); if (instance == NULL) { return false; } @@ -346,7 +346,7 @@ static int _mdns_check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) if (!ip->addr) { return 1;//denial! they win } - if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { + if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(tcpip_if), &if_ip_info)) { return 1;//they win } int ret = memcmp((uint8_t *)&if_ip_info.ip.addr, (uint8_t *)&ip->addr, sizeof(esp_ip4_addr_t)); @@ -358,7 +358,7 @@ static int _mdns_check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) if (other_if == MDNS_MAX_INTERFACES) { return 1;//AP interface! They win } - if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &other_ip_info)) { + if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(other_if), &other_ip_info)) { return 1;//IPv4 not active! They win } if (ip->addr != other_ip_info.ip.addr) { @@ -382,10 +382,10 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) if (mdns_utils_ipv6_address_is_zero(*ip)) { return 1;//denial! they win } - if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(tcpip_if), &if_ip6)) { + if (esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(tcpip_if), &if_ip6)) { return 1;//they win } - int ret = memcmp((uint8_t *)&if_ip6.addr, (uint8_t *)ip->addr, _MDNS_SIZEOF_IP6_ADDR); + int ret = memcmp((uint8_t *)&if_ip6.addr, (uint8_t *)ip->addr, MDNS_UTILS_SIZEOF_IP6_ADDR); if (ret > 0) { return -1;//we win } else if (ret < 0) { @@ -394,10 +394,10 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) if (other_if == MDNS_MAX_INTERFACES) { return 1;//AP interface! They win } - if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &other_ip6)) { + if (esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(other_if), &other_ip6)) { return 1;//IPv6 not active! They win } - if (memcmp((uint8_t *)&other_ip6.addr, (uint8_t *)ip->addr, _MDNS_SIZEOF_IP6_ADDR)) { + if (memcmp((uint8_t *)&other_ip6.addr, (uint8_t *)ip->addr, MDNS_UTILS_SIZEOF_IP6_ADDR)) { return 1;//IPv6 not ours! They win } mdns_priv_pcb_set_duplicate(tcpip_if); @@ -439,7 +439,7 @@ static int _mdns_check_txt_collision(mdns_service_t *service, const uint8_t *dat txt = service->txt; while (txt) { - append_one_txt_record_entry(ours, &index, txt); + mdns_priv_append_one_txt_record_entry(ours, &index, txt); txt = txt->next; } @@ -457,11 +457,11 @@ static int _mdns_check_txt_collision(mdns_service_t *service, const uint8_t *dat */ static int _mdns_check_srv_collision(mdns_service_t *service, uint16_t priority, uint16_t weight, uint16_t port, const char *host, const char *domain) { - if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { + if (mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { return 0; } - size_t our_host_len = strlen(mdns_utils_get_global_hostname()); + size_t our_host_len = strlen(mdns_priv_get_global_hostname()); size_t our_len = 14 + our_host_len; size_t their_host_len = strlen(host); @@ -476,11 +476,11 @@ static int _mdns_check_srv_collision(mdns_service_t *service, uint16_t priority, uint16_t our_index = 0; uint8_t our_data[our_len]; - _mdns_append_u16(our_data, &our_index, service->priority); - _mdns_append_u16(our_data, &our_index, service->weight); - _mdns_append_u16(our_data, &our_index, service->port); + mdns_utils_append_u16(our_data, &our_index, service->priority); + mdns_utils_append_u16(our_data, &our_index, service->weight); + mdns_utils_append_u16(our_data, &our_index, service->port); our_data[our_index++] = our_host_len; - memcpy(our_data + our_index, mdns_utils_get_global_hostname(), our_host_len); + memcpy(our_data + our_index, mdns_priv_get_global_hostname(), our_host_len); our_index += our_host_len; our_data[our_index++] = 5; memcpy(our_data + our_index, MDNS_UTILS_DEFAULT_DOMAIN, 5); @@ -489,9 +489,9 @@ static int _mdns_check_srv_collision(mdns_service_t *service, uint16_t priority, uint16_t their_index = 0; uint8_t their_data[their_len]; - _mdns_append_u16(their_data, &their_index, priority); - _mdns_append_u16(their_data, &their_index, weight); - _mdns_append_u16(their_data, &their_index, port); + mdns_utils_append_u16(their_data, &their_index, priority); + mdns_utils_append_u16(their_data, &their_index, weight); + mdns_utils_append_u16(their_data, &their_index, port); their_data[their_index++] = their_host_len; memcpy(their_data + their_index, host, their_host_len); their_index += their_host_len; @@ -514,19 +514,19 @@ static int _mdns_check_srv_collision(mdns_service_t *service, uint16_t priority, */ static bool _mdns_name_is_selfhosted(mdns_name_t *name) { - if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { // self-hostname needs to be defined + if (mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { // self-hostname needs to be defined return false; } // hostname only -- check if selfhosted name if (mdns_utils_str_null_or_empty(name->service) && mdns_utils_str_null_or_empty(name->proto) && - strcasecmp(name->host, mdns_utils_get_global_hostname()) == 0) { + strcasecmp(name->host, mdns_priv_get_global_hostname()) == 0) { return true; } // service -- check if selfhosted service - mdns_srv_item_t *srv = _mdns_get_service_item(name->service, name->proto, NULL); - if (srv && strcasecmp(mdns_utils_get_global_hostname(), srv->service->hostname) == 0) { + mdns_srv_item_t *srv = mdns_utils_get_service_item(name->service, name->proto, NULL); + if (srv && strcasecmp(mdns_priv_get_global_hostname(), srv->service->hostname) == 0) { return true; } return false; @@ -554,7 +554,7 @@ static bool _mdns_question_matches(mdns_parsed_question_t *question, uint16_t ty } } } else if (service && (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT)) { - const char *name = _mdns_get_service_instance_name(service->service); + const char *name = mdns_utils_get_service_instance_name(service->service); if (name && question->host && question->service && question->proto && question->domain && !strcasecmp(name, question->host) && !strcasecmp(service->service->service, question->service) @@ -626,7 +626,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) #ifdef CONFIG_LWIP_IPV4 if (packet->ip_protocol == MDNS_IP_PROTOCOL_V4) { esp_netif_ip_info_t if_ip_info; - if (esp_netif_get_ip_info(_mdns_get_esp_netif(packet->tcpip_if), &if_ip_info) == ESP_OK && + if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(packet->tcpip_if), &if_ip_info) == ESP_OK && memcmp(&if_ip_info.ip.addr, &packet->src.u_addr.ip4.addr, sizeof(esp_ip4_addr_t)) == 0) { return; } @@ -635,7 +635,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) #ifdef CONFIG_LWIP_IPV6 if (packet->ip_protocol == MDNS_IP_PROTOCOL_V6) { struct esp_ip6_addr if_ip6; - if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(packet->tcpip_if), &if_ip6) == ESP_OK && + if (esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(packet->tcpip_if), &if_ip6) == ESP_OK && memcmp(&if_ip6, &packet->src.u_addr.ip6, sizeof(esp_ip6_addr_t)) == 0) { return; } @@ -671,7 +671,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } //if we have not set the hostname, we can not answer questions - if (header.questions && !header.answers && mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { + if (header.questions && !header.answers && mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { mdns_mem_free(parsed_packet); return; } @@ -690,7 +690,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) uint8_t qs = header.questions; while (qs--) { - content = _mdns_parse_fqdn(data, content, name, len); + content = mdns_utils_parse_fqdn(data, content, name, len); if (!content) { header.answers = 0; header.additional = 0; @@ -714,7 +714,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (_mdns_name_is_discovery(name, type)) { //service discovery parsed_packet->discovery = true; - mdns_srv_item_t *a = mdns_utils_get_services(); + mdns_srv_item_t *a = mdns_priv_get_services(); while (a) { mdns_parsed_question_t *question = (mdns_parsed_question_t *)mdns_mem_calloc(1, sizeof(mdns_parsed_question_t)); if (!question) { @@ -772,7 +772,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) while (content < (data + len)) { - content = _mdns_parse_fqdn(data, content, name, len); + content = mdns_utils_parse_fqdn(data, content, name, len); if (!content) { goto clear_rx_packet;//error } @@ -814,7 +814,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else if (!name->sub && _mdns_name_is_ours(name)) { ours = true; if (name->service[0] && name->proto[0]) { - service = _mdns_get_service_item(name->service, name->proto, NULL); + service = mdns_utils_get_service_item(name->service, name->proto, NULL); } } else { if ((header.flags & MDNS_FLAGS_QUERY_REPSONSE) == 0 || record_type == MDNS_NS) { @@ -864,7 +864,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } if (type == MDNS_TYPE_PTR) { - if (!_mdns_parse_fqdn(data, data_ptr, name, len)) { + if (!mdns_utils_parse_fqdn(data, data_ptr, name, len)) { continue;//error } if (search_result) { @@ -872,9 +872,9 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) packet->tcpip_if, packet->ip_protocol, ttl); } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { if (name->host[0]) { - service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL); + service = mdns_utils_get_service_item_instance(name->host, name->service, name->proto, NULL); } else { - service = _mdns_get_service_item(name->service, name->proto, NULL); + service = mdns_utils_get_service_item(name->service, name->proto, NULL); } if (discovery && service) { _mdns_remove_parsed_question(parsed_packet, MDNS_TYPE_SDPTR, service); @@ -931,7 +931,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (search_result && search_result->type == MDNS_TYPE_PTR) { result = search_result->result; while (result) { - if (_mdns_get_esp_netif(packet->tcpip_if) == result->esp_netif + if (mdns_netif_get_esp_netif(packet->tcpip_if) == result->esp_netif && packet->ip_protocol == result->ip_protocol && result->instance_name && !strcmp(name->host, result->instance_name)) { break; @@ -947,7 +947,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } bool is_selfhosted = _mdns_name_is_selfhosted(name); - if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { + if (!mdns_utils_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { continue;//error } if (data_ptr + MDNS_SRV_PORT_OFFSET + 1 >= data + len) { @@ -1003,24 +1003,24 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) mdns_mem_free((char *)service->service->instance); service->service->instance = new_instance; } - _mdns_probe_all_pcbs(&service, 1, false, false); - } else if (!mdns_utils_str_null_or_empty(mdns_utils_get_instance())) { - char *new_instance = _mdns_mangle_name((char *)mdns_utils_get_instance()); + mdns_responder_probe_all_pcbs(&service, 1, false, false); + } else if (!mdns_utils_str_null_or_empty(mdns_priv_get_instance())) { + char *new_instance = _mdns_mangle_name((char *) mdns_priv_get_instance()); if (new_instance) { - mdns_utils_set_instance(new_instance); + mdns_priv_set_instance(new_instance); } - _mdns_restart_all_pcbs_no_instance(); + mdns_priv_restart_all_pcbs_no_instance(); } else { - char *new_host = _mdns_mangle_name((char *)mdns_utils_get_global_hostname()); + char *new_host = _mdns_mangle_name((char *) mdns_priv_get_global_hostname()); if (new_host) { - _mdns_remap_self_service_hostname(mdns_utils_get_global_hostname(), new_host); - mdns_utils_set_global_hostname(new_host); + mdns_priv_remap_self_service_hostname(mdns_priv_get_global_hostname(), new_host); + mdns_priv_set_global_hostname(new_host); } - _mdns_restart_all_pcbs(); + mdns_priv_restart_all_pcbs(); } } else if (service) { - _mdns_pcb_send_bye(packet->tcpip_if, packet->ip_protocol, &service, 1, false); - _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, false); + mdns_send_bye_pcb(packet->tcpip_if, packet->ip_protocol, &service, 1, false); + mdns_responder_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, false); } } } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions) { @@ -1044,7 +1044,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (search_result->type == MDNS_TYPE_PTR) { result = search_result->result; while (result) { - if (_mdns_get_esp_netif(packet->tcpip_if) == result->esp_netif + if (mdns_netif_get_esp_netif(packet->tcpip_if) == result->esp_netif && packet->ip_protocol == result->ip_protocol && result->instance_name && !strcmp(name->host, result->instance_name)) { break; @@ -1093,7 +1093,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } if (col && !mdns_priv_pcb_is_probing(packet) && service) { do_not_reply = true; - _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); + mdns_responder_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); } else if (ttl > (MDNS_ANSWER_TXT_TTL / 2) && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( packet)) { _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); @@ -1142,15 +1142,15 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (mdns_priv_pcb_is_probing(packet)) { if (col && (parsed_packet->probe || parsed_packet->authoritative)) { mdns_priv_pcb_set_probe_failed(packet); - char *new_host = _mdns_mangle_name((char *)mdns_utils_get_global_hostname()); + char *new_host = _mdns_mangle_name((char *) mdns_priv_get_global_hostname()); if (new_host) { - _mdns_remap_self_service_hostname(mdns_utils_get_global_hostname(), new_host); - mdns_utils_set_global_hostname(new_host); + mdns_priv_remap_self_service_hostname(mdns_priv_get_global_hostname(), new_host); + mdns_priv_set_global_hostname(new_host); } - _mdns_restart_all_pcbs(); + mdns_priv_restart_all_pcbs(); } } else { - _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); + mdns_responder_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); } } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( packet)) { @@ -1201,15 +1201,15 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (mdns_priv_pcb_is_probing(packet)) { if (col && (parsed_packet->probe || parsed_packet->authoritative)) { mdns_priv_pcb_set_probe_failed(packet); - char *new_host = _mdns_mangle_name((char *)mdns_utils_get_global_hostname()); + char *new_host = _mdns_mangle_name((char *) mdns_priv_get_global_hostname()); if (new_host) { - _mdns_remap_self_service_hostname(mdns_utils_get_global_hostname(), new_host); - mdns_utils_set_global_hostname(new_host); + mdns_priv_remap_self_service_hostname(mdns_priv_get_global_hostname(), new_host); + mdns_priv_set_global_hostname(new_host); } - _mdns_restart_all_pcbs(); + mdns_priv_restart_all_pcbs(); } } else { - _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); + mdns_responder_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); } } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( packet)) { @@ -1227,7 +1227,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } if (!do_not_reply && mdns_priv_pcb_is_after_probing(packet) && (parsed_packet->questions || parsed_packet->discovery)) { - _mdns_create_answer_from_parsed_packet(parsed_packet); + mdns_priv_create_answer_from_parsed_packet(parsed_packet); } if (out_sync_browse) { DBG_BROWSE_RESULTS_WITH_MSG(out_sync_browse->browse->result, diff --git a/components/mdns/mdns_responder.c b/components/mdns/mdns_responder.c index 9c69d67523..1667ac3464 100644 --- a/components/mdns/mdns_responder.c +++ b/components/mdns/mdns_responder.c @@ -36,7 +36,7 @@ void mdns_priv_pcb_announce(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, size_t i; if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { if (PCB_STATE_IS_PROBING(_pcb)) { - _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, len, include_ip); + mdns_responder_init_pcb_probe(tcpip_if, ip_protocol, services, len, include_ip); } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { mdns_tx_packet_t *p = _mdns_get_next_pcb_packet(tcpip_if, ip_protocol); if (p) { @@ -57,14 +57,14 @@ void mdns_priv_pcb_announce(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, } } else if (_pcb->state == PCB_RUNNING) { - if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { + if (mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { return; } _pcb->state = PCB_ANNOUNCE_1; mdns_tx_packet_t *p = _mdns_create_announce_packet(tcpip_if, ip_protocol, services, len, include_ip); if (p) { - _mdns_schedule_tx_packet(p, 0); + mdns_send_schedule_tx_packet(p, 0); } } } @@ -114,24 +114,24 @@ static esp_err_t mdns_pcb_deinit_local(mdns_if_t tcpip_if, mdns_ip_protocol_t ip static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { size_t srv_count = 0; - mdns_srv_item_t *a = mdns_utils_get_services(); + mdns_srv_item_t *a = mdns_priv_get_services(); while (a) { srv_count++; a = a->next; } if (srv_count == 0) { // proble only IP - _mdns_init_pcb_probe(tcpip_if, ip_protocol, NULL, 0, true); + mdns_responder_init_pcb_probe(tcpip_if, ip_protocol, NULL, 0, true); return; } mdns_srv_item_t *services[srv_count]; size_t i = 0; - a = mdns_utils_get_services(); + a = mdns_priv_get_services(); while (a) { services[i++] = a; a = a->next; } - _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, srv_count, true); + mdns_responder_init_pcb_probe(tcpip_if, ip_protocol, services, srv_count, true); } /** @@ -211,13 +211,13 @@ void mdns_priv_pcb_schedule_tx_packet(mdns_tx_packet_t *p) } //fallthrough case PCB_PROBE_2: - _mdns_schedule_tx_packet(p, 250); + mdns_send_schedule_tx_packet(p, 250); pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); break; case PCB_PROBE_3: a = _mdns_create_announce_from_probe(p); if (!a) { - _mdns_schedule_tx_packet(p, 250); + mdns_send_schedule_tx_packet(p, 250); break; } pcb->probe_running = false; @@ -233,7 +233,7 @@ void mdns_priv_pcb_schedule_tx_packet(mdns_tx_packet_t *p) case PCB_ANNOUNCE_1: //fallthrough case PCB_ANNOUNCE_2: - _mdns_schedule_tx_packet(p, send_after); + mdns_send_schedule_tx_packet(p, send_after); pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); break; case PCB_ANNOUNCE_3: @@ -372,24 +372,17 @@ static void _mdns_init_pcb_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protoco pcb->probe_services = _services; pcb->probe_services_len = services_final_len; pcb->probe_running = true; - _mdns_schedule_tx_packet(packet, ((pcb->failed_probes > 5) ? 1000 : 120) + (esp_random() & 0x7F)); + mdns_send_schedule_tx_packet(packet, ((pcb->failed_probes > 5) ? 1000 : 120) + (esp_random() & 0x7F)); pcb->state = PCB_PROBE_1; } -/** - * @brief Send probe for particular services on particular PCB - * - * Tests possible duplication on probing service structure and probes only for new entries. - * - If pcb probing then add only non-probing services and restarts probing - * - If pcb not probing, run probing for all specified services - */ -void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) +void mdns_responder_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) { mdns_pcb_t *pcb = &s_pcbs[tcpip_if][ip_protocol]; _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); - if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { + if (mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { pcb->state = PCB_RUNNING; return; } @@ -426,23 +419,20 @@ void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, md void mdns_responder_send_bye_service(mdns_srv_item_t **services, size_t len, bool include_ip) { uint8_t i, j; - if (mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { + if (mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { return; } for (i = 0; i < MDNS_MAX_INTERFACES; i++) { for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { if (mdns_is_netif_ready(i, j) && s_pcbs[i][j].state == PCB_RUNNING) { - _mdns_pcb_send_bye((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); + mdns_send_bye_pcb((mdns_if_t) i, (mdns_ip_protocol_t) j, services, len, include_ip); } } } } -/** - * @brief Send probe on all active PCBs - */ -void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe) +void mdns_responder_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe) { uint8_t i, j; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { @@ -455,7 +445,7 @@ void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, _pcb->probe_services_len = 0; _pcb->probe_running = false; } - _mdns_init_pcb_probe((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, probe_ip); + mdns_responder_init_pcb_probe((mdns_if_t) i, (mdns_ip_protocol_t) j, services, len, probe_ip); } } } diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index 465029069a..897ce29749 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -44,16 +44,7 @@ static inline uint8_t _mdns_append_u8(uint8_t *packet, uint16_t *index, uint8_t return 1; } -/** - * @brief appends uint16_t in a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param value the value to set - * - * @return length of added data: 0 on error or 2 on success - */ -uint8_t _mdns_append_u16(uint8_t *packet, uint16_t *index, uint16_t value) +uint8_t mdns_utils_append_u16(uint8_t *packet, uint16_t *index, uint16_t value) { if ((*index + 1) >= MDNS_MAX_PACKET_SIZE) { return 0; @@ -104,25 +95,25 @@ static inline uint8_t _mdns_append_type(uint8_t *packet, uint16_t *index, uint8_ mdns_class = MDNS_CLASS_IN_FLUSH_CACHE; } if (type == MDNS_ANSWER_PTR) { - _mdns_append_u16(packet, index, MDNS_TYPE_PTR); - _mdns_append_u16(packet, index, mdns_class); + mdns_utils_append_u16(packet, index, MDNS_TYPE_PTR); + mdns_utils_append_u16(packet, index, mdns_class); } else if (type == MDNS_ANSWER_TXT) { - _mdns_append_u16(packet, index, MDNS_TYPE_TXT); - _mdns_append_u16(packet, index, mdns_class); + mdns_utils_append_u16(packet, index, MDNS_TYPE_TXT); + mdns_utils_append_u16(packet, index, mdns_class); } else if (type == MDNS_ANSWER_SRV) { - _mdns_append_u16(packet, index, MDNS_TYPE_SRV); - _mdns_append_u16(packet, index, mdns_class); + mdns_utils_append_u16(packet, index, MDNS_TYPE_SRV); + mdns_utils_append_u16(packet, index, mdns_class); } else if (type == MDNS_ANSWER_A) { - _mdns_append_u16(packet, index, MDNS_TYPE_A); - _mdns_append_u16(packet, index, mdns_class); + mdns_utils_append_u16(packet, index, MDNS_TYPE_A); + mdns_utils_append_u16(packet, index, mdns_class); } else if (type == MDNS_ANSWER_AAAA) { - _mdns_append_u16(packet, index, MDNS_TYPE_AAAA); - _mdns_append_u16(packet, index, mdns_class); + mdns_utils_append_u16(packet, index, MDNS_TYPE_AAAA); + mdns_utils_append_u16(packet, index, mdns_class); } else { return 0; } _mdns_append_u32(packet, index, ttl); - _mdns_append_u16(packet, index, 0); + mdns_utils_append_u16(packet, index, 0); return 10; } @@ -158,18 +149,7 @@ static inline uint8_t _mdns_append_string(uint8_t *packet, uint16_t *index, cons return len + 1; } -/** - * @brief appends one TXT record ("key=value" or "key") - * - * @param packet MDNS packet - * @param index offset in the packet - * @param txt one txt record - * - * @return length of added data: length of the added txt value + 1 on success - * 0 if data won't fit the packet - * -1 if invalid TXT entry - */ -int append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt) +int mdns_priv_append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt) { if (txt == NULL || txt->key == NULL) { return -1; @@ -297,10 +277,10 @@ bool _mdns_alloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_ser static mdns_host_item_t *mdns_get_host_item(const char *hostname) { - if (hostname == NULL || strcasecmp(hostname, mdns_utils_get_global_hostname()) == 0) { - return mdns_utils_get_selfhost(); + if (hostname == NULL || strcasecmp(hostname, mdns_priv_get_global_hostname()) == 0) { + return priv_get_self_host(); } - mdns_host_item_t *host = mdns_utils_get_hosts(); + mdns_host_item_t *host = mdns_priv_get_hosts(); while (host != NULL) { if (strcasecmp(host->hostname, hostname) == 0) { return host; @@ -314,7 +294,7 @@ static bool _mdns_create_answer_from_service(mdns_tx_packet_t *packet, mdns_serv mdns_parsed_question_t *question, bool shared, bool send_flush) { mdns_host_item_t *host = mdns_get_host_item(service->hostname); - bool is_delegated = (host != mdns_utils_get_selfhost()); + bool is_delegated = (host != priv_get_self_host()); if (question->type == MDNS_TYPE_PTR || question->type == MDNS_TYPE_ANY) { // According to RFC6763-section12.1, for DNS-SD, SRV, TXT and all address records // should be included in additional records. @@ -357,7 +337,7 @@ static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t *packet, const ch static bool _mdns_service_match_ptr_question(const mdns_service_t *service, const mdns_parsed_question_t *question) { - if (!_mdns_service_match(service, question->service, question->proto, NULL)) { + if (!mdns_utils_service_match(service, question->service, question->proto, NULL)) { return false; } // The question parser stores anything before _type._proto in question->host @@ -373,7 +353,7 @@ static bool _mdns_service_match_ptr_question(const mdns_service_t *service, cons return false; } if (question->host) { - if (strcasecmp(_mdns_get_service_instance_name(service), question->host) != 0) { + if (strcasecmp(mdns_utils_get_service_instance_name(service), question->host) != 0) { return false; } } @@ -394,7 +374,7 @@ bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_sr size_t services_len, bool flush, bool bye) { if (services == NULL) { - mdns_host_item_t *host = mdns_get_host_item(mdns_utils_get_global_hostname()); + mdns_host_item_t *host = mdns_get_host_item(mdns_priv_get_global_hostname()); if (host != NULL) { return _mdns_append_host(destination, host, flush, bye); } @@ -411,13 +391,13 @@ bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_sr bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye) { - if (!mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname())) { - mdns_host_item_t *self_host = mdns_get_host_item(mdns_utils_get_global_hostname()); + if (!mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { + mdns_host_item_t *self_host = mdns_get_host_item(mdns_priv_get_global_hostname()); if (!_mdns_append_host(destination, self_host, flush, bye)) { return false; } } - mdns_host_item_t *host = mdns_utils_get_hosts(); + mdns_host_item_t *host = mdns_priv_get_hosts(); while (host != NULL) { host = host->next; if (!_mdns_append_host(destination, host, flush, bye)) { @@ -470,8 +450,8 @@ static bool _mdns_append_host_question(mdns_out_question_t **questions, const ch static bool _mdns_append_host_questions_for_services(mdns_out_question_t **questions, mdns_srv_item_t *services[], size_t len, bool unicast) { - if (!mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname()) && - !_mdns_append_host_question(questions, mdns_utils_get_global_hostname(), unicast)) { + if (!mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname()) && + !_mdns_append_host_question(questions, mdns_priv_get_global_hostname(), unicast)) { return false; } for (size_t i = 0; i < len; i++) { @@ -553,7 +533,7 @@ static uint8_t _mdns_append_reverse_ptr_record(uint8_t *packet, uint16_t *index, } uint16_t data_len_location = *index - 2; /* store the position of size (2=16bis) of this record */ - const char *str[2] = { mdns_utils_get_selfhost()->hostname, MDNS_UTILS_DEFAULT_DOMAIN }; + const char *str[2] = {priv_get_self_host()->hostname, MDNS_UTILS_DEFAULT_DOMAIN }; int part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); if (!part_length) { @@ -565,10 +545,7 @@ static uint8_t _mdns_append_reverse_ptr_record(uint8_t *packet, uint16_t *index, } #endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ -/** - * @brief Create answer packet to questions from parsed packet - */ -void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) +void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) { if (!parsed_packet->questions) { return; @@ -589,7 +566,7 @@ void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) while (q) { shared = q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_SDPTR || !parsed_packet->probe; if (q->type == MDNS_TYPE_SRV || q->type == MDNS_TYPE_TXT) { - mdns_srv_item_t *service = _mdns_get_service_item_instance(q->host, q->service, q->proto, NULL); + mdns_srv_item_t *service = mdns_utils_get_service_item_instance(q->host, q->service, q->proto, NULL); if (service == NULL) { // Service not found, but we continue to the next question q = q->next; continue; @@ -601,19 +578,19 @@ void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) out_record_nums++; } } else if (q->service && q->proto) { - mdns_srv_item_t *service = mdns_utils_get_services(); + mdns_srv_item_t *service = mdns_priv_get_services(); while (service) { if (_mdns_service_match_ptr_question(service->service, q)) { mdns_parsed_record_t *r = parsed_packet->records; bool is_record_exist = false; while (r) { if (service->service->instance && r->host) { - if (_mdns_service_match_instance(service->service, r->host, r->service, r->proto, NULL) && r->ttl > (MDNS_ANSWER_PTR_TTL / 2)) { + if (mdns_utils_service_match_instance(service->service, r->host, r->service, r->proto, NULL) && r->ttl > (MDNS_ANSWER_PTR_TTL / 2)) { is_record_exist = true; break; } } else if (!service->service->instance && !r->host) { - if (_mdns_service_match(service->service, r->service, r->proto, NULL) && r->ttl > (MDNS_ANSWER_PTR_TTL / 2)) { + if (mdns_utils_service_match(service->service, r->service, r->proto, NULL) && r->ttl > (MDNS_ANSWER_PTR_TTL / 2)) { is_record_exist = true; break; } @@ -704,7 +681,7 @@ void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) static uint8_t share_step = 0; if (shared) { - _mdns_schedule_tx_packet(packet, 25 + (share_step * 25)); + mdns_send_schedule_tx_packet(packet, 25 + (share_step * 25)); share_step = (share_step + 1) & 0x03; } else { _mdns_dispatch_tx_packet(packet); @@ -751,7 +728,7 @@ static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char * name.service[0] = 0; name.proto[0] = 0; name.domain[0] = 0; - const uint8_t *content = _mdns_read_fqdn(packet, len_location, &name, buf, packet_len); + const uint8_t *content = mdns_utils_read_fqdn(packet, len_location, &name, buf, packet_len); if (!content) { //not a readable fqdn? goto search_next; // could be our unfinished fqdn, continue searching @@ -783,7 +760,7 @@ static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char * //we have found the string so let's insert a pointer to it instead uint16_t offset = len_location - packet; offset |= MDNS_NAME_REF; - return _mdns_append_u16(packet, index, offset); + return mdns_utils_append_u16(packet, index, offset); } @@ -822,8 +799,8 @@ static uint16_t _mdns_append_question(uint8_t *packet, uint16_t *index, mdns_out } } - part_length += _mdns_append_u16(packet, index, q->type); - part_length += _mdns_append_u16(packet, index, q->unicast ? 0x8001 : 0x0001); + part_length += mdns_utils_append_u16(packet, index, q->type); + part_length += mdns_utils_append_u16(packet, index, q->unicast ? 0x8001 : 0x0001); return part_length; } @@ -931,7 +908,7 @@ static uint8_t _mdns_append_service_ptr_answers(uint8_t *packet, uint16_t *index { uint8_t appended_answers = 0; - if (_mdns_append_ptr_record(packet, index, _mdns_get_service_instance_name(service), service->service, + if (_mdns_append_ptr_record(packet, index, mdns_utils_get_service_instance_name(service), service->service, service->proto, flush, bye) <= 0) { return appended_answers; } @@ -940,7 +917,7 @@ static uint8_t _mdns_append_service_ptr_answers(uint8_t *packet, uint16_t *index mdns_subtype_t *subtype = service->subtype; while (subtype) { appended_answers += - (_mdns_append_subtype_ptr_record(packet, index, _mdns_get_service_instance_name(service), subtype->subtype, + (_mdns_append_subtype_ptr_record(packet, index, mdns_utils_get_service_instance_name(service), subtype->subtype, service->service, service->proto, flush, bye) > 0); subtype = subtype->next; } @@ -968,7 +945,7 @@ static uint16_t _mdns_append_srv_record(uint8_t *packet, uint16_t *index, mdns_s return 0; } - str[0] = _mdns_get_service_instance_name(service); + str[0] = mdns_utils_get_service_instance_name(service); str[1] = service->service; str[2] = service->proto; str[3] = MDNS_UTILS_DEFAULT_DOMAIN; @@ -992,9 +969,9 @@ static uint16_t _mdns_append_srv_record(uint8_t *packet, uint16_t *index, mdns_s uint16_t data_len_location = *index - 2; part_length = 0; - part_length += _mdns_append_u16(packet, index, service->priority); - part_length += _mdns_append_u16(packet, index, service->weight); - part_length += _mdns_append_u16(packet, index, service->port); + part_length += mdns_utils_append_u16(packet, index, service->priority); + part_length += mdns_utils_append_u16(packet, index, service->weight); + part_length += mdns_utils_append_u16(packet, index, service->port); if (part_length != 6) { return 0; } @@ -1002,7 +979,7 @@ static uint16_t _mdns_append_srv_record(uint8_t *packet, uint16_t *index, mdns_s if (service->hostname) { str[0] = service->hostname; } else { - str[0] = mdns_utils_get_global_hostname(); + str[0] = mdns_priv_get_global_hostname(); } str[1] = MDNS_UTILS_DEFAULT_DOMAIN; @@ -1040,7 +1017,7 @@ static uint16_t _mdns_append_txt_record(uint8_t *packet, uint16_t *index, mdns_s return 0; } - str[0] = _mdns_get_service_instance_name(service); + str[0] = mdns_utils_get_service_instance_name(service); str[1] = service->service; str[2] = service->proto; str[3] = MDNS_UTILS_DEFAULT_DOMAIN; @@ -1066,7 +1043,7 @@ static uint16_t _mdns_append_txt_record(uint8_t *packet, uint16_t *index, mdns_s mdns_txt_linked_item_t *txt = service->txt; while (txt) { - int l = append_one_txt_record_entry(packet, index, txt); + int l = mdns_priv_append_one_txt_record_entry(packet, index, txt); if (l > 0) { data_len += l; } else if (l == 0) { // TXT entry won't fit into the mdns packet @@ -1274,8 +1251,8 @@ static uint8_t _mdns_append_host_answer(uint8_t *packet, uint16_t *index, mdns_h static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_answer_t *answer, mdns_if_t tcpip_if) { if (answer->host) { - bool is_host_valid = (mdns_utils_get_selfhost() == answer->host); - mdns_host_item_t *target_host = mdns_utils_get_hosts(); + bool is_host_valid = (priv_get_self_host() == answer->host); + mdns_host_item_t *target_host = mdns_priv_get_hosts(); while (target_host && !is_host_valid) { if (target_host == answer->host) { is_host_valid = true; @@ -1309,26 +1286,26 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an } #ifdef CONFIG_LWIP_IPV4 else if (answer->type == MDNS_TYPE_A) { - if (answer->host == mdns_utils_get_selfhost()) { + if (answer->host == priv_get_self_host()) { esp_netif_ip_info_t if_ip_info; if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && !mdns_priv_pcb_is_duplicate(tcpip_if, MDNS_IP_PROTOCOL_V4)) { return 0; } - if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { + if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(tcpip_if), &if_ip_info)) { return 0; } - if (_mdns_append_a_record(packet, index, mdns_utils_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { + if (_mdns_append_a_record(packet, index, mdns_priv_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { return 0; } if (!mdns_priv_pcb_check_for_duplicates(tcpip_if)) { return 1; } mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); - if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &if_ip_info)) { + if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(other_if), &if_ip_info)) { return 1; } - if (_mdns_append_a_record(packet, index, mdns_utils_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { + if (_mdns_append_a_record(packet, index, mdns_priv_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { return 2; } return 1; @@ -1339,20 +1316,20 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an #endif /* CONFIG_LWIP_IPV4 */ #ifdef CONFIG_LWIP_IPV6 else if (answer->type == MDNS_TYPE_AAAA) { - if (answer->host == mdns_utils_get_selfhost()) { + if (answer->host == priv_get_self_host()) { struct esp_ip6_addr if_ip6s[NETIF_IPV6_MAX_NUMS]; uint8_t count = 0; if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && !mdns_priv_pcb_is_duplicate(tcpip_if, MDNS_IP_PROTOCOL_V6)) { return 0; } - count = esp_netif_get_all_ip6(_mdns_get_esp_netif(tcpip_if), if_ip6s); + count = esp_netif_get_all_ip6(mdns_netif_get_esp_netif(tcpip_if), if_ip6s); assert(count <= NETIF_IPV6_MAX_NUMS); for (int i = 0; i < count; i++) { if (mdns_utils_ipv6_address_is_zero(if_ip6s[i])) { return 0; } - if (_mdns_append_aaaa_record(packet, index, mdns_utils_get_global_hostname(), (uint8_t *)if_ip6s[i].addr, + if (_mdns_append_aaaa_record(packet, index, mdns_priv_get_global_hostname(), (uint8_t *)if_ip6s[i].addr, answer->flush, answer->bye) <= 0) { return 0; } @@ -1363,10 +1340,10 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); struct esp_ip6_addr other_ip6; - if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &other_ip6)) { + if (esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(other_if), &other_ip6)) { return count; } - if (_mdns_append_aaaa_record(packet, index, mdns_utils_get_global_hostname(), (uint8_t *)other_ip6.addr, + if (_mdns_append_aaaa_record(packet, index, mdns_priv_get_global_hostname(), (uint8_t *)other_ip6.addr, answer->flush, answer->bye) > 0) { return 1 + count; } @@ -1461,7 +1438,7 @@ mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol q->next = NULL; q->unicast = first; q->type = MDNS_TYPE_ANY; - q->host = _mdns_get_service_instance_name(services[i]->service); + q->host = mdns_utils_get_service_instance_name(services[i]->service); q->service = services[i]->service->service; q->proto = services[i]->service->proto; q->domain = MDNS_UTILS_DEFAULT_DOMAIN; @@ -1564,10 +1541,7 @@ mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *probe) return packet; } -/** - * @brief Send by for particular services on particular PCB - */ -void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) +void mdns_send_bye_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) { mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); if (!packet) { @@ -1679,7 +1653,7 @@ void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_pro * @param packet the packet * @param ms_after number of milliseconds after which the packet should be dispatched */ -void _mdns_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after) +void mdns_send_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after) { if (!packet) { return; @@ -1772,7 +1746,7 @@ mdns_tx_packet_t *_mdns_get_next_tx_packet(void) */ void mdns_send_packets(void) { - mdns_service_lock(); + mdns_priv_service_lock(); mdns_tx_packet_t *p = s_tx_queue_head; mdns_action_t *action = NULL; @@ -1781,7 +1755,7 @@ void mdns_send_packets(void) p = p->next; } if (!p) { - mdns_service_unlock(); + mdns_priv_service_unlock(); return; } while (p && (int32_t)(p->send_at - (xTaskGetTickCount() * portTICK_PERIOD_MS)) < 0) { @@ -1790,7 +1764,7 @@ void mdns_send_packets(void) action->type = ACTION_TX_HANDLE; action->data.tx_handle.packet = p; p->queued = true; - if (!mdns_action_queue(action)) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(action); p->queued = false; } @@ -1801,7 +1775,7 @@ void mdns_send_packets(void) //Find the next unqued packet p = p->next; } - mdns_service_unlock(); + mdns_priv_service_unlock(); } diff --git a/components/mdns/mdns_utils.c b/components/mdns/mdns_utils.c index 46d12d1de8..c52dbf8038 100644 --- a/components/mdns/mdns_utils.c +++ b/components/mdns/mdns_utils.c @@ -11,20 +11,8 @@ static const char *MDNS_DEFAULT_DOMAIN = "local"; static const char *MDNS_SUB_STR = "_sub"; -static const char *TAG = "mdns_utils"; -/** - * @brief reads MDNS FQDN into mdns_name_t structure - * FQDN is in format: [hostname.|[instance.]_service._proto.]local. - * - * @param packet MDNS packet - * @param start Starting point of FQDN - * @param name mdns_name_t structure to populate - * @param buf temporary char buffer - * - * @return the address after the parsed FQDN in the packet or NULL on error - */ -const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len) +const uint8_t *mdns_utils_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len) { size_t index = 0; const uint8_t *packet_end = packet + packet_len; @@ -68,7 +56,7 @@ const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns //reference address can not be after where we are return NULL; } - if (_mdns_read_fqdn(packet, packet + address, name, buf, packet_len)) { + if (mdns_utils_read_fqdn(packet, packet + address, name, buf, packet_len)) { return start + index; } return NULL; @@ -77,16 +65,7 @@ const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns return start + index + 1; } -/** - * @brief reads and formats MDNS FQDN into mdns_name_t structure - * - * @param packet MDNS packet - * @param start Starting point of FQDN - * @param name mdns_name_t structure to populate - * - * @return the address after the parsed FQDN in the packet or NULL on error - */ -const uint8_t *_mdns_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, size_t packet_len) +const uint8_t *mdns_utils_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, size_t packet_len) { name->parts = 0; name->sub = 0; @@ -98,7 +77,7 @@ const uint8_t *_mdns_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdn static char buf[MDNS_NAME_BUF_LEN]; - const uint8_t *next_data = (uint8_t *)_mdns_read_fqdn(packet, start, name, buf, packet_len); + const uint8_t *next_data = (uint8_t *) mdns_utils_read_fqdn(packet, start, name, buf, packet_len); if (!next_data) { return 0; } @@ -120,13 +99,13 @@ const uint8_t *_mdns_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdn return next_data; } -bool _hostname_is_ours(const char *hostname) +bool mdns_utils_hostname_is_ours(const char *hostname) { - if (!mdns_utils_str_null_or_empty(mdns_utils_get_global_hostname()) && - strcasecmp(hostname, mdns_utils_get_global_hostname()) == 0) { + if (!mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname()) && + strcasecmp(hostname, mdns_priv_get_global_hostname()) == 0) { return true; } - mdns_host_item_t *host = mdns_utils_get_hosts(); + mdns_host_item_t *host = mdns_priv_get_hosts(); while (host != NULL) { if (strcasecmp(hostname, host->hostname) == 0) { return true; @@ -136,8 +115,8 @@ bool _hostname_is_ours(const char *hostname) return false; } -bool _mdns_service_match(const mdns_service_t *srv, const char *service, const char *proto, - const char *hostname) +bool mdns_utils_service_match(const mdns_service_t *srv, const char *service, const char *proto, + const char *hostname) { if (!service || !proto || !srv->hostname) { return false; @@ -146,20 +125,11 @@ bool _mdns_service_match(const mdns_service_t *srv, const char *service, const c (mdns_utils_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); } -/** - * @brief finds service from given service type - * @param server the server - * @param service service type to match - * @param proto proto to match - * @param hostname hostname of the service (if non-null) - * - * @return the service item if found or NULL on error - */ -mdns_srv_item_t *_mdns_get_service_item(const char *service, const char *proto, const char *hostname) +mdns_srv_item_t *mdns_utils_get_service_item(const char *service, const char *proto, const char *hostname) { - mdns_srv_item_t *s = mdns_utils_get_services(); + mdns_srv_item_t *s = mdns_priv_get_services(); while (s) { - if (_mdns_service_match(s->service, service, proto, hostname)) { + if (mdns_utils_service_match(s->service, service, proto, hostname)) { return s; } s = s->next; @@ -167,17 +137,17 @@ mdns_srv_item_t *_mdns_get_service_item(const char *service, const char *proto, return NULL; } -mdns_srv_item_t *_mdns_get_service_item_instance(const char *instance, const char *service, const char *proto, - const char *hostname) +mdns_srv_item_t *mdns_utils_get_service_item_instance(const char *instance, const char *service, const char *proto, + const char *hostname) { - mdns_srv_item_t *s = mdns_utils_get_services(); + mdns_srv_item_t *s = mdns_priv_get_services(); while (s) { if (instance) { - if (_mdns_service_match_instance(s->service, instance, service, proto, hostname)) { + if (mdns_utils_service_match_instance(s->service, instance, service, proto, hostname)) { return s; } } else { - if (_mdns_service_match(s->service, service, proto, hostname)) { + if (mdns_utils_service_match(s->service, service, proto, hostname)) { return s; } } @@ -186,8 +156,8 @@ mdns_srv_item_t *_mdns_get_service_item_instance(const char *instance, const cha return NULL; } -bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instance, const char *service, - const char *proto, const char *hostname) +bool mdns_utils_service_match_instance(const mdns_service_t *srv, const char *instance, const char *service, + const char *proto, const char *hostname) { // service and proto must be supplied, if not this instance won't match if (!service || !proto) { @@ -195,18 +165,18 @@ bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instanc } // instance==NULL -> _mdns_instance_name_match() will check the default instance // hostname==NULL -> matches if instance, service and proto matches - return !strcasecmp(srv->service, service) && _mdns_instance_name_match(srv->instance, instance) && + return !strcasecmp(srv->service, service) && mdns_utils_instance_name_match(srv->instance, instance) && !strcasecmp(srv->proto, proto) && (mdns_utils_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); } -const char *_mdns_get_default_instance_name(void) +static const char *get_default_instance_name(void) { - const char* instance = mdns_utils_get_instance(); + const char* instance = mdns_priv_get_instance(); if (!mdns_utils_str_null_or_empty(instance)) { return instance; } - const char* host = mdns_utils_get_global_hostname(); + const char* host = mdns_priv_get_global_hostname(); if (!mdns_utils_str_null_or_empty(host)) { return host; } @@ -216,36 +186,36 @@ const char *_mdns_get_default_instance_name(void) /** * @brief Get the service name of a service */ -const char *_mdns_get_service_instance_name(const mdns_service_t *service) +const char *mdns_utils_get_service_instance_name(const mdns_service_t *service) { if (service && !mdns_utils_str_null_or_empty(service->instance)) { return service->instance; } - return _mdns_get_default_instance_name(); + return get_default_instance_name(); } -bool _mdns_instance_name_match(const char *lhs, const char *rhs) +bool mdns_utils_instance_name_match(const char *lhs, const char *rhs) { if (lhs == NULL) { - lhs = _mdns_get_default_instance_name(); + lhs = get_default_instance_name(); } if (rhs == NULL) { - rhs = _mdns_get_default_instance_name(); + rhs = get_default_instance_name(); } return !strcasecmp(lhs, rhs); } -mdns_ip_addr_t *copy_address_list(const mdns_ip_addr_t *address_list) +mdns_ip_addr_t *mdns_utils_copy_address_list(const mdns_ip_addr_t *address_list) { mdns_ip_addr_t *head = NULL; mdns_ip_addr_t *tail = NULL; while (address_list != NULL) { mdns_ip_addr_t *addr = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); if (addr == NULL) { - free_address_list(head); + mdns_utils_free_address_list(head); return NULL; } addr->addr = address_list->addr; @@ -262,7 +232,7 @@ mdns_ip_addr_t *copy_address_list(const mdns_ip_addr_t *address_list) return head; } -void free_address_list(mdns_ip_addr_t *address_list) +void mdns_utils_free_address_list(mdns_ip_addr_t *address_list) { while (address_list != NULL) { mdns_ip_addr_t *next = address_list->next; @@ -272,14 +242,11 @@ void free_address_list(mdns_ip_addr_t *address_list) } #ifdef CONFIG_LWIP_IPV6 -/** - * @brief Check if IPv6 address is NULL - */ bool mdns_utils_ipv6_address_is_zero(esp_ip6_addr_t ip6) { uint8_t i; uint8_t *data = (uint8_t *)ip6.addr; - for (i = 0; i < _MDNS_SIZEOF_IP6_ADDR; i++) { + for (i = 0; i < MDNS_UTILS_SIZEOF_IP6_ADDR; i++) { if (data[i]) { return false; } @@ -287,24 +254,3 @@ bool mdns_utils_ipv6_address_is_zero(esp_ip6_addr_t ip6) return true; } #endif /* CONFIG_LWIP_IPV6 */ - - -/** - * @brief Create linked IP (copy) from parsed one - */ -mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip) -{ - mdns_ip_addr_t *a = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); - if (!a) { - HOOK_MALLOC_FAILED; - return NULL; - } - memset(a, 0, sizeof(mdns_ip_addr_t)); - a->addr.type = ip->type; - if (ip->type == ESP_IPADDR_TYPE_V6) { - memcpy(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16); - } else { - a->addr.u_addr.ip4.addr = ip->u_addr.ip4.addr; - } - return a; -} diff --git a/components/mdns/private_include/mdns_netif.h b/components/mdns/private_include/mdns_netif.h index 770657a6e0..990a2b591c 100644 --- a/components/mdns/private_include/mdns_netif.h +++ b/components/mdns/private_include/mdns_netif.h @@ -48,6 +48,19 @@ void mdns_netif_disable(mdns_if_t tcpip_if); */ mdns_if_t mdns_netif_get_other_interface(mdns_if_t tcpip_if); +/** + * @brief Gets the actual esp_netif pointer from the internal network interface list + * + * The supplied ordinal number could + * - point to a predef netif -> "STA", "AP", "ETH" + * - if no entry in the list (NULL) -> check if the system added this netif + * - point to a custom netif -> just return the entry in the list + * - users is responsible for the lifetime of this netif (to be valid between mdns-init -> deinit) + * + * @param tcpip_if Ordinal number of the interface + * @return Pointer ot the esp_netif object if the interface is available, NULL otherwise + */ +esp_netif_t *mdns_netif_get_esp_netif(mdns_if_t tcpip_if); #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 90315f2a1e..149e57d31c 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -443,16 +443,74 @@ typedef struct { } data; } mdns_action_t; -/* - * @brief Convert mnds if to esp-netif handle - * - * @param tcpip_if mdns supported interface as internal enum - * - * @return - * - ptr to esp-netif on success - * - NULL if no available netif for current interface index +/** + * @brief Returns true if the mdns server is initialized + */ +bool mdns_priv_is_server_init(void); + +/** + * @brief get global (mdns_server->hostname) hostname + */ +const char *mdns_priv_get_global_hostname(void); + +/** + * @brief get service list + */ +mdns_srv_item_t *mdns_priv_get_services(void); + +/** + * @brief get host list + */ +mdns_host_item_t *mdns_priv_get_hosts(void); + +/** + * @brief get self host + */ +mdns_host_item_t *priv_get_self_host(void); + +/** + * @brief set global hostname + */ +void mdns_priv_set_global_hostname(const char *hostname); + +/** + * @brief set mdns_server->instance + */ +const char *mdns_priv_get_instance(void); + +/** + * @brief set mdns_server->instance + */ +void mdns_priv_set_instance(const char *instance); + +/** + * @brief Restart the responder on all services without instance + */ +void mdns_priv_restart_all_pcbs_no_instance(void); + +/** + * @brief Remaps hostname of self service */ -esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if); +void mdns_priv_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); +/** + * @brief Restart the responder on all active PCBs + */ +void mdns_priv_restart_all_pcbs(void); + +/** + * @brief Lock mdns service + */ +void mdns_priv_service_lock(void); + +/** + * @brief Unlock mdns service + */ +void mdns_priv_service_unlock(void); + +/** + * @brief Send the given action to the service queue + */ +bool mdns_priv_queue_action(mdns_action_t *action); #endif /* MDNS_PRIVATE_H_ */ diff --git a/components/mdns/private_include/mdns_querier.h b/components/mdns/private_include/mdns_querier.h index 891dad9973..545a6ef9b7 100644 --- a/components/mdns/private_include/mdns_querier.h +++ b/components/mdns/private_include/mdns_querier.h @@ -88,6 +88,20 @@ mdns_result_t *mdns_priv_query_result_add_ptr(mdns_search_once_t *search, const */ void mdns_priv_query_action(mdns_action_t *action, mdns_action_subtype_t type); +/** + * @brief Create linked IP (copy) from parsed one + */ +mdns_ip_addr_t *mdns_priv_result_addr_create_ip(esp_ip_addr_t *ip); + +/** + * @brief Update TTL results to whichever is smaller + */ +static inline void mdns_priv_query_update_result_ttl(mdns_result_t *r, uint32_t ttl) +{ + r->ttl = r->ttl < ttl ? r->ttl : ttl; +} + + #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_responder.h b/components/mdns/private_include/mdns_responder.h index 44a577a8bb..4d9cef87cf 100644 --- a/components/mdns/private_include/mdns_responder.h +++ b/components/mdns/private_include/mdns_responder.h @@ -102,6 +102,21 @@ bool mdns_priv_pcb_check_for_duplicates(mdns_if_t tcpip_if); */ void mdns_responder_send_bye_service(mdns_srv_item_t **services, size_t len, bool include_ip); +/** + * @brief Send probe on all active PCBs + */ +void mdns_responder_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe); + +/** + * @brief Send probe for particular services on particular PCB + * + * Tests possible duplication on probing service structure and probes only for new entries. + * - If pcb probing then add only non-probing services and restarts probing + * - If pcb not probing, run probing for all specified services + */ +void mdns_responder_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip); + + #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_send.h b/components/mdns/private_include/mdns_send.h index 89d88a9f2d..2817bb98ce 100644 --- a/components/mdns/private_include/mdns_send.h +++ b/components/mdns/private_include/mdns_send.h @@ -12,30 +12,126 @@ extern "C" { #endif +/** + * @brief Send a search query packet on the specified interface and protocol + */ void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +/** + * @brief Free a transmit packet and its associated resources + */ void _mdns_free_tx_packet(mdns_tx_packet_t *packet); +/** + * @brief Create a probe packet for service discovery + */ mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool first, bool include_ip); +/** + * @brief Allocate and initialize an answer record for mDNS response + */ bool _mdns_alloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_service_t *service, mdns_host_item_t *host, bool flush, bool bye); +/** + * @brief Create an announcement packet for service advertisement + */ mdns_tx_packet_t *_mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool include_ip); + +/** + * @brief Create an announcement packet from an existing probe packet + */ mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *probe); + +/** + * @brief Dispatch a transmit packet for sending + */ void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p); + +/** + * @brief Send a goodbye message for a service subtype + */ void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, mdns_subtype_t *remove_subtypes); + +/** + * @brief Append host list information to service records + */ bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], size_t services_len, bool flush, bool bye); + +/** + * @brief Clear the transmit queue head for a specific interface and protocol + */ void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Clear the global transmit queue head + */ void _mdns_clear_tx_queue_head(void); + +/** + * @brief Remove scheduled service packets for a given service + */ void _mdns_remove_scheduled_service_packets(mdns_service_t *service); + +/** + * @brief Get the next packet from the PCB queue for a specific interface and protocol + */ mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Deallocate an answer record + */ void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service); + +/** + * @brief Remove a scheduled answer for a specific interface, protocol, and service + */ void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service); + +/** + * @brief Allocate a new packet with default settings + */ mdns_tx_packet_t *_mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Send all pending mDNS packets + */ void mdns_send_packets(void); + +/** + * @brief Execute an mDNS action with specified type + */ void mdns_send_action(mdns_action_t *action, mdns_action_subtype_t type); +/** + * @brief Schedule a transmit packet for sending after a specified delay + */ +void mdns_send_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after); + +/** + * @brief Send by for particular services on particular PCB + */ +void mdns_send_bye_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); + +/** + * @brief Create answer packet to questions from parsed packet + */ +void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet); + +/** + * @brief appends one TXT record ("key=value" or "key") + * + * @param packet MDNS packet + * @param index offset in the packet + * @param txt one txt record + * + * @return length of added data: length of the added txt value + 1 on success + * 0 if data won't fit the packet + * -1 if invalid TXT entry + */ +int mdns_priv_append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt); + + #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_utils.h b/components/mdns/private_include/mdns_utils.h index a220c4be5d..9bec567d0d 100644 --- a/components/mdns/private_include/mdns_utils.h +++ b/components/mdns/private_include/mdns_utils.h @@ -6,7 +6,7 @@ #include "mdns_private.h" #define MDNS_UTILS_DEFAULT_DOMAIN "local" -#define _MDNS_SIZEOF_IP6_ADDR (MDNS_ANSWER_AAAA_SIZE) +#define MDNS_UTILS_SIZEOF_IP6_ADDR (MDNS_ANSWER_AAAA_SIZE) /** * @brief read uint16_t from a packet @@ -32,80 +32,105 @@ static inline uint32_t mdns_utils_read_u32(const uint8_t *packet, uint16_t index return (uint32_t)(packet[index]) << 24 | (uint32_t)(packet[index + 1]) << 16 | (uint32_t)(packet[index + 2]) << 8 | packet[index + 3]; } +/** + * @brief Check for null or empty string + */ static inline bool mdns_utils_str_null_or_empty(const char *str) { return (str == NULL || *str == 0); } -static inline void _mdns_result_update_ttl(mdns_result_t *r, uint32_t ttl) -{ - r->ttl = r->ttl < ttl ? r->ttl : ttl; -} +/** + * @brief reads and formats MDNS FQDN into mdns_name_t structure + * + * @param packet MDNS packet + * @param start Starting point of FQDN + * @param name mdns_name_t structure to populate + * + * @return the address after the parsed FQDN in the packet or NULL on error + */ +const uint8_t *mdns_utils_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, size_t packet_len); +/** + * @brief reads MDNS FQDN into mdns_name_t structure + * FQDN is in format: [hostname.|[instance.]_service._proto.]local. + * + * @param packet MDNS packet + * @param start Starting point of FQDN + * @param name mdns_name_t structure to populate + * @param buf temporary char buffer + * + * @return the address after the parsed FQDN in the packet or NULL on error + */ +const uint8_t *mdns_utils_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len); -const uint8_t *_mdns_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, size_t packet_len); - -const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len); - -bool is_mdns_server(void); -//mdns_pcb_t *mdns_utils_get_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -const char *mdns_utils_get_global_hostname(void); -mdns_srv_item_t *mdns_utils_get_services(void); -mdns_host_item_t *mdns_utils_get_hosts(void); -mdns_host_item_t *mdns_utils_get_selfhost(void); -void mdns_utils_set_global_hostname(const char *hostname); -const char *mdns_utils_get_instance(void); -void mdns_utils_set_instance(const char *instance); -//mdns_search_once_t *mdns_utils_get_search(void); -//mdns_browse_t *mdns_utils_get_browse(void); -//mdns_tx_packet_t *mdns_utils_get_tx_packet(void); -//bool mdns_utils_is_probing(mdns_rx_packet_t *packet); -//bool mdns_utils_is_pcb_after_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -//bool mdns_utils_is_pcb_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -//bool mdns_utils_after_probing(mdns_rx_packet_t *packet); -//void mdns_utils_probe_failed(mdns_rx_packet_t *packet); - -void _mdns_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after); -void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe); -void _mdns_restart_all_pcbs_no_instance(void); -void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); -void _mdns_restart_all_pcbs(void); -void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); -void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip); +/** + * @brief Check if IPv6 address is NULL + */ bool mdns_utils_ipv6_address_is_zero(esp_ip6_addr_t ip6); -void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet); - -bool _hostname_is_ours(const char *hostname); -bool _mdns_service_match(const mdns_service_t *srv, const char *service, const char *proto, - const char *hostname); -mdns_srv_item_t *_mdns_get_service_item(const char *service, const char *proto, const char *hostname); +/** + * @brief Checks if the hostname is ours + */ +bool mdns_utils_hostname_is_ours(const char *hostname); -mdns_srv_item_t *_mdns_get_service_item_instance(const char *instance, const char *service, const char *proto, - const char *hostname); +/** + * @brief Checks if given service matches with arguments + */ +bool mdns_utils_service_match(const mdns_service_t *srv, const char *service, const char *proto, + const char *hostname); -bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instance, const char *service, - const char *proto, const char *hostname); +/** + * @brief finds service from given service type + * @param server the server + * @param service service type to match + * @param proto proto to match + * @param hostname hostname of the service (if non-null) + * + * @return the service item if found or NULL on error + */ +mdns_srv_item_t *mdns_utils_get_service_item(const char *service, const char *proto, const char *hostname); -bool _mdns_instance_name_match(const char *lhs, const char *rhs); +/** + * @brief finds service from given instance, etc + */ +mdns_srv_item_t *mdns_utils_get_service_item_instance(const char *instance, const char *service, const char *proto, + const char *hostname); -const char *_mdns_get_default_instance_name(void); -const char *_mdns_get_service_instance_name(const mdns_service_t *service); +/** + * @brief returns true if the service matches with args + */ +bool mdns_utils_service_match_instance(const mdns_service_t *srv, const char *instance, const char *service, + const char *proto, const char *hostname); -mdns_ip_addr_t *copy_address_list(const mdns_ip_addr_t *address_list); -void free_address_list(mdns_ip_addr_t *address_list); -int append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt); -uint8_t _mdns_append_u16(uint8_t *packet, uint16_t *index, uint16_t value); -//--------------------------------------------- +/** + * @brief returns true if the two instances match + */ +bool mdns_utils_instance_name_match(const char *lhs, const char *rhs); +/** + * @brief Get service instance name + */ +const char *mdns_utils_get_service_instance_name(const mdns_service_t *service); -/// -//mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if); -//void _mdns_dup_interface(mdns_if_t tcpip_if); +/** + * @brief Copy address list + */ +mdns_ip_addr_t *mdns_utils_copy_address_list(const mdns_ip_addr_t *address_list); -void mdns_service_lock(void); -void mdns_service_unlock(void); +/** + * @brief Free address list + */ +void mdns_utils_free_address_list(mdns_ip_addr_t *address_list); -bool mdns_action_queue(mdns_action_t *action); -mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip); +/** + * @brief appends uint16_t in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 2 on success + */ +uint8_t mdns_utils_append_u16(uint8_t *packet, uint16_t *index, uint16_t value); From acd3c131c1f0fdcb37afce60edbf93cd6e33d773 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 24 Mar 2025 12:40:49 +0100 Subject: [PATCH 11/27] feat(mdns): Add service module --- components/mdns/CMakeLists.txt | 2 +- components/mdns/mdns.c | 658 ++++-------------- components/mdns/mdns_netif.c | 2 +- .../mdns/{mdns_responder.c => mdns_pcb.c} | 2 +- components/mdns/mdns_querier.c | 2 +- components/mdns/mdns_receive.c | 2 +- components/mdns/mdns_send.c | 7 +- components/mdns/mdns_service.c | 443 +++++++++++- components/mdns/private_include/mdns_pcb.h | 122 ++++ .../mdns/private_include/mdns_private.h | 23 +- .../mdns/private_include/mdns_responder.h | 106 +-- 11 files changed, 735 insertions(+), 634 deletions(-) rename components/mdns/{mdns_responder.c => mdns_pcb.c} (99%) create mode 100644 components/mdns/private_include/mdns_pcb.h diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 3ad426e9b8..e6a5c83448 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -13,7 +13,7 @@ endif() set(MDNS_MEMORY "mdns_mem_caps.c") set(MDNS_CORE "mdns.c" "mdns_receive.c" "mdns_utils.c" "mdns_debug.c" "mdns_browser.c" "mdns_send.c" "mdns_netif.c" - "mdns_querier.c" "mdns_responder.c") + "mdns_querier.c" "mdns_pcb.c" "mdns_service.c") #set(MDNS_CORE "mdns.c" ) idf_build_get_property(target IDF_TARGET) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 235b2a840f..79bcbf78b3 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -5,12 +5,7 @@ */ #include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" #include "esp_log.h" -#include "esp_random.h" #include "esp_check.h" #include "mdns.h" #include "mdns_private.h" @@ -23,19 +18,35 @@ #include "mdns_send.h" #include "mdns_receive.h" #include "mdns_querier.h" -#include "mdns_responder.h" +#include "mdns_pcb.h" mdns_server_t *_mdns_server = NULL; static mdns_host_item_t *_mdns_host_list = NULL; static mdns_host_item_t _mdns_self_host; -static const char *TAG = "mdns"; +static const char *TAG = "mdns_responder"; -static volatile TaskHandle_t _mdns_service_task_handle = NULL; -static SemaphoreHandle_t _mdns_service_semaphore = NULL; -static StackType_t *_mdns_stack_buffer; +esp_err_t mdns_responder_init(void) +{ + _mdns_server = (mdns_server_t *)mdns_mem_malloc(sizeof(mdns_server_t)); + if (!_mdns_server) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + memset((uint8_t *)_mdns_server, 0, sizeof(mdns_server_t)); + return ESP_OK; +} -esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); +void mdns_responder_free(void) +{ + if (_mdns_server == NULL) { + return; + } + mdns_mem_free((char *)_mdns_server->hostname); + mdns_mem_free((char *)_mdns_server->instance); + mdns_mem_free(_mdns_server); + _mdns_server = NULL; +} const char *mdns_priv_get_global_hostname(void) { @@ -111,14 +122,6 @@ static bool _mdns_can_add_more_services(void) #endif } -bool mdns_priv_queue_action(mdns_action_t *action) -{ - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - return false; - } - return true; -} - /** * @brief Send announcement on all active PCBs */ @@ -395,14 +398,7 @@ static void _mdns_free_service(mdns_service_t *service) mdns_mem_free(service); } -/** - * @brief Adds a delegated hostname to the linked list - * @param hostname Host name pointer - * @param address_list Address list - * @return true on success - * false if the host wasn't attached (this is our hostname, or alloc failure) so we have to free the structs - */ -static bool _mdns_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *address_list) +bool mdns_priv_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *address_list) { if (mdns_utils_hostname_is_ours(hostname)) { return false; @@ -442,9 +438,7 @@ static bool _mdns_delegate_hostname_set_address(const char *hostname, mdns_ip_ad return false; } - - -static void free_delegated_hostnames(void) +void mdns_responder_free_delegated_hostnames(void) { mdns_host_item_t *host = _mdns_host_list; while (host != NULL) { @@ -501,443 +495,8 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) return true; } -#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES -static inline char nibble_to_hex(int var) -{ - return var > 9 ? var - 10 + 'a' : var + '0'; -} -#endif - -/** - * @brief Performs interface changes based on system events or custom commands - */ -static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) -{ - if (!_mdns_server || mdns_if >= MDNS_MAX_INTERFACES) { - return; - } - if (action & MDNS_EVENT_ENABLE_IP4) { - mdns_priv_pcb_enable(mdns_if, MDNS_IP_PROTOCOL_V4); - } - if (action & MDNS_EVENT_ENABLE_IP6) { - mdns_priv_pcb_enable(mdns_if, MDNS_IP_PROTOCOL_V6); - } - if (action & MDNS_EVENT_DISABLE_IP4) { - mdns_priv_pcb_disable(mdns_if, MDNS_IP_PROTOCOL_V4); - } - if (action & MDNS_EVENT_DISABLE_IP6) { - mdns_priv_pcb_disable(mdns_if, MDNS_IP_PROTOCOL_V6); - } - if (action & MDNS_EVENT_ANNOUNCE_IP4) { - mdns_priv_pcb_announce(mdns_if, MDNS_IP_PROTOCOL_V4, NULL, 0, true); - } - if (action & MDNS_EVENT_ANNOUNCE_IP6) { - mdns_priv_pcb_announce(mdns_if, MDNS_IP_PROTOCOL_V6, NULL, 0, true); - } - -#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES -#ifdef CONFIG_LWIP_IPV4 - if (action & MDNS_EVENT_IP4_REVERSE_LOOKUP) { - esp_netif_ip_info_t if_ip_info; - if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(mdns_if), &if_ip_info) == ESP_OK) { - esp_ip4_addr_t *ip = &if_ip_info.ip; - char *reverse_query_name = NULL; - if (asprintf(&reverse_query_name, "%d.%d.%d.%d.in-addr", - esp_ip4_addr4_16(ip), esp_ip4_addr3_16(ip), - esp_ip4_addr2_16(ip), esp_ip4_addr1_16(ip)) > 0 && reverse_query_name) { - ESP_LOGD(TAG, "Registered reverse query: %s.arpa", reverse_query_name); - _mdns_delegate_hostname_add(reverse_query_name, NULL); - } - } - } -#endif /* CONFIG_LWIP_IPV4 */ -#ifdef CONFIG_LWIP_IPV6 - if (action & MDNS_EVENT_IP6_REVERSE_LOOKUP) { - esp_ip6_addr_t addr6; - if (!esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(mdns_if), &addr6) && !mdns_utils_ipv6_address_is_zero(addr6)) { - uint8_t *paddr = (uint8_t *)&addr6.addr; - const char sub[] = "ip6"; - const size_t query_name_size = 4 * sizeof(addr6.addr) /* (2 nibbles + 2 dots)/per byte of IP address */ + sizeof(sub); - char *reverse_query_name = mdns_mem_malloc(query_name_size); - if (reverse_query_name) { - char *ptr = &reverse_query_name[query_name_size]; // point to the end - memcpy(ptr - sizeof(sub), sub, sizeof(sub)); // copy the IP sub-domain - ptr -= sizeof(sub) + 1; // move before the sub-domain - while (reverse_query_name < ptr) { // continue populating reverse query from the end - *ptr-- = '.'; // nibble by nibble, until we reach the beginning - *ptr-- = nibble_to_hex(((*paddr) >> 4) & 0x0F); - *ptr-- = '.'; - *ptr-- = nibble_to_hex((*paddr) & 0x0F); - paddr++; - } - ESP_LOGD(TAG, "Registered reverse query: %s.arpa", reverse_query_name); - _mdns_delegate_hostname_add(reverse_query_name, NULL); - } - } - } -#endif /* CONFIG_LWIP_IPV6 */ -#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ -} -void mdns_priv_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) -{ - mdns_srv_item_t *service = _mdns_server->services; - - while (service) { - if (service->service->hostname && - strcmp(service->service->hostname, old_hostname) == 0) { - mdns_mem_free((char *)service->service->hostname); - service->service->hostname = mdns_mem_strdup(new_hostname); - } - service = service->next; - } -} - -/** - * @brief Free action data - */ -static void _mdns_free_action(mdns_action_t *action) -{ - switch (action->type) { - case ACTION_HOSTNAME_SET: - mdns_mem_free(action->data.hostname_set.hostname); - break; - case ACTION_INSTANCE_SET: - mdns_mem_free(action->data.instance); - break; - case ACTION_SEARCH_ADD: - case ACTION_SEARCH_SEND: - case ACTION_SEARCH_END: - mdns_priv_query_action(action, ACTION_CLEANUP); - break; - case ACTION_BROWSE_ADD: - case ACTION_BROWSE_END: - case ACTION_BROWSE_SYNC: - mdns_browse_action(action, ACTION_CLEANUP); - break; - case ACTION_TX_HANDLE: - mdns_send_action(action, ACTION_CLEANUP); - break; - case ACTION_RX_HANDLE: - mdns_priv_receive_action(action, ACTION_CLEANUP); - break; - case ACTION_DELEGATE_HOSTNAME_SET_ADDR: - case ACTION_DELEGATE_HOSTNAME_ADD: - mdns_mem_free((char *)action->data.delegate_hostname.hostname); - mdns_utils_free_address_list(action->data.delegate_hostname.address_list); - break; - case ACTION_DELEGATE_HOSTNAME_REMOVE: - mdns_mem_free((char *)action->data.delegate_hostname.hostname); - break; - default: - break; - } - mdns_mem_free(action); -} - -/** - * @brief Called from service thread to execute given action - */ -static void _mdns_execute_action(mdns_action_t *action) -{ - switch (action->type) { - case ACTION_SYSTEM_EVENT: - perform_event_action(action->data.sys_event.interface, action->data.sys_event.event_action); - break; - case ACTION_HOSTNAME_SET: - _mdns_send_bye_all_pcbs_no_instance(true); - mdns_priv_remap_self_service_hostname(_mdns_server->hostname, action->data.hostname_set.hostname); - mdns_mem_free((char *)_mdns_server->hostname); - _mdns_server->hostname = action->data.hostname_set.hostname; - _mdns_self_host.hostname = action->data.hostname_set.hostname; - mdns_priv_restart_all_pcbs(); - xSemaphoreGive(_mdns_server->action_sema); - break; - case ACTION_INSTANCE_SET: - _mdns_send_bye_all_pcbs_no_instance(false); - mdns_mem_free((char *)_mdns_server->instance); - _mdns_server->instance = action->data.instance; - mdns_priv_restart_all_pcbs_no_instance(); - - break; - case ACTION_SEARCH_ADD: - case ACTION_SEARCH_SEND: - case ACTION_SEARCH_END: - mdns_priv_query_action(action, ACTION_RUN); - break; - case ACTION_BROWSE_ADD: - case ACTION_BROWSE_SYNC: - case ACTION_BROWSE_END: - mdns_browse_action(action, ACTION_RUN); - break; - - case ACTION_TX_HANDLE: - mdns_send_action(action, ACTION_RUN); - break; - case ACTION_RX_HANDLE: - mdns_priv_receive_action(action, ACTION_RUN); - break; - case ACTION_DELEGATE_HOSTNAME_ADD: - if (!_mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, - action->data.delegate_hostname.address_list)) { - mdns_mem_free((char *)action->data.delegate_hostname.hostname); - mdns_utils_free_address_list(action->data.delegate_hostname.address_list); - } - xSemaphoreGive(_mdns_server->action_sema); - break; - case ACTION_DELEGATE_HOSTNAME_SET_ADDR: - if (!_mdns_delegate_hostname_set_address(action->data.delegate_hostname.hostname, - action->data.delegate_hostname.address_list)) { - mdns_utils_free_address_list(action->data.delegate_hostname.address_list); - } - mdns_mem_free((char *)action->data.delegate_hostname.hostname); - break; - case ACTION_DELEGATE_HOSTNAME_REMOVE: - _mdns_delegate_hostname_remove(action->data.delegate_hostname.hostname); - mdns_mem_free((char *)action->data.delegate_hostname.hostname); - break; - default: - break; - } - mdns_mem_free(action); -} - -/** - * @brief the main MDNS service task. Packets are received and parsed here - */ -static void _mdns_service_task(void *pvParameters) -{ - mdns_action_t *a = NULL; - for (;;) { - if (_mdns_server && _mdns_server->action_queue) { - if (xQueueReceive(_mdns_server->action_queue, &a, portMAX_DELAY) == pdTRUE) { - assert(a); - if (a->type == ACTION_TASK_STOP) { - break; - } - MDNS_SERVICE_LOCK(); - _mdns_execute_action(a); - MDNS_SERVICE_UNLOCK(); - } - } else { - vTaskDelay(500 * portTICK_PERIOD_MS); - } - } - _mdns_service_task_handle = NULL; - vTaskDelay(portMAX_DELAY); -} - -static void _mdns_timer_cb(void *arg) -{ - mdns_send_packets(); - mdns_priv_query_start_stop(); -} - -static esp_err_t _mdns_start_timer(void) -{ - esp_timer_create_args_t timer_conf = { - .callback = _mdns_timer_cb, - .arg = NULL, - .dispatch_method = ESP_TIMER_TASK, - .name = "mdns_timer" - }; - esp_err_t err = esp_timer_create(&timer_conf, &(_mdns_server->timer_handle)); - if (err) { - return err; - } - return esp_timer_start_periodic(_mdns_server->timer_handle, MDNS_TIMER_PERIOD_US); -} - -static esp_err_t _mdns_stop_timer(void) -{ - esp_err_t err = ESP_OK; - if (_mdns_server->timer_handle) { - err = esp_timer_stop(_mdns_server->timer_handle); - if (err) { - return err; - } - err = esp_timer_delete(_mdns_server->timer_handle); - } - return err; -} - -static esp_err_t _mdns_task_create_with_caps(void) -{ - esp_err_t ret = ESP_OK; - static StaticTask_t mdns_task_buffer; - - _mdns_stack_buffer = mdns_mem_task_malloc(MDNS_SERVICE_STACK_DEPTH); - ESP_GOTO_ON_FALSE(_mdns_stack_buffer != NULL, ESP_FAIL, err, TAG, "failed to allocate memory for the mDNS task's stack"); - - _mdns_service_task_handle = xTaskCreateStaticPinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, MDNS_TASK_PRIORITY, _mdns_stack_buffer, &mdns_task_buffer, MDNS_TASK_AFFINITY); - ESP_GOTO_ON_FALSE(_mdns_service_task_handle != NULL, ESP_FAIL, err, TAG, "failed to create task for the mDNS"); - - return ret; - -err: - mdns_mem_task_free(_mdns_stack_buffer); - return ret; -} - -/** - * @brief Start the service thread if not running - * - * @return - * - ESP_OK on success - * - ESP_FAIL on error - */ -static esp_err_t _mdns_service_task_start(void) -{ - esp_err_t ret = ESP_OK; - if (!_mdns_service_semaphore) { - _mdns_service_semaphore = xSemaphoreCreateMutex(); - ESP_RETURN_ON_FALSE(_mdns_service_semaphore != NULL, ESP_FAIL, TAG, "Failed to create the mDNS service lock"); - } - MDNS_SERVICE_LOCK(); - ESP_GOTO_ON_ERROR(_mdns_start_timer(), err, TAG, "Failed to start the mDNS service timer"); - - if (!_mdns_service_task_handle) { - ESP_GOTO_ON_ERROR(_mdns_task_create_with_caps(), err_stop_timer, TAG, "Failed to start the mDNS service task"); -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) && !CONFIG_IDF_TARGET_LINUX - StackType_t *mdns_debug_stack_buffer; - StaticTask_t *mdns_debug_task_buffer; - xTaskGetStaticBuffers(_mdns_service_task_handle, &mdns_debug_stack_buffer, &mdns_debug_task_buffer); - ESP_LOGD(TAG, "mdns_debug_stack_buffer:%p mdns_debug_task_buffer:%p\n", mdns_debug_stack_buffer, mdns_debug_task_buffer); -#endif // CONFIG_IDF_TARGET_LINUX - } - MDNS_SERVICE_UNLOCK(); - return ret; - -err_stop_timer: - _mdns_stop_timer(); -err: - MDNS_SERVICE_UNLOCK(); - vSemaphoreDelete(_mdns_service_semaphore); - _mdns_service_semaphore = NULL; - return ret; -} - -/** - * @brief Stop the service thread - * - * @return - * - ESP_OK - */ -static esp_err_t _mdns_service_task_stop(void) -{ - _mdns_stop_timer(); - if (_mdns_service_task_handle) { - TaskHandle_t task_handle = _mdns_service_task_handle; - mdns_action_t action; - mdns_action_t *a = &action; - action.type = ACTION_TASK_STOP; - if (xQueueSend(_mdns_server->action_queue, &a, (TickType_t)0) != pdPASS) { - _mdns_service_task_handle = NULL; - } - while (_mdns_service_task_handle) { - vTaskDelay(10 / portTICK_PERIOD_MS); - } - vTaskDelete(task_handle); - } - vSemaphoreDelete(_mdns_service_semaphore); - _mdns_service_semaphore = NULL; - return ESP_OK; -} - -void mdns_priv_service_lock(void) -{ - MDNS_SERVICE_LOCK(); -} - -void mdns_priv_service_unlock(void) -{ - MDNS_SERVICE_UNLOCK(); -} - -esp_err_t mdns_init(void) -{ - esp_err_t err = ESP_OK; - - if (_mdns_server) { - return err; - } - - _mdns_server = (mdns_server_t *)mdns_mem_malloc(sizeof(mdns_server_t)); - if (!_mdns_server) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; - } - memset((uint8_t *)_mdns_server, 0, sizeof(mdns_server_t)); - - _mdns_server->action_queue = xQueueCreate(MDNS_ACTION_QUEUE_LEN, sizeof(mdns_action_t *)); - if (!_mdns_server->action_queue) { - err = ESP_ERR_NO_MEM; - goto free_server; - } - - _mdns_server->action_sema = xSemaphoreCreateBinary(); - if (!_mdns_server->action_sema) { - err = ESP_ERR_NO_MEM; - goto free_queue; - } - - - if (mdns_netif_init() != ESP_OK) { - err = ESP_FAIL; - goto free_action_sema; - } - - if (_mdns_service_task_start()) { - //service start failed! - err = ESP_FAIL; - goto free_all_and_disable_pcbs; - } - - return ESP_OK; - -free_all_and_disable_pcbs: - mdns_netif_deinit(); -free_action_sema: - vSemaphoreDelete(_mdns_server->action_sema); -free_queue: - vQueueDelete(_mdns_server->action_queue); -free_server: - mdns_mem_free(_mdns_server); - _mdns_server = NULL; - return err; -} - -void mdns_free(void) -{ - if (!_mdns_server) { - return; - } - - // Unregister handlers before destroying the mdns internals to avoid receiving async events while deinit - mdns_netif_unregister_predefined_handlers(); - - mdns_service_remove_all(); - free_delegated_hostnames(); - _mdns_service_task_stop(); - // at this point, the service task is deleted, so we can destroy the stack size - mdns_mem_task_free(_mdns_stack_buffer); - mdns_priv_pcb_deinit(); - mdns_mem_free((char *)_mdns_server->hostname); - mdns_mem_free((char *)_mdns_server->instance); - if (_mdns_server->action_queue) { - mdns_action_t *c; - while (xQueueReceive(_mdns_server->action_queue, &c, 0) == pdTRUE) { - _mdns_free_action(c); - } - vQueueDelete(_mdns_server->action_queue); - } - _mdns_clear_tx_queue_head(); - mdns_priv_query_free(); - mdns_browse_free(); - vSemaphoreDelete(_mdns_server->action_sema); - mdns_mem_free(_mdns_server); - _mdns_server = NULL; -} +/*** SPLIT POINT ***/ esp_err_t mdns_hostname_set(const char *hostname) { @@ -960,12 +519,12 @@ esp_err_t mdns_hostname_set(const char *hostname) } action->type = ACTION_HOSTNAME_SET; action->data.hostname_set.hostname = new_hostname; - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(new_hostname); mdns_mem_free(action); return ESP_ERR_NO_MEM; } - xSemaphoreTake(_mdns_server->action_sema, portMAX_DELAY); + mdns_priv_wait_action_complete(); return ESP_OK; } @@ -979,11 +538,11 @@ esp_err_t mdns_hostname_get(char *hostname) return ESP_ERR_INVALID_STATE; } - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); size_t len = strnlen(_mdns_server->hostname, MDNS_NAME_BUF_LEN - 1); strncpy(hostname, _mdns_server->hostname, len); hostname[len] = 0; - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ESP_OK; } @@ -1009,12 +568,12 @@ esp_err_t mdns_delegate_hostname_add(const char *hostname, const mdns_ip_addr_t action->type = ACTION_DELEGATE_HOSTNAME_ADD; action->data.delegate_hostname.hostname = new_hostname; action->data.delegate_hostname.address_list = mdns_utils_copy_address_list(address_list); - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(new_hostname); mdns_mem_free(action); return ESP_ERR_NO_MEM; } - xSemaphoreTake(_mdns_server->action_sema, portMAX_DELAY); + mdns_priv_wait_action_complete(); return ESP_OK; } @@ -1039,7 +598,7 @@ esp_err_t mdns_delegate_hostname_remove(const char *hostname) } action->type = ACTION_DELEGATE_HOSTNAME_REMOVE; action->data.delegate_hostname.hostname = new_hostname; - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(new_hostname); mdns_mem_free(action); return ESP_ERR_NO_MEM; @@ -1069,7 +628,7 @@ esp_err_t mdns_delegate_hostname_set_address(const char *hostname, const mdns_ip action->type = ACTION_DELEGATE_HOSTNAME_SET_ADDR; action->data.delegate_hostname.hostname = new_hostname; action->data.delegate_hostname.address_list = mdns_utils_copy_address_list(address_list); - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(new_hostname); mdns_mem_free(action); return ESP_ERR_NO_MEM; @@ -1080,9 +639,9 @@ esp_err_t mdns_delegate_hostname_set_address(const char *hostname, const mdns_ip bool mdns_hostname_exists(const char *hostname) { bool ret = false; - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); ret = mdns_utils_hostname_is_ours(hostname); - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; } @@ -1107,7 +666,7 @@ esp_err_t mdns_instance_name_set(const char *instance) } action->type = ACTION_INSTANCE_SET; action->data.instance = new_instance; - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(new_instance); mdns_mem_free(action); return ESP_ERR_NO_MEM; @@ -1126,7 +685,7 @@ esp_err_t mdns_service_add_for_host(const char *instance, const char *service, c return ESP_ERR_INVALID_ARG; } - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); esp_err_t ret = ESP_OK; const char *hostname = host ? host : _mdns_server->hostname; mdns_service_t *s = NULL; @@ -1149,11 +708,11 @@ esp_err_t mdns_service_add_for_host(const char *instance, const char *service, c item->next = _mdns_server->services; _mdns_server->services = item; mdns_responder_probe_all_pcbs(&item, 1, false, false); - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ESP_OK; err: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); _mdns_free_service(s); if (ret == ESP_ERR_NO_MEM) { HOOK_MALLOC_FAILED; @@ -1173,9 +732,9 @@ esp_err_t mdns_service_add(const char *instance, const char *service, const char bool mdns_service_exists(const char *service_type, const char *proto, const char *hostname) { bool ret = false; - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); ret = mdns_utils_get_service_item(service_type, proto, hostname) != NULL; - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; } @@ -1183,9 +742,9 @@ bool mdns_service_exists_with_instance(const char *instance, const char *service const char *hostname) { bool ret = false; - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); ret = mdns_utils_get_service_item_instance(instance, service_type, proto, hostname) != NULL; - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; } @@ -1336,7 +895,7 @@ static mdns_result_t *_mdns_lookup_service(const char *instance, const char *ser esp_err_t mdns_service_port_set_for_host(const char *instance, const char *service, const char *proto, const char *host, uint16_t port) { - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); esp_err_t ret = ESP_OK; const char *hostname = host ? host : _mdns_server->hostname; ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && port, @@ -1348,7 +907,7 @@ esp_err_t mdns_service_port_set_for_host(const char *instance, const char *servi _mdns_announce_all_pcbs(&s, 1, true); err: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; } @@ -1363,7 +922,7 @@ esp_err_t mdns_service_port_set(const char *service, const char *proto, uint16_t esp_err_t mdns_service_txt_set_for_host(const char *instance, const char *service, const char *proto, const char *host, mdns_txt_item_t txt_items[], uint8_t num_items) { - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); esp_err_t ret = ESP_OK; const char *hostname = host ? host : _mdns_server->hostname; ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !(num_items && txt_items == NULL), @@ -1386,7 +945,7 @@ esp_err_t mdns_service_txt_set_for_host(const char *instance, const char *servic _mdns_announce_all_pcbs(&s, 1, false); err: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; } @@ -1401,7 +960,7 @@ esp_err_t mdns_service_txt_set(const char *service, const char *proto, mdns_txt_ esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char *instance, const char *service, const char *proto, const char *host, const char *key, const char *value_arg, uint8_t value_len) { - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); esp_err_t ret = ESP_OK; char *value = NULL; mdns_txt_linked_item_t *new_txt = NULL; @@ -1444,10 +1003,10 @@ esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char _mdns_announce_all_pcbs(&s, 1, false); err: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; out_of_mem: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); HOOK_MALLOC_FAILED; mdns_mem_free(value); mdns_mem_free(new_txt); @@ -1483,7 +1042,7 @@ esp_err_t mdns_service_txt_item_set_with_explicit_value_len(const char *service, esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char *service, const char *proto, const char *host, const char *key) { - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); esp_err_t ret = ESP_OK; const char *hostname = host ? host : _mdns_server->hostname; ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(key), @@ -1520,7 +1079,7 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char _mdns_announce_all_pcbs(&s, 1, false); err: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); if (ret == ESP_ERR_NO_MEM) { HOOK_MALLOC_FAILED; } @@ -1567,7 +1126,7 @@ static esp_err_t _mdns_service_subtype_remove_for_host(mdns_srv_item_t *service, esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const char *service, const char *proto, const char *hostname, const char *subtype) { - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); esp_err_t ret = ESP_OK; ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(subtype), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); @@ -1588,12 +1147,12 @@ esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const _mdns_send_bye_subtype(s, instance_name, remove_subtypes); _mdns_free_subtype(remove_subtypes); err: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; out_of_mem: HOOK_MALLOC_FAILED; mdns_mem_free(remove_subtypes); - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; } @@ -1624,7 +1183,7 @@ static esp_err_t _mdns_service_subtype_add_for_host(mdns_srv_item_t *service, co esp_err_t mdns_service_subtype_add_multiple_items_for_host(const char *instance_name, const char *service, const char *proto, const char *hostname, mdns_subtype_item_t subtype[], uint8_t num_items) { - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); esp_err_t ret = ESP_OK; int cur_index = 0; ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && @@ -1654,7 +1213,7 @@ esp_err_t mdns_service_subtype_add_multiple_items_for_host(const char *instance_ } } exit: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; } @@ -1719,7 +1278,7 @@ static mdns_subtype_t *_mdns_service_find_subtype_needed_sendbye(mdns_service_t esp_err_t mdns_service_subtype_update_multiple_items_for_host(const char *instance_name, const char *service_type, const char *proto, const char *hostname, mdns_subtype_item_t subtype[], uint8_t num_items) { - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); esp_err_t ret = ESP_OK; int cur_index = 0; ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service_type) && !_str_null_or_empty(proto), @@ -1759,14 +1318,14 @@ esp_err_t mdns_service_subtype_update_multiple_items_for_host(const char *instan } } exit: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; } esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, const char *service, const char *proto, const char *host, const char *instance) { - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); esp_err_t ret = ESP_OK; const char *hostname = host ? host : _mdns_server->hostname; @@ -1785,7 +1344,7 @@ esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, cons mdns_responder_probe_all_pcbs(&s, 1, false, false); err: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; } @@ -1799,7 +1358,7 @@ esp_err_t mdns_service_instance_name_set(const char *service, const char *proto, esp_err_t mdns_service_remove_for_host(const char *instance, const char *service, const char *proto, const char *host) { - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); esp_err_t ret = ESP_OK; const char *hostname = host ? host : _mdns_server->hostname; ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto), @@ -1846,7 +1405,7 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service } err: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; } @@ -1860,7 +1419,7 @@ esp_err_t mdns_service_remove(const char *service_type, const char *proto) esp_err_t mdns_service_remove_all(void) { - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); esp_err_t ret = ESP_OK; ESP_GOTO_ON_FALSE(_mdns_server, ESP_ERR_INVALID_ARG, done, TAG, "Invalid state"); if (!_mdns_server->services) { @@ -1879,7 +1438,7 @@ esp_err_t mdns_service_remove_all(void) } done: - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ret; } @@ -1892,9 +1451,9 @@ esp_err_t mdns_lookup_delegated_service(const char *instance, const char *servic if (!result || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); *result = _mdns_lookup_service(instance, service, proto, max_results, false); - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ESP_OK; } @@ -1907,8 +1466,87 @@ esp_err_t mdns_lookup_selfhosted_service(const char *instance, const char *servi if (!result || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } - MDNS_SERVICE_LOCK(); + mdns_priv_service_lock(); *result = _mdns_lookup_service(instance, service, proto, max_results, true); - MDNS_SERVICE_UNLOCK(); + mdns_priv_service_unlock(); return ESP_OK; } + +void mdns_priv_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) +{ + mdns_srv_item_t *service = _mdns_server->services; + + while (service) { + if (service->service->hostname && + strcmp(service->service->hostname, old_hostname) == 0) { + mdns_mem_free((char *)service->service->hostname); + service->service->hostname = mdns_mem_strdup(new_hostname); + } + service = service->next; + } +} + +void mdns_priv_responder_action(mdns_action_t *action, mdns_action_subtype_t type) +{ + if (type == ACTION_RUN) { + switch (action->type) { + case ACTION_HOSTNAME_SET: + _mdns_send_bye_all_pcbs_no_instance(true); + mdns_priv_remap_self_service_hostname(_mdns_server->hostname, action->data.hostname_set.hostname); + mdns_mem_free((char *)_mdns_server->hostname); + _mdns_server->hostname = action->data.hostname_set.hostname; + _mdns_self_host.hostname = action->data.hostname_set.hostname; + mdns_priv_restart_all_pcbs(); + break; + case ACTION_INSTANCE_SET: + _mdns_send_bye_all_pcbs_no_instance(false); + mdns_mem_free((char *)_mdns_server->instance); + _mdns_server->instance = action->data.instance; + mdns_priv_restart_all_pcbs_no_instance(); + break; + case ACTION_DELEGATE_HOSTNAME_ADD: + if (!mdns_priv_delegate_hostname_add(action->data.delegate_hostname.hostname, + action->data.delegate_hostname.address_list)) { + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + mdns_utils_free_address_list(action->data.delegate_hostname.address_list); + } + break; + case ACTION_DELEGATE_HOSTNAME_SET_ADDR: + if (!_mdns_delegate_hostname_set_address(action->data.delegate_hostname.hostname, + action->data.delegate_hostname.address_list)) { + mdns_utils_free_address_list(action->data.delegate_hostname.address_list); + } + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + break; + case ACTION_DELEGATE_HOSTNAME_REMOVE: + _mdns_delegate_hostname_remove(action->data.delegate_hostname.hostname); + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + break; + default: + abort(); + } + return; + } + if (type == ACTION_CLEANUP) { + switch (action->type) { + case ACTION_HOSTNAME_SET: + mdns_mem_free(action->data.hostname_set.hostname); + break; + case ACTION_INSTANCE_SET: + mdns_mem_free(action->data.instance); + break; + case ACTION_DELEGATE_HOSTNAME_SET_ADDR: + case ACTION_DELEGATE_HOSTNAME_ADD: + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + mdns_utils_free_address_list(action->data.delegate_hostname.address_list); + break; + case ACTION_DELEGATE_HOSTNAME_REMOVE: + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + break; + default: + abort(); + } + return; + } + +} diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c index 13c1cef6d3..ce1b15c7e8 100644 --- a/components/mdns/mdns_netif.c +++ b/components/mdns/mdns_netif.c @@ -17,7 +17,7 @@ #include "mdns_browser.h" #include "mdns_netif.h" #include "mdns_send.h" -#include "mdns_responder.h" +#include "mdns_pcb.h" static const char *TAG = "mdns_netif"; diff --git a/components/mdns/mdns_responder.c b/components/mdns/mdns_pcb.c similarity index 99% rename from components/mdns/mdns_responder.c rename to components/mdns/mdns_pcb.c index 1667ac3464..04fca0fd7c 100644 --- a/components/mdns/mdns_responder.c +++ b/components/mdns/mdns_pcb.c @@ -6,7 +6,7 @@ #include #include "mdns_private.h" #include "mdns_networking.h" -#include "mdns_responder.h" +#include "mdns_pcb.h" #include "mdns_netif.h" #include "mdns_utils.h" #include "mdns_send.h" diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index 3fe29f7bb7..9cbf209c3f 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -10,7 +10,7 @@ #include "mdns_utils.h" #include "mdns_send.h" #include "esp_log.h" -#include "mdns_responder.h" +#include "mdns_pcb.h" #include "mdns_netif.h" static const char *TAG = "mdns_querier"; diff --git a/components/mdns/mdns_receive.c b/components/mdns/mdns_receive.c index 1727f6b510..82f588198c 100644 --- a/components/mdns/mdns_receive.c +++ b/components/mdns/mdns_receive.c @@ -16,7 +16,7 @@ #include "mdns_send.h" #include "mdns_browser.h" #include "mdns_querier.h" -#include "mdns_responder.h" +#include "mdns_pcb.h" static const char *TAG = "mdns_packet"; diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index 897ce29749..f15d84d944 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -13,7 +13,7 @@ #include "esp_log.h" #include "mdns_debug.h" #include "mdns_netif.h" -#include "mdns_responder.h" +#include "mdns_pcb.h" static const char *TAG = "mdns_send"; static const char *MDNS_SUB_STR = "_sub"; @@ -1732,11 +1732,6 @@ mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol return NULL; } -mdns_tx_packet_t *_mdns_get_next_tx_packet(void) -{ - return s_tx_queue_head; -} - /** * @brief Called from timer task to run mDNS responder * diff --git a/components/mdns/mdns_service.c b/components/mdns/mdns_service.c index 237d777894..bb2c827cbe 100644 --- a/components/mdns/mdns_service.c +++ b/components/mdns/mdns_service.c @@ -1,17 +1,442 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include #include "mdns_private.h" #include "mdns_networking.h" -#include "mdns_types.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_check.h" +#include "mdns.h" +#include "mdns_private.h" +#include "mdns_networking.h" +#include "mdns_mem_caps.h" +#include "mdns_utils.h" +#include "mdns_debug.h" +#include "mdns_browser.h" +#include "mdns_netif.h" +#include "mdns_send.h" +#include "mdns_receive.h" +#include "mdns_querier.h" +#include "mdns_pcb.h" +#include "mdns_responder.h" + + +static volatile TaskHandle_t _mdns_service_task_handle = NULL; +static SemaphoreHandle_t _mdns_service_semaphore = NULL; +static StackType_t *_mdns_stack_buffer; +static QueueHandle_t s_action_queue; +static SemaphoreHandle_t s_action_sema; +static esp_timer_handle_t s_timer_handle; + +static const char *TAG = "mdns_service"; + +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES +static inline char nibble_to_hex(int var) +{ + return var > 9 ? var - 10 + 'a' : var + '0'; +} +#endif + +/** + * @brief Performs interface changes based on system events or custom commands + */ +static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) +{ + if (!mdns_priv_is_server_init() || mdns_if >= MDNS_MAX_INTERFACES) { + return; + } + if (action & MDNS_EVENT_ENABLE_IP4) { + mdns_priv_pcb_enable(mdns_if, MDNS_IP_PROTOCOL_V4); + } + if (action & MDNS_EVENT_ENABLE_IP6) { + mdns_priv_pcb_enable(mdns_if, MDNS_IP_PROTOCOL_V6); + } + if (action & MDNS_EVENT_DISABLE_IP4) { + mdns_priv_pcb_disable(mdns_if, MDNS_IP_PROTOCOL_V4); + } + if (action & MDNS_EVENT_DISABLE_IP6) { + mdns_priv_pcb_disable(mdns_if, MDNS_IP_PROTOCOL_V6); + } + if (action & MDNS_EVENT_ANNOUNCE_IP4) { + mdns_priv_pcb_announce(mdns_if, MDNS_IP_PROTOCOL_V4, NULL, 0, true); + } + if (action & MDNS_EVENT_ANNOUNCE_IP6) { + mdns_priv_pcb_announce(mdns_if, MDNS_IP_PROTOCOL_V6, NULL, 0, true); + } + +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES +#ifdef CONFIG_LWIP_IPV4 + if (action & MDNS_EVENT_IP4_REVERSE_LOOKUP) { + esp_netif_ip_info_t if_ip_info; + if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(mdns_if), &if_ip_info) == ESP_OK) { + esp_ip4_addr_t *ip = &if_ip_info.ip; + char *reverse_query_name = NULL; + if (asprintf(&reverse_query_name, "%d.%d.%d.%d.in-addr", + esp_ip4_addr4_16(ip), esp_ip4_addr3_16(ip), + esp_ip4_addr2_16(ip), esp_ip4_addr1_16(ip)) > 0 && reverse_query_name) { + ESP_LOGD(TAG, "Registered reverse query: %s.arpa", reverse_query_name); + mdns_priv_delegate_hostname_add(reverse_query_name, NULL); + } + } + } +#endif /* CONFIG_LWIP_IPV4 */ +#ifdef CONFIG_LWIP_IPV6 + if (action & MDNS_EVENT_IP6_REVERSE_LOOKUP) { + esp_ip6_addr_t addr6; + if (!esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(mdns_if), &addr6) && !mdns_utils_ipv6_address_is_zero(addr6)) { + uint8_t *paddr = (uint8_t *)&addr6.addr; + const char sub[] = "ip6"; + const size_t query_name_size = 4 * sizeof(addr6.addr) /* (2 nibbles + 2 dots)/per byte of IP address */ + sizeof(sub); + char *reverse_query_name = mdns_mem_malloc(query_name_size); + if (reverse_query_name) { + char *ptr = &reverse_query_name[query_name_size]; // point to the end + memcpy(ptr - sizeof(sub), sub, sizeof(sub)); // copy the IP sub-domain + ptr -= sizeof(sub) + 1; // move before the sub-domain + while (reverse_query_name < ptr) { // continue populating reverse query from the end + *ptr-- = '.'; // nibble by nibble, until we reach the beginning + *ptr-- = nibble_to_hex(((*paddr) >> 4) & 0x0F); + *ptr-- = '.'; + *ptr-- = nibble_to_hex((*paddr) & 0x0F); + paddr++; + } + ESP_LOGD(TAG, "Registered reverse query: %s.arpa", reverse_query_name); + mdns_priv_delegate_hostname_add(reverse_query_name, NULL); + } + } + } +#endif /* CONFIG_LWIP_IPV6 */ +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ +} + + + +/** + * @brief Free action data + */ +static void _mdns_free_action(mdns_action_t *action) +{ + switch (action->type) { + case ACTION_SEARCH_ADD: + case ACTION_SEARCH_SEND: + case ACTION_SEARCH_END: + mdns_priv_query_action(action, ACTION_CLEANUP); + break; + case ACTION_BROWSE_ADD: + case ACTION_BROWSE_END: + case ACTION_BROWSE_SYNC: + mdns_browse_action(action, ACTION_CLEANUP); + break; + case ACTION_TX_HANDLE: + mdns_send_action(action, ACTION_CLEANUP); + break; + case ACTION_RX_HANDLE: + mdns_priv_receive_action(action, ACTION_CLEANUP); + break; + case ACTION_HOSTNAME_SET: + case ACTION_INSTANCE_SET: + case ACTION_DELEGATE_HOSTNAME_SET_ADDR: + case ACTION_DELEGATE_HOSTNAME_REMOVE: + case ACTION_DELEGATE_HOSTNAME_ADD: + mdns_priv_responder_action(action, ACTION_CLEANUP); + break; + default: + break; + } + mdns_mem_free(action); +} + +/** + * @brief Called from service thread to execute given action + */ +static void _mdns_execute_action(mdns_action_t *action) +{ + switch (action->type) { + case ACTION_SYSTEM_EVENT: + perform_event_action(action->data.sys_event.interface, action->data.sys_event.event_action); + break; + case ACTION_HOSTNAME_SET: + mdns_priv_responder_action(action, ACTION_RUN); + xSemaphoreGive(s_action_sema); + break; + case ACTION_INSTANCE_SET: + mdns_priv_responder_action(action, ACTION_RUN); + break; + case ACTION_SEARCH_ADD: + case ACTION_SEARCH_SEND: + case ACTION_SEARCH_END: + mdns_priv_query_action(action, ACTION_RUN); + break; + case ACTION_BROWSE_ADD: + case ACTION_BROWSE_SYNC: + case ACTION_BROWSE_END: + mdns_browse_action(action, ACTION_RUN); + break; + + case ACTION_TX_HANDLE: + mdns_send_action(action, ACTION_RUN); + break; + case ACTION_RX_HANDLE: + mdns_priv_receive_action(action, ACTION_RUN); + break; + case ACTION_DELEGATE_HOSTNAME_ADD: + mdns_priv_responder_action(action, ACTION_RUN); + xSemaphoreGive(s_action_sema); + break; + case ACTION_DELEGATE_HOSTNAME_SET_ADDR: + mdns_priv_responder_action(action, ACTION_RUN); + break; + case ACTION_DELEGATE_HOSTNAME_REMOVE: + mdns_priv_responder_action(action, ACTION_RUN); + break; + default: + break; + } + mdns_mem_free(action); +} + +/** + * @brief the main MDNS service task. Packets are received and parsed here + */ +static void _mdns_service_task(void *pvParameters) +{ + mdns_action_t *a = NULL; + for (;;) { + if (mdns_priv_is_server_init() && s_action_queue) { + if (xQueueReceive(s_action_queue, &a, portMAX_DELAY) == pdTRUE) { + assert(a); + if (a->type == ACTION_TASK_STOP) { + break; + } + MDNS_SERVICE_LOCK(); + _mdns_execute_action(a); + MDNS_SERVICE_UNLOCK(); + } + } else { + vTaskDelay(500 * portTICK_PERIOD_MS); + } + } + _mdns_service_task_handle = NULL; + vTaskDelete(NULL); +} + +static void _mdns_timer_cb(void *arg) +{ + mdns_send_packets(); + mdns_priv_query_start_stop(); +} + +static esp_err_t _mdns_start_timer(void) +{ + esp_timer_create_args_t timer_conf = { + .callback = _mdns_timer_cb, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "mdns_timer" + }; + esp_err_t err = esp_timer_create(&timer_conf, &(s_timer_handle)); + if (err) { + return err; + } + return esp_timer_start_periodic(s_timer_handle, MDNS_TIMER_PERIOD_US); +} + +static esp_err_t _mdns_stop_timer(void) +{ + esp_err_t err = ESP_OK; + if (s_timer_handle) { + err = esp_timer_stop(s_timer_handle); + if (err) { + return err; + } + err = esp_timer_delete(s_timer_handle); + } + return err; +} + +static esp_err_t _mdns_task_create_with_caps(void) +{ + esp_err_t ret = ESP_OK; + static StaticTask_t mdns_task_buffer; + + _mdns_stack_buffer = mdns_mem_task_malloc(MDNS_SERVICE_STACK_DEPTH); + ESP_GOTO_ON_FALSE(_mdns_stack_buffer != NULL, ESP_FAIL, err, TAG, "failed to allocate memory for the mDNS task's stack"); + + _mdns_service_task_handle = xTaskCreateStaticPinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, MDNS_TASK_PRIORITY, _mdns_stack_buffer, &mdns_task_buffer, MDNS_TASK_AFFINITY); + ESP_GOTO_ON_FALSE(_mdns_service_task_handle != NULL, ESP_FAIL, err, TAG, "failed to create task for the mDNS"); + + return ret; + +err: + mdns_mem_task_free(_mdns_stack_buffer); + return ret; +} + +/** + * @brief Start the service thread if not running + * + * @return + * - ESP_OK on success + * - ESP_FAIL on error + */ +static esp_err_t _mdns_service_task_start(void) +{ + esp_err_t ret = ESP_OK; + if (!_mdns_service_semaphore) { + _mdns_service_semaphore = xSemaphoreCreateMutex(); + ESP_RETURN_ON_FALSE(_mdns_service_semaphore != NULL, ESP_FAIL, TAG, "Failed to create the mDNS service lock"); + } + MDNS_SERVICE_LOCK(); + ESP_GOTO_ON_ERROR(_mdns_start_timer(), err, TAG, "Failed to start the mDNS service timer"); + + if (!_mdns_service_task_handle) { + ESP_GOTO_ON_ERROR(_mdns_task_create_with_caps(), err_stop_timer, TAG, "Failed to start the mDNS service task"); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) && !CONFIG_IDF_TARGET_LINUX + StackType_t *mdns_debug_stack_buffer; + StaticTask_t *mdns_debug_task_buffer; + xTaskGetStaticBuffers(_mdns_service_task_handle, &mdns_debug_stack_buffer, &mdns_debug_task_buffer); + ESP_LOGD(TAG, "mdns_debug_stack_buffer:%p mdns_debug_task_buffer:%p\n", mdns_debug_stack_buffer, mdns_debug_task_buffer); +#endif // CONFIG_IDF_TARGET_LINUX + } + MDNS_SERVICE_UNLOCK(); + return ret; + +err_stop_timer: + _mdns_stop_timer(); +err: + MDNS_SERVICE_UNLOCK(); + vSemaphoreDelete(_mdns_service_semaphore); + _mdns_service_semaphore = NULL; + return ret; +} + +/** + * @brief Stop the service thread + * + * @return + * - ESP_OK + */ +static esp_err_t _mdns_service_task_stop(void) +{ + _mdns_stop_timer(); + if (_mdns_service_task_handle) { + mdns_action_t action; + mdns_action_t *a = &action; + action.type = ACTION_TASK_STOP; + if (xQueueSend(s_action_queue, &a, (TickType_t)0) != pdPASS) { + vTaskDelete(_mdns_service_task_handle); + _mdns_service_task_handle = NULL; + } + while (_mdns_service_task_handle) { + vTaskDelay(10 / portTICK_PERIOD_MS); + } + } + vSemaphoreDelete(_mdns_service_semaphore); + _mdns_service_semaphore = NULL; + return ESP_OK; +} + +void mdns_priv_service_lock(void) +{ + MDNS_SERVICE_LOCK(); +} + +void mdns_priv_service_unlock(void) +{ + MDNS_SERVICE_UNLOCK(); +} + +esp_err_t mdns_init(void) +{ + esp_err_t err = ESP_OK; + + if (mdns_priv_is_server_init()) { + return err; + } + + if (mdns_responder_init() != ESP_OK) { + return ESP_ERR_NO_MEM; + } + + s_action_queue = xQueueCreate(MDNS_ACTION_QUEUE_LEN, sizeof(mdns_action_t *)); + if (!s_action_queue) { + err = ESP_ERR_NO_MEM; + goto free_server; + } + + s_action_sema = xSemaphoreCreateBinary(); + if (!s_action_sema) { + err = ESP_ERR_NO_MEM; + goto free_queue; + } + + + if (mdns_netif_init() != ESP_OK) { + err = ESP_FAIL; + goto free_action_sema; + } + + if (_mdns_service_task_start()) { + //service start failed! + err = ESP_FAIL; + goto free_all_and_disable_pcbs; + } + + return ESP_OK; + +free_all_and_disable_pcbs: + mdns_netif_deinit(); +free_action_sema: + vSemaphoreDelete(s_action_sema); +free_queue: + vQueueDelete(s_action_queue); +free_server: + mdns_responder_free(); + return err; +} + +void mdns_free(void) +{ + if (!mdns_priv_is_server_init()) { + return; + } + + // Unregister handlers before destroying the mdns internals to avoid receiving async events while deinit + mdns_netif_unregister_predefined_handlers(); + + mdns_service_remove_all(); + mdns_responder_free_delegated_hostnames(); + _mdns_service_task_stop(); + // at this point, the service task is deleted, so we can destroy the stack size + mdns_mem_task_free(_mdns_stack_buffer); + mdns_priv_pcb_deinit(); + if (s_action_queue) { + mdns_action_t *c; + while (xQueueReceive(s_action_queue, &c, 0) == pdTRUE) { + _mdns_free_action(c); + } + vQueueDelete(s_action_queue); + } + _mdns_clear_tx_queue_head(); + mdns_priv_query_free(); + mdns_browse_free(); + vSemaphoreDelete(s_action_sema); + mdns_responder_free(); +} -// Service management functions -static esp_err_t mdns_start_service_task(void); -static void mdns_service_task(void *pvParameters); -static void mdns_timer_cb(void *arg); +bool mdns_priv_queue_action(mdns_action_t *action) +{ + if (xQueueSend(s_action_queue, &action, (TickType_t)0) != pdPASS) { + return false; + } + return true; +} -// Action handling -static esp_err_t mdns_handle_system_event(mdns_action_t *action); -static esp_err_t mdns_handle_action(mdns_action_t *action); +void mdns_priv_wait_action_complete(void) +{ + xSemaphoreTake(s_action_sema, portMAX_DELAY); +} diff --git a/components/mdns/private_include/mdns_pcb.h b/components/mdns/private_include/mdns_pcb.h new file mode 100644 index 0000000000..4d9cef87cf --- /dev/null +++ b/components/mdns/private_include/mdns_pcb.h @@ -0,0 +1,122 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "mdns_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Disable the PCB for the selected interface and protocol + * @note Called from the main module (deinit and event handler) + */ +void mdns_priv_pcb_disable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Enable the PCB for the selected interface and protocol + * @note Called from the main module (deinit and event handler) + */ +void mdns_priv_pcb_enable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Set the interface as duplicate + * @note Called from the packet parser when checking for collisions + */ +void mdns_priv_pcb_set_duplicate(mdns_if_t tcpip_if); + +/** + * @brief Send announcement on particular PCB + * @note Called mainly from mdns.c to send announcements on all interfaces + */ +void mdns_priv_pcb_announce(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); + +/** + * @brief Checks if the PCB is OFF + * @note Called from mdns_send.c + */ +bool mdns_priv_pcb_is_off(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Schedules TX packets for various PCB states of probing and announcing + * @note Called from mdns_send.c + */ +void mdns_priv_pcb_schedule_tx_packet(mdns_tx_packet_t *p); + +/** + * @brief Update probing services on certain service removal + * @note Called from mdns_send.c upon removing scheduled packets for a service + */ +void mdns_priv_pcb_check_probing_services(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_service_t *service, bool removed_answers, bool *should_remove_questions); + +/** + * @brief Deinit pcbs + * @note Called from mdns_free() + */ +void mdns_priv_pcb_deinit(void); + +/** + * @brief Checks if the netif and PCB is initialized + * @note Called from mdns_send.c + */ +bool mdsn_priv_pcb_is_inited(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Checks if PCB is duplicated + * @note Called from mdns_send.c + */ +bool mdns_priv_pcb_is_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Checks if PCB is probing + * @note Called from mdns_receive.c + */ +bool mdns_priv_pcb_is_probing(mdns_rx_packet_t *packet); + +/** + * @brief Set probe failed to PCB + * @note Called from mdns_receive.c + */ +void mdns_priv_pcb_set_probe_failed(mdns_rx_packet_t *packet); + +/** + * @brief Checks if PCB completed probing + * @note Called from mdns_receive.c + */ +bool mdns_priv_pcb_is_after_probing(mdns_rx_packet_t *packet); + +/** + * @brief Checks if the selected interface has a duplicate + * @note Called from mdns_send.c + */ +bool mdns_priv_pcb_check_for_duplicates(mdns_if_t tcpip_if); + +/** + * @brief Sends bye for particular services on particular PCB + * @note Called from mdns.c + */ +void mdns_responder_send_bye_service(mdns_srv_item_t **services, size_t len, bool include_ip); + +/** + * @brief Send probe on all active PCBs + */ +void mdns_responder_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe); + +/** + * @brief Send probe for particular services on particular PCB + * + * Tests possible duplication on probing service structure and probes only for new entries. + * - If pcb probing then add only non-probing services and restarts probing + * - If pcb not probing, run probing for all specified services + */ +void mdns_responder_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip); + + +#ifdef __cplusplus +} +#endif diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 149e57d31c..7c009d39ac 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -402,11 +402,11 @@ typedef struct mdns_server_s { const char *hostname; const char *instance; mdns_srv_item_t *services; - QueueHandle_t action_queue; - SemaphoreHandle_t action_sema; +// QueueHandle_t action_queue; +// SemaphoreHandle_t action_sema; // mdns_tx_packet_t *tx_queue_head; // mdns_search_once_t *search_once; - esp_timer_handle_t timer_handle; +// esp_timer_handle_t timer_handle; // mdns_browse_t *browse; } mdns_server_t; @@ -513,4 +513,21 @@ void mdns_priv_service_unlock(void); */ bool mdns_priv_queue_action(mdns_action_t *action); +esp_err_t mdns_responder_init(void); + +void mdns_responder_free(void); + +void mdns_priv_wait_action_complete(void); + +/** + * @brief Adds a delegated hostname to the linked list + * @param hostname Host name pointer + * @param address_list Address list + * @return true on success + * false if the host wasn't attached (this is our hostname, or alloc failure) so we have to free the structs + */ +bool mdns_priv_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *address_list); + +void mdns_responder_free_delegated_hostnames(void); + #endif /* MDNS_PRIVATE_H_ */ diff --git a/components/mdns/private_include/mdns_responder.h b/components/mdns/private_include/mdns_responder.h index 4d9cef87cf..731d72d22b 100644 --- a/components/mdns/private_include/mdns_responder.h +++ b/components/mdns/private_include/mdns_responder.h @@ -13,108 +13,12 @@ extern "C" { #endif /** - * @brief Disable the PCB for the selected interface and protocol - * @note Called from the main module (deinit and event handler) - */ -void mdns_priv_pcb_disable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); - -/** - * @brief Enable the PCB for the selected interface and protocol - * @note Called from the main module (deinit and event handler) - */ -void mdns_priv_pcb_enable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); - -/** - * @brief Set the interface as duplicate - * @note Called from the packet parser when checking for collisions - */ -void mdns_priv_pcb_set_duplicate(mdns_if_t tcpip_if); - -/** - * @brief Send announcement on particular PCB - * @note Called mainly from mdns.c to send announcements on all interfaces - */ -void mdns_priv_pcb_announce(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); - -/** - * @brief Checks if the PCB is OFF - * @note Called from mdns_send.c - */ -bool mdns_priv_pcb_is_off(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); - -/** - * @brief Schedules TX packets for various PCB states of probing and announcing - * @note Called from mdns_send.c - */ -void mdns_priv_pcb_schedule_tx_packet(mdns_tx_packet_t *p); - -/** - * @brief Update probing services on certain service removal - * @note Called from mdns_send.c upon removing scheduled packets for a service - */ -void mdns_priv_pcb_check_probing_services(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_service_t *service, bool removed_answers, bool *should_remove_questions); - -/** - * @brief Deinit pcbs - * @note Called from mdns_free() - */ -void mdns_priv_pcb_deinit(void); - -/** - * @brief Checks if the netif and PCB is initialized - * @note Called from mdns_send.c - */ -bool mdsn_priv_pcb_is_inited(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +* @brief Perform action from mdns responder +* +* @note Called from the _mdns_service_task() in mdns.c +*/ +void mdns_priv_responder_action(mdns_action_t *action, mdns_action_subtype_t type); -/** - * @brief Checks if PCB is duplicated - * @note Called from mdns_send.c - */ -bool mdns_priv_pcb_is_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); - -/** - * @brief Checks if PCB is probing - * @note Called from mdns_receive.c - */ -bool mdns_priv_pcb_is_probing(mdns_rx_packet_t *packet); - -/** - * @brief Set probe failed to PCB - * @note Called from mdns_receive.c - */ -void mdns_priv_pcb_set_probe_failed(mdns_rx_packet_t *packet); - -/** - * @brief Checks if PCB completed probing - * @note Called from mdns_receive.c - */ -bool mdns_priv_pcb_is_after_probing(mdns_rx_packet_t *packet); - -/** - * @brief Checks if the selected interface has a duplicate - * @note Called from mdns_send.c - */ -bool mdns_priv_pcb_check_for_duplicates(mdns_if_t tcpip_if); - -/** - * @brief Sends bye for particular services on particular PCB - * @note Called from mdns.c - */ -void mdns_responder_send_bye_service(mdns_srv_item_t **services, size_t len, bool include_ip); - -/** - * @brief Send probe on all active PCBs - */ -void mdns_responder_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe); - -/** - * @brief Send probe for particular services on particular PCB - * - * Tests possible duplication on probing service structure and probes only for new entries. - * - If pcb probing then add only non-probing services and restarts probing - * - If pcb not probing, run probing for all specified services - */ -void mdns_responder_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip); #ifdef __cplusplus From 2005f3f0ae4d4c451c9efd2998d7b7b0fced8cc9 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 24 Mar 2025 13:51:36 +0100 Subject: [PATCH 12/27] fix(mdns): Forward porting 8ca45f34fa delete race --- components/mdns/mdns_service.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns_service.c b/components/mdns/mdns_service.c index bb2c827cbe..91404640c1 100644 --- a/components/mdns/mdns_service.c +++ b/components/mdns/mdns_service.c @@ -221,7 +221,7 @@ static void _mdns_service_task(void *pvParameters) } } _mdns_service_task_handle = NULL; - vTaskDelete(NULL); + vTaskDelay(portMAX_DELAY); } static void _mdns_timer_cb(void *arg) @@ -324,16 +324,17 @@ static esp_err_t _mdns_service_task_stop(void) { _mdns_stop_timer(); if (_mdns_service_task_handle) { + TaskHandle_t task_handle = _mdns_service_task_handle; mdns_action_t action; mdns_action_t *a = &action; action.type = ACTION_TASK_STOP; if (xQueueSend(s_action_queue, &a, (TickType_t)0) != pdPASS) { - vTaskDelete(_mdns_service_task_handle); _mdns_service_task_handle = NULL; } while (_mdns_service_task_handle) { vTaskDelay(10 / portTICK_PERIOD_MS); } + vTaskDelete(task_handle); } vSemaphoreDelete(_mdns_service_semaphore); _mdns_service_semaphore = NULL; From 2b15776530a467b82cc1432830a110d5ba697166 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 26 Mar 2025 12:29:45 +0100 Subject: [PATCH 13/27] fix(mdns): Minor cleanup --- components/mdns/CMakeLists.txt | 2 +- components/mdns/mdns_browser.c | 1 + components/mdns/mdns_netif.c | 3 +- components/mdns/mdns_networking_lwip.c | 5 +- components/mdns/mdns_pcb.c | 15 +- components/mdns/mdns_querier.c | 1 + components/mdns/mdns_receive.c | 11 +- components/mdns/{mdns.c => mdns_responder.c} | 530 +++++++++--------- components/mdns/mdns_send.c | 1 + components/mdns/mdns_service.c | 44 +- components/mdns/mdns_utils.c | 1 + components/mdns/private_include/mdns_pcb.h | 6 +- .../mdns/private_include/mdns_private.h | 84 --- .../mdns/private_include/mdns_responder.h | 78 +++ 14 files changed, 380 insertions(+), 402 deletions(-) rename components/mdns/{mdns.c => mdns_responder.c} (78%) diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index e6a5c83448..5f414e5212 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -12,7 +12,7 @@ endif() set(MDNS_MEMORY "mdns_mem_caps.c") -set(MDNS_CORE "mdns.c" "mdns_receive.c" "mdns_utils.c" "mdns_debug.c" "mdns_browser.c" "mdns_send.c" "mdns_netif.c" +set(MDNS_CORE "mdns_responder.c" "mdns_receive.c" "mdns_utils.c" "mdns_debug.c" "mdns_browser.c" "mdns_send.c" "mdns_netif.c" "mdns_querier.c" "mdns_pcb.c" "mdns_service.c") #set(MDNS_CORE "mdns.c" ) diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index 03fa753a7d..3476e3b064 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -11,6 +11,7 @@ #include "mdns_debug.h" #include "mdns_utils.h" #include "mdns_querier.h" +#include "mdns_responder.h" #include "mdns_netif.h" #include "esp_log.h" diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c index ce1b15c7e8..73edffed05 100644 --- a/components/mdns/mdns_netif.c +++ b/components/mdns/mdns_netif.c @@ -10,14 +10,13 @@ #include "esp_event.h" #include "mdns.h" #include "mdns_private.h" -#include "mdns_networking.h" #include "mdns_mem_caps.h" #include "mdns_utils.h" #include "mdns_debug.h" #include "mdns_browser.h" #include "mdns_netif.h" -#include "mdns_send.h" #include "mdns_pcb.h" +#include "mdns_responder.h" static const char *TAG = "mdns_netif"; diff --git a/components/mdns/mdns_networking_lwip.c b/components/mdns/mdns_networking_lwip.c index 4c9085878f..c7ae6d30a9 100644 --- a/components/mdns/mdns_networking_lwip.c +++ b/components/mdns/mdns_networking_lwip.c @@ -16,12 +16,11 @@ #include "lwip/udp.h" #include "lwip/mld6.h" #include "lwip/priv/tcpip_priv.h" -#include "esp_system.h" -#include "esp_event.h" #include "mdns_networking.h" #include "esp_netif_net_stack.h" #include "mdns_mem_caps.h" #include "mdns_utils.h" +#include "mdns_netif.h" /* * MDNS Server Networking @@ -57,7 +56,7 @@ static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) action->type = ACTION_RX_HANDLE; action->data.rx_handle.packet = packet; - if (!mdns_action_queue(action)) { + if (!mdns_priv_queue_action(action)) { mdns_mem_free(action); return ESP_ERR_NO_MEM; } diff --git a/components/mdns/mdns_pcb.c b/components/mdns/mdns_pcb.c index 04fca0fd7c..f559c0c43e 100644 --- a/components/mdns/mdns_pcb.c +++ b/components/mdns/mdns_pcb.c @@ -13,6 +13,7 @@ #include "mdns_mem_caps.h" #include "esp_log.h" #include "esp_random.h" +#include "mdns_responder.h" static const char *TAG = "mdns_responder"; @@ -36,7 +37,7 @@ void mdns_priv_pcb_announce(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, size_t i; if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { if (PCB_STATE_IS_PROBING(_pcb)) { - mdns_responder_init_pcb_probe(tcpip_if, ip_protocol, services, len, include_ip); + mdns_priv_init_pcb_probe(tcpip_if, ip_protocol, services, len, include_ip); } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { mdns_tx_packet_t *p = _mdns_get_next_pcb_packet(tcpip_if, ip_protocol); if (p) { @@ -121,7 +122,7 @@ static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol } if (srv_count == 0) { // proble only IP - mdns_responder_init_pcb_probe(tcpip_if, ip_protocol, NULL, 0, true); + mdns_priv_init_pcb_probe(tcpip_if, ip_protocol, NULL, 0, true); return; } mdns_srv_item_t *services[srv_count]; @@ -131,7 +132,7 @@ static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol services[i++] = a; a = a->next; } - mdns_responder_init_pcb_probe(tcpip_if, ip_protocol, services, srv_count, true); + mdns_priv_init_pcb_probe(tcpip_if, ip_protocol, services, srv_count, true); } /** @@ -376,7 +377,7 @@ static void _mdns_init_pcb_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protoco pcb->state = PCB_PROBE_1; } -void mdns_responder_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) +void mdns_priv_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) { mdns_pcb_t *pcb = &s_pcbs[tcpip_if][ip_protocol]; @@ -416,7 +417,7 @@ void mdns_responder_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_pro /** * @brief Send by for particular services */ -void mdns_responder_send_bye_service(mdns_srv_item_t **services, size_t len, bool include_ip) +void mdns_priv_pcb_send_bye_service(mdns_srv_item_t **services, size_t len, bool include_ip) { uint8_t i, j; if (mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { @@ -432,7 +433,7 @@ void mdns_responder_send_bye_service(mdns_srv_item_t **services, size_t len, boo } } -void mdns_responder_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe) +void mdns_priv_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe) { uint8_t i, j; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { @@ -445,7 +446,7 @@ void mdns_responder_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool _pcb->probe_services_len = 0; _pcb->probe_running = false; } - mdns_responder_init_pcb_probe((mdns_if_t) i, (mdns_ip_protocol_t) j, services, len, probe_ip); + mdns_priv_init_pcb_probe((mdns_if_t) i, (mdns_ip_protocol_t) j, services, len, probe_ip); } } } diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index 9cbf209c3f..023f9de3ae 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -12,6 +12,7 @@ #include "esp_log.h" #include "mdns_pcb.h" #include "mdns_netif.h" +#include "mdns_responder.h" static const char *TAG = "mdns_querier"; diff --git a/components/mdns/mdns_receive.c b/components/mdns/mdns_receive.c index 82f588198c..b7bc84e182 100644 --- a/components/mdns/mdns_receive.c +++ b/components/mdns/mdns_receive.c @@ -17,6 +17,7 @@ #include "mdns_browser.h" #include "mdns_querier.h" #include "mdns_pcb.h" +#include "mdns_responder.h" static const char *TAG = "mdns_packet"; @@ -1003,7 +1004,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) mdns_mem_free((char *)service->service->instance); service->service->instance = new_instance; } - mdns_responder_probe_all_pcbs(&service, 1, false, false); + mdns_priv_probe_all_pcbs(&service, 1, false, false); } else if (!mdns_utils_str_null_or_empty(mdns_priv_get_instance())) { char *new_instance = _mdns_mangle_name((char *) mdns_priv_get_instance()); if (new_instance) { @@ -1020,7 +1021,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } else if (service) { mdns_send_bye_pcb(packet->tcpip_if, packet->ip_protocol, &service, 1, false); - mdns_responder_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, false); + mdns_priv_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, false); } } } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions) { @@ -1093,7 +1094,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } if (col && !mdns_priv_pcb_is_probing(packet) && service) { do_not_reply = true; - mdns_responder_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); + mdns_priv_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); } else if (ttl > (MDNS_ANSWER_TXT_TTL / 2) && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( packet)) { _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); @@ -1150,7 +1151,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) mdns_priv_restart_all_pcbs(); } } else { - mdns_responder_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); + mdns_priv_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); } } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( packet)) { @@ -1209,7 +1210,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) mdns_priv_restart_all_pcbs(); } } else { - mdns_responder_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); + mdns_priv_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); } } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( packet)) { diff --git a/components/mdns/mdns.c b/components/mdns/mdns_responder.c similarity index 78% rename from components/mdns/mdns.c rename to components/mdns/mdns_responder.c index 79bcbf78b3..9aca73d010 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns_responder.c @@ -9,94 +9,107 @@ #include "esp_check.h" #include "mdns.h" #include "mdns_private.h" -#include "mdns_networking.h" #include "mdns_mem_caps.h" #include "mdns_utils.h" -#include "mdns_debug.h" -#include "mdns_browser.h" -#include "mdns_netif.h" #include "mdns_send.h" -#include "mdns_receive.h" #include "mdns_querier.h" #include "mdns_pcb.h" -mdns_server_t *_mdns_server = NULL; -static mdns_host_item_t *_mdns_host_list = NULL; -static mdns_host_item_t _mdns_self_host; +typedef struct mdns_server_s { + const char *hostname; + const char *instance; + mdns_srv_item_t *services; +} mdns_server_t; + +static mdns_server_t *s_mdns_server = NULL; +static mdns_host_item_t *s_mdns_host_list = NULL; +static mdns_host_item_t s_mdns_self_host; +static SemaphoreHandle_t s_action_sema; static const char *TAG = "mdns_responder"; -esp_err_t mdns_responder_init(void) +esp_err_t mdns_priv_responder_init(void) { - _mdns_server = (mdns_server_t *)mdns_mem_malloc(sizeof(mdns_server_t)); - if (!_mdns_server) { + s_mdns_server = (mdns_server_t *)mdns_mem_malloc(sizeof(mdns_server_t)); + if (!s_mdns_server) { HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } - memset((uint8_t *)_mdns_server, 0, sizeof(mdns_server_t)); + memset((uint8_t *)s_mdns_server, 0, sizeof(mdns_server_t)); + + s_action_sema = xSemaphoreCreateBinary(); + if (!s_action_sema) { + mdns_mem_free(s_mdns_server); + return ESP_ERR_NO_MEM; + } + return ESP_OK; } -void mdns_responder_free(void) +void mdns_priv_responder_free(void) { - if (_mdns_server == NULL) { + if (s_action_sema != NULL) { + vSemaphoreDelete(s_action_sema); + s_action_sema = NULL; + } + if (s_mdns_server == NULL) { return; } - mdns_mem_free((char *)_mdns_server->hostname); - mdns_mem_free((char *)_mdns_server->instance); - mdns_mem_free(_mdns_server); - _mdns_server = NULL; + mdns_mem_free((char *)s_mdns_server->hostname); + mdns_mem_free((char *)s_mdns_server->instance); + mdns_mem_free(s_mdns_server); + s_mdns_server = NULL; } const char *mdns_priv_get_global_hostname(void) { - return _mdns_server ? _mdns_server->hostname : NULL; + return s_mdns_server ? s_mdns_server->hostname : NULL; } mdns_srv_item_t *mdns_priv_get_services(void) { - return _mdns_server->services; + return s_mdns_server->services; } mdns_host_item_t *mdns_priv_get_hosts(void) { - return _mdns_host_list; + return s_mdns_host_list; } mdns_host_item_t *priv_get_self_host(void) { - return &_mdns_self_host; + return &s_mdns_self_host; } void mdns_priv_set_global_hostname(const char *hostname) { - if (_mdns_server) { - if (_mdns_server->hostname) { - mdns_mem_free((void *)_mdns_server->hostname); + if (s_mdns_server) { + if (s_mdns_server->hostname) { + mdns_mem_free((void *)s_mdns_server->hostname); } - _mdns_server->hostname = hostname; - _mdns_self_host.hostname = hostname; + s_mdns_server->hostname = hostname; + s_mdns_self_host.hostname = hostname; } } const char *mdns_priv_get_instance(void) { - return _mdns_server ? _mdns_server->instance : NULL; + return s_mdns_server ? s_mdns_server->instance : NULL; } void mdns_priv_set_instance(const char *instance) { - if (_mdns_server) { - if (_mdns_server->instance) { - mdns_mem_free((void *)_mdns_server->instance); + if (s_mdns_server) { + if (s_mdns_server->instance) { + mdns_mem_free((void *)s_mdns_server->instance); } - _mdns_server->instance = instance; + s_mdns_server->instance = instance; } } bool mdns_priv_is_server_init(void) { - return _mdns_server != NULL; + return s_mdns_server != NULL; } static inline bool _str_null_or_empty(const char *str) @@ -104,12 +117,12 @@ static inline bool _str_null_or_empty(const char *str) return (str == NULL || *str == 0); } -static bool _mdns_can_add_more_services(void) +static bool can_add_more_services(void) { #if MDNS_MAX_SERVICES == 0 return false; #else - mdns_srv_item_t *s = _mdns_server->services; + mdns_srv_item_t *s = s_mdns_server->services; uint16_t service_num = 0; while (s) { service_num ++; @@ -125,7 +138,7 @@ static bool _mdns_can_add_more_services(void) /** * @brief Send announcement on all active PCBs */ -static void _mdns_announce_all_pcbs(mdns_srv_item_t **services, size_t len, bool include_ip) +static void announce_all_pcbs(mdns_srv_item_t **services, size_t len, bool include_ip) { uint8_t i, j; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { @@ -136,13 +149,13 @@ static void _mdns_announce_all_pcbs(mdns_srv_item_t **services, size_t len, bool } /** - * @brief Restart the responder on all active PCBs + * @brief Send bye to all services */ -static void _mdns_send_final_bye(bool include_ip) +static void send_final_bye(bool include_ip) { - //collect all services and start probe + //collect all services to send bye packet size_t srv_count = 0; - mdns_srv_item_t *a = _mdns_server->services; + mdns_srv_item_t *a = s_mdns_server->services; while (a) { srv_count++; a = a->next; @@ -152,21 +165,21 @@ static void _mdns_send_final_bye(bool include_ip) } mdns_srv_item_t *services[srv_count]; size_t i = 0; - a = _mdns_server->services; + a = s_mdns_server->services; while (a) { services[i++] = a; a = a->next; } - mdns_responder_send_bye_service(services, srv_count, include_ip); + mdns_priv_pcb_send_bye_service(services, srv_count, include_ip); } /** * @brief Stop the responder on all services without instance */ -static void _mdns_send_bye_all_pcbs_no_instance(bool include_ip) +static void send_bye_all_pcbs_no_instance(bool include_ip) { size_t srv_count = 0; - mdns_srv_item_t *a = _mdns_server->services; + mdns_srv_item_t *a = s_mdns_server->services; while (a) { if (!a->service->instance) { srv_count++; @@ -178,20 +191,20 @@ static void _mdns_send_bye_all_pcbs_no_instance(bool include_ip) } mdns_srv_item_t *services[srv_count]; size_t i = 0; - a = _mdns_server->services; + a = s_mdns_server->services; while (a) { if (!a->service->instance) { services[i++] = a; } a = a->next; } - mdns_responder_send_bye_service(services, srv_count, include_ip); + mdns_priv_pcb_send_bye_service(services, srv_count, include_ip); } void mdns_priv_restart_all_pcbs_no_instance(void) { size_t srv_count = 0; - mdns_srv_item_t *a = _mdns_server->services; + mdns_srv_item_t *a = s_mdns_server->services; while (a) { if (!a->service->instance) { srv_count++; @@ -203,42 +216,40 @@ void mdns_priv_restart_all_pcbs_no_instance(void) } mdns_srv_item_t *services[srv_count]; size_t i = 0; - a = _mdns_server->services; + a = s_mdns_server->services; while (a) { if (!a->service->instance) { services[i++] = a; } a = a->next; } - mdns_responder_probe_all_pcbs(services, srv_count, false, true); + mdns_priv_probe_all_pcbs(services, srv_count, false, true); } void mdns_priv_restart_all_pcbs(void) { _mdns_clear_tx_queue_head(); size_t srv_count = 0; - mdns_srv_item_t *a = _mdns_server->services; + mdns_srv_item_t *a = s_mdns_server->services; while (a) { srv_count++; a = a->next; } if (srv_count == 0) { - mdns_responder_probe_all_pcbs(NULL, 0, true, true); + mdns_priv_probe_all_pcbs(NULL, 0, true, true); return; } mdns_srv_item_t *services[srv_count]; size_t l = 0; - a = _mdns_server->services; + a = s_mdns_server->services; while (a) { services[l++] = a; a = a->next; } - mdns_responder_probe_all_pcbs(services, srv_count, true, true); + mdns_priv_probe_all_pcbs(services, srv_count, true, true); } - - /** * @brief creates/allocates new text item list * @param num_items service number of txt items or 0 @@ -246,7 +257,7 @@ void mdns_priv_restart_all_pcbs(void) * * @return pointer to the linked txt item list or NULL */ -static mdns_txt_linked_item_t *_mdns_allocate_txt(size_t num_items, mdns_txt_item_t txt[]) +static mdns_txt_linked_item_t *allocate_txt(size_t num_items, mdns_txt_item_t txt[]) { mdns_txt_linked_item_t *new_txt = NULL; size_t i = 0; @@ -280,7 +291,7 @@ static mdns_txt_linked_item_t *_mdns_allocate_txt(size_t num_items, mdns_txt_ite * @brief Deallocate the txt linked list * @param txt pointer to the txt pointer to free, noop if txt==NULL */ -static void _mdns_free_linked_txt(mdns_txt_linked_item_t *txt) +static void free_linked_txt(mdns_txt_linked_item_t *txt) { mdns_txt_linked_item_t *t; while (txt) { @@ -304,9 +315,9 @@ static void _mdns_free_linked_txt(mdns_txt_linked_item_t *txt) * * @return pointer to the service or NULL on error */ -static mdns_service_t *_mdns_create_service(const char *service, const char *proto, const char *hostname, - uint16_t port, const char *instance, size_t num_items, - mdns_txt_item_t txt[]) +static mdns_service_t *create_service(const char *service, const char *proto, const char *hostname, + uint16_t port, const char *instance, size_t num_items, + mdns_txt_item_t txt[]) { mdns_service_t *s = (mdns_service_t *)mdns_mem_calloc(1, sizeof(mdns_service_t)); if (!s) { @@ -314,7 +325,7 @@ static mdns_service_t *_mdns_create_service(const char *service, const char *pro return NULL; } - mdns_txt_linked_item_t *new_txt = _mdns_allocate_txt(num_items, txt); + mdns_txt_linked_item_t *new_txt = allocate_txt(num_items, txt); if (num_items && new_txt == NULL) { goto fail; } @@ -347,7 +358,7 @@ static mdns_service_t *_mdns_create_service(const char *service, const char *pro return s; fail: - _mdns_free_linked_txt(s->txt); + free_linked_txt(s->txt); mdns_mem_free((char *)s->instance); mdns_mem_free((char *)s->service); mdns_mem_free((char *)s->proto); @@ -357,7 +368,7 @@ static mdns_service_t *_mdns_create_service(const char *service, const char *pro return NULL; } -static void _mdns_free_subtype(mdns_subtype_t *subtype) +static void free_subtype(mdns_subtype_t *subtype) { while (subtype) { mdns_subtype_t *next = subtype->next; @@ -367,9 +378,9 @@ static void _mdns_free_subtype(mdns_subtype_t *subtype) } } -static void _mdns_free_service_subtype(mdns_service_t *service) +static void free_service_subtype(mdns_service_t *service) { - _mdns_free_subtype(service->subtype); + free_subtype(service->subtype); service->subtype = NULL; } @@ -378,7 +389,7 @@ static void _mdns_free_service_subtype(mdns_service_t *service) * * @param service the service */ -static void _mdns_free_service(mdns_service_t *service) +static void free_service(mdns_service_t *service) { if (!service) { return; @@ -394,7 +405,7 @@ static void _mdns_free_service(mdns_service_t *service) mdns_mem_free((char *)s->value); mdns_mem_free(s); } - _mdns_free_service_subtype(service); + free_service_subtype(service); mdns_mem_free(service); } @@ -411,20 +422,18 @@ bool mdns_priv_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *addre } host->address_list = address_list; host->hostname = hostname; - host->next = _mdns_host_list; - _mdns_host_list = host; + host->next = s_mdns_host_list; + s_mdns_host_list = host; return true; } - - -static bool _mdns_delegate_hostname_set_address(const char *hostname, mdns_ip_addr_t *address_list) +static bool delegate_hostname_set_address(const char *hostname, mdns_ip_addr_t *address_list) { - if (!_str_null_or_empty(_mdns_server->hostname) && - strcasecmp(hostname, _mdns_server->hostname) == 0) { + if (!_str_null_or_empty(s_mdns_server->hostname) && + strcasecmp(hostname, s_mdns_server->hostname) == 0) { return false; } - mdns_host_item_t *host = _mdns_host_list; + mdns_host_item_t *host = s_mdns_host_list; while (host != NULL) { if (strcasecmp(hostname, host->hostname) == 0) { // free previous address list @@ -438,9 +447,9 @@ static bool _mdns_delegate_hostname_set_address(const char *hostname, mdns_ip_ad return false; } -void mdns_responder_free_delegated_hostnames(void) +void mdns_priv_free_delegated_hostnames(void) { - mdns_host_item_t *host = _mdns_host_list; + mdns_host_item_t *host = s_mdns_host_list; while (host != NULL) { mdns_utils_free_address_list(host->address_list); mdns_mem_free((char *)host->hostname); @@ -448,38 +457,38 @@ void mdns_responder_free_delegated_hostnames(void) host = host->next; mdns_mem_free(item); } - _mdns_host_list = NULL; + s_mdns_host_list = NULL; } -static bool _mdns_delegate_hostname_remove(const char *hostname) +static bool delegate_hostname_remove(const char *hostname) { - mdns_srv_item_t *srv = _mdns_server->services; + mdns_srv_item_t *srv = s_mdns_server->services; mdns_srv_item_t *prev_srv = NULL; while (srv) { if (strcasecmp(srv->service->hostname, hostname) == 0) { mdns_srv_item_t *to_free = srv; - mdns_responder_send_bye_service(&srv, 1, false); + mdns_priv_pcb_send_bye_service(&srv, 1, false); _mdns_remove_scheduled_service_packets(srv->service); if (prev_srv == NULL) { - _mdns_server->services = srv->next; + s_mdns_server->services = srv->next; srv = srv->next; } else { prev_srv->next = srv->next; srv = srv->next; } - _mdns_free_service(to_free->service); + free_service(to_free->service); mdns_mem_free(to_free); } else { prev_srv = srv; srv = srv->next; } } - mdns_host_item_t *host = _mdns_host_list; + mdns_host_item_t *host = s_mdns_host_list; mdns_host_item_t *prev_host = NULL; while (host != NULL) { if (strcasecmp(hostname, host->hostname) == 0) { if (prev_host == NULL) { - _mdns_host_list = host->next; + s_mdns_host_list = host->next; } else { prev_host->next = host->next; } @@ -495,12 +504,92 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) return true; } +void mdns_priv_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) +{ + mdns_srv_item_t *service = s_mdns_server->services; -/*** SPLIT POINT ***/ + while (service) { + if (service->service->hostname && + strcmp(service->service->hostname, old_hostname) == 0) { + mdns_mem_free((char *)service->service->hostname); + service->service->hostname = mdns_mem_strdup(new_hostname); + } + service = service->next; + } +} +void mdns_priv_responder_action(mdns_action_t *action, mdns_action_subtype_t type) +{ + if (type == ACTION_RUN) { + switch (action->type) { + case ACTION_HOSTNAME_SET: + send_bye_all_pcbs_no_instance(true); + mdns_priv_remap_self_service_hostname(s_mdns_server->hostname, action->data.hostname_set.hostname); + mdns_mem_free((char *)s_mdns_server->hostname); + s_mdns_server->hostname = action->data.hostname_set.hostname; + s_mdns_self_host.hostname = action->data.hostname_set.hostname; + mdns_priv_restart_all_pcbs(); + xSemaphoreGive(s_action_sema); + break; + case ACTION_INSTANCE_SET: + send_bye_all_pcbs_no_instance(false); + mdns_mem_free((char *)s_mdns_server->instance); + s_mdns_server->instance = action->data.instance; + mdns_priv_restart_all_pcbs_no_instance(); + break; + case ACTION_DELEGATE_HOSTNAME_ADD: + if (!mdns_priv_delegate_hostname_add(action->data.delegate_hostname.hostname, + action->data.delegate_hostname.address_list)) { + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + mdns_utils_free_address_list(action->data.delegate_hostname.address_list); + } + xSemaphoreGive(s_action_sema); + break; + case ACTION_DELEGATE_HOSTNAME_SET_ADDR: + if (!delegate_hostname_set_address(action->data.delegate_hostname.hostname, + action->data.delegate_hostname.address_list)) { + mdns_utils_free_address_list(action->data.delegate_hostname.address_list); + } + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + break; + case ACTION_DELEGATE_HOSTNAME_REMOVE: + delegate_hostname_remove(action->data.delegate_hostname.hostname); + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + break; + default: + abort(); + } + return; + } + if (type == ACTION_CLEANUP) { + switch (action->type) { + case ACTION_HOSTNAME_SET: + mdns_mem_free(action->data.hostname_set.hostname); + break; + case ACTION_INSTANCE_SET: + mdns_mem_free(action->data.instance); + break; + case ACTION_DELEGATE_HOSTNAME_SET_ADDR: + case ACTION_DELEGATE_HOSTNAME_ADD: + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + mdns_utils_free_address_list(action->data.delegate_hostname.address_list); + break; + case ACTION_DELEGATE_HOSTNAME_REMOVE: + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + break; + default: + abort(); + } + return; + } +} + +/** + * @ingroup PUBLIC_API + */ esp_err_t mdns_hostname_set(const char *hostname) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_ARG; } if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { @@ -524,7 +613,7 @@ esp_err_t mdns_hostname_set(const char *hostname) mdns_mem_free(action); return ESP_ERR_NO_MEM; } - mdns_priv_wait_action_complete(); + xSemaphoreTake(s_action_sema, portMAX_DELAY); return ESP_OK; } @@ -534,13 +623,13 @@ esp_err_t mdns_hostname_get(char *hostname) return ESP_ERR_INVALID_ARG; } - if (!_mdns_server || !_mdns_server->hostname) { + if (!s_mdns_server || !s_mdns_server->hostname) { return ESP_ERR_INVALID_STATE; } mdns_priv_service_lock(); - size_t len = strnlen(_mdns_server->hostname, MDNS_NAME_BUF_LEN - 1); - strncpy(hostname, _mdns_server->hostname, len); + size_t len = strnlen(s_mdns_server->hostname, MDNS_NAME_BUF_LEN - 1); + strncpy(hostname, s_mdns_server->hostname, len); hostname[len] = 0; mdns_priv_service_unlock(); return ESP_OK; @@ -548,7 +637,7 @@ esp_err_t mdns_hostname_get(char *hostname) esp_err_t mdns_delegate_hostname_add(const char *hostname, const mdns_ip_addr_t *address_list) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { @@ -573,13 +662,13 @@ esp_err_t mdns_delegate_hostname_add(const char *hostname, const mdns_ip_addr_t mdns_mem_free(action); return ESP_ERR_NO_MEM; } - mdns_priv_wait_action_complete(); + xSemaphoreTake(s_action_sema, portMAX_DELAY); return ESP_OK; } esp_err_t mdns_delegate_hostname_remove(const char *hostname) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { @@ -608,7 +697,7 @@ esp_err_t mdns_delegate_hostname_remove(const char *hostname) esp_err_t mdns_delegate_hostname_set_address(const char *hostname, const mdns_ip_addr_t *address_list) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { @@ -647,10 +736,10 @@ bool mdns_hostname_exists(const char *hostname) esp_err_t mdns_instance_name_set(const char *instance) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } - if (_str_null_or_empty(instance) || _mdns_server->hostname == NULL || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { + if (_str_null_or_empty(instance) || s_mdns_server->hostname == NULL || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } char *new_instance = mdns_mem_strndup(instance, MDNS_NAME_BUF_LEN - 1); @@ -674,29 +763,25 @@ esp_err_t mdns_instance_name_set(const char *instance) return ESP_OK; } -/* - * MDNS SERVICES - * */ - esp_err_t mdns_service_add_for_host(const char *instance, const char *service, const char *proto, const char *host, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !_mdns_server->hostname) { + if (!s_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !s_mdns_server->hostname) { return ESP_ERR_INVALID_ARG; } mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : _mdns_server->hostname; + const char *hostname = host ? host : s_mdns_server->hostname; mdns_service_t *s = NULL; - ESP_GOTO_ON_FALSE(_mdns_can_add_more_services(), ESP_ERR_NO_MEM, err, TAG, + ESP_GOTO_ON_FALSE(can_add_more_services(), ESP_ERR_NO_MEM, err, TAG, "Cannot add more services, please increase CONFIG_MDNS_MAX_SERVICES (%d)", CONFIG_MDNS_MAX_SERVICES); mdns_srv_item_t *item = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(!item, ESP_ERR_INVALID_ARG, err, TAG, "Service already exists"); - s = _mdns_create_service(service, proto, hostname, port, instance, num_items, txt); + s = create_service(service, proto, hostname, port, instance, num_items, txt); ESP_GOTO_ON_FALSE(s, ESP_ERR_NO_MEM, err, TAG, "Cannot create service: Out of memory"); item = (mdns_srv_item_t *)mdns_mem_malloc(sizeof(mdns_srv_item_t)); @@ -705,15 +790,15 @@ esp_err_t mdns_service_add_for_host(const char *instance, const char *service, c item->service = s; item->next = NULL; - item->next = _mdns_server->services; - _mdns_server->services = item; - mdns_responder_probe_all_pcbs(&item, 1, false, false); + item->next = s_mdns_server->services; + s_mdns_server->services = item; + mdns_priv_probe_all_pcbs(&item, 1, false, false); mdns_priv_service_unlock(); return ESP_OK; err: mdns_priv_service_unlock(); - _mdns_free_service(s); + free_service(s); if (ret == ESP_ERR_NO_MEM) { HOOK_MALLOC_FAILED; } @@ -723,7 +808,7 @@ esp_err_t mdns_service_add_for_host(const char *instance, const char *service, c esp_err_t mdns_service_add(const char *instance, const char *service, const char *proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_add_for_host(instance, service, proto, NULL, port, txt, num_items); @@ -748,7 +833,7 @@ bool mdns_service_exists_with_instance(const char *instance, const char *service return ret; } -static mdns_txt_item_t *_copy_mdns_txt_items(mdns_txt_linked_item_t *items, uint8_t **txt_value_len, size_t *txt_count) +static mdns_txt_item_t *copy_txt_items(mdns_txt_linked_item_t *items, uint8_t **txt_value_len, size_t *txt_count) { mdns_txt_item_t *ret = NULL; size_t ret_index = 0; @@ -801,9 +886,9 @@ static mdns_txt_item_t *_copy_mdns_txt_items(mdns_txt_linked_item_t *items, uint return NULL; } -static mdns_ip_addr_t *_copy_delegated_host_address_list(char *hostname) +static mdns_ip_addr_t *copy_delegated_host_address_list(char *hostname) { - mdns_host_item_t *host = _mdns_host_list; + mdns_host_item_t *host = s_mdns_host_list; while (host) { if (strcasecmp(host->hostname, hostname) == 0) { return mdns_utils_copy_address_list(host->address_list); @@ -813,22 +898,22 @@ static mdns_ip_addr_t *_copy_delegated_host_address_list(char *hostname) return NULL; } -static mdns_result_t *_mdns_lookup_service(const char *instance, const char *service, const char *proto, size_t max_results, bool selfhost) +static mdns_result_t *lookup_service(const char *instance, const char *service, const char *proto, size_t max_results, bool selfhost) { if (_str_null_or_empty(service) || _str_null_or_empty(proto)) { return NULL; } mdns_result_t *results = NULL; size_t num_results = 0; - mdns_srv_item_t *s = _mdns_server->services; + mdns_srv_item_t *s = s_mdns_server->services; while (s) { mdns_service_t *srv = s->service; if (!srv || !srv->hostname) { s = s->next; continue; } - bool is_service_selfhosted = !_str_null_or_empty(_mdns_server->hostname) && !strcasecmp(_mdns_server->hostname, srv->hostname); - bool is_service_delegated = _str_null_or_empty(_mdns_server->hostname) || strcasecmp(_mdns_server->hostname, srv->hostname); + bool is_service_selfhosted = !_str_null_or_empty(s_mdns_server->hostname) && !strcasecmp(s_mdns_server->hostname, srv->hostname); + bool is_service_delegated = _str_null_or_empty(s_mdns_server->hostname) || strcasecmp(s_mdns_server->hostname, srv->hostname); if ((selfhost && is_service_selfhosted) || (!selfhost && is_service_delegated)) { if (!strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && (_str_null_or_empty(instance) || mdns_utils_instance_name_match(srv->instance, instance))) { @@ -867,12 +952,12 @@ static mdns_result_t *_mdns_lookup_service(const char *instance, const char *ser goto handle_error; } item->port = srv->port; - item->txt = _copy_mdns_txt_items(srv->txt, &(item->txt_value_len), &(item->txt_count)); + item->txt = copy_txt_items(srv->txt, &(item->txt_value_len), &(item->txt_count)); // We should not append addresses for selfhost lookup result as we don't know which interface's address to append. if (selfhost) { item->addr = NULL; } else { - item->addr = _copy_delegated_host_address_list(item->hostname); + item->addr = copy_delegated_host_address_list(item->hostname); if (!item->addr) { goto handle_error; } @@ -897,14 +982,14 @@ esp_err_t mdns_service_port_set_for_host(const char *instance, const char *servi { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : _mdns_server->hostname; - ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && port, + const char *hostname = host ? host : s_mdns_server->hostname; + ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && port, ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); s->service->port = port; - _mdns_announce_all_pcbs(&s, 1, true); + announce_all_pcbs(&s, 1, true); err: mdns_priv_service_unlock(); @@ -913,7 +998,7 @@ esp_err_t mdns_service_port_set_for_host(const char *instance, const char *servi esp_err_t mdns_service_port_set(const char *service, const char *proto, uint16_t port) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_port_set_for_host(NULL, service, proto, NULL, port); @@ -924,15 +1009,15 @@ esp_err_t mdns_service_txt_set_for_host(const char *instance, const char *servic { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : _mdns_server->hostname; - ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !(num_items && txt_items == NULL), + const char *hostname = host ? host : s_mdns_server->hostname; + ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !(num_items && txt_items == NULL), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); mdns_txt_linked_item_t *new_txt = NULL; if (num_items) { - new_txt = _mdns_allocate_txt(num_items, txt_items); + new_txt = allocate_txt(num_items, txt_items); if (!new_txt) { return ESP_ERR_NO_MEM; } @@ -940,9 +1025,9 @@ esp_err_t mdns_service_txt_set_for_host(const char *instance, const char *servic mdns_service_t *srv = s->service; mdns_txt_linked_item_t *txt = srv->txt; srv->txt = NULL; - _mdns_free_linked_txt(txt); + free_linked_txt(txt); srv->txt = new_txt; - _mdns_announce_all_pcbs(&s, 1, false); + announce_all_pcbs(&s, 1, false); err: mdns_priv_service_unlock(); @@ -951,7 +1036,7 @@ esp_err_t mdns_service_txt_set_for_host(const char *instance, const char *servic esp_err_t mdns_service_txt_set(const char *service, const char *proto, mdns_txt_item_t txt[], uint8_t num_items) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_txt_set_for_host(NULL, service, proto, NULL, txt, num_items); @@ -964,8 +1049,8 @@ esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char esp_err_t ret = ESP_OK; char *value = NULL; mdns_txt_linked_item_t *new_txt = NULL; - const char *hostname = host ? host : _mdns_server->hostname; - ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(key) && + const char *hostname = host ? host : s_mdns_server->hostname; + ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(key) && !((!value_arg && value_len)), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); @@ -1000,7 +1085,7 @@ esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char srv->txt = new_txt; } - _mdns_announce_all_pcbs(&s, 1, false); + announce_all_pcbs(&s, 1, false); err: mdns_priv_service_unlock(); @@ -1023,7 +1108,7 @@ esp_err_t mdns_service_txt_item_set_for_host(const char *instance, const char *s esp_err_t mdns_service_txt_item_set(const char *service, const char *proto, const char *key, const char *value) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, NULL, key, @@ -1033,7 +1118,7 @@ esp_err_t mdns_service_txt_item_set(const char *service, const char *proto, cons esp_err_t mdns_service_txt_item_set_with_explicit_value_len(const char *service, const char *proto, const char *key, const char *value, uint8_t value_len) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, NULL, key, value, value_len); @@ -1044,8 +1129,8 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : _mdns_server->hostname; - ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(key), + const char *hostname = host ? host : s_mdns_server->hostname; + ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(key), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); @@ -1076,7 +1161,7 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char } } - _mdns_announce_all_pcbs(&s, 1, false); + announce_all_pcbs(&s, 1, false); err: mdns_priv_service_unlock(); @@ -1088,13 +1173,13 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char esp_err_t mdns_service_txt_item_remove(const char *service, const char *proto, const char *key) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_txt_item_remove_for_host(NULL, service, proto, NULL, key); } -static esp_err_t _mdns_service_subtype_remove_for_host(mdns_srv_item_t *service, const char *subtype) +static esp_err_t service_subtype_remove_for_host(mdns_srv_item_t *service, const char *subtype) { esp_err_t ret = ESP_ERR_NOT_FOUND; mdns_subtype_t *srv_subtype = service->service->subtype; @@ -1128,13 +1213,13 @@ esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && + ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(subtype), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_name, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); - ret = _mdns_service_subtype_remove_for_host(s, subtype); + ret = service_subtype_remove_for_host(s, subtype); ESP_GOTO_ON_ERROR(ret, err, TAG, "Failed to remove the subtype: %s", subtype); // Transmit a sendbye message for the removed subtype. @@ -1145,7 +1230,7 @@ esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const remove_subtypes->next = NULL; _mdns_send_bye_subtype(s, instance_name, remove_subtypes); - _mdns_free_subtype(remove_subtypes); + free_subtype(remove_subtypes); err: mdns_priv_service_unlock(); return ret; @@ -1156,7 +1241,7 @@ esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const return ret; } -static esp_err_t _mdns_service_subtype_add_for_host(mdns_srv_item_t *service, const char *subtype) +static esp_err_t service_subtype_add_for_host(mdns_srv_item_t *service, const char *subtype) { esp_err_t ret = ESP_OK; mdns_subtype_t *srv_subtype = service->service->subtype; @@ -1186,14 +1271,14 @@ esp_err_t mdns_service_subtype_add_multiple_items_for_host(const char *instance_ mdns_priv_service_lock(); esp_err_t ret = ESP_OK; int cur_index = 0; - ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && + ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && (num_items > 0), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_name, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); for (; cur_index < num_items; cur_index++) { - ret = _mdns_service_subtype_add_for_host(s, subtype[cur_index].subtype); + ret = service_subtype_add_for_host(s, subtype[cur_index].subtype); if (ret == ESP_OK) { continue; } else if (ret == ESP_ERR_NO_MEM) { @@ -1205,11 +1290,11 @@ esp_err_t mdns_service_subtype_add_multiple_items_for_host(const char *instance_ } } - _mdns_announce_all_pcbs(&s, 1, false); + announce_all_pcbs(&s, 1, false); err: if (ret == ESP_ERR_NO_MEM) { for (int idx = 0; idx < cur_index; idx++) { - _mdns_service_subtype_remove_for_host(s, subtype[idx].subtype); + service_subtype_remove_for_host(s, subtype[idx].subtype); } } exit: @@ -1225,8 +1310,8 @@ esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const cha return mdns_service_subtype_add_multiple_items_for_host(instance_name, service_type, proto, hostname, _subtype, 1); } -static mdns_subtype_t *_mdns_service_find_subtype_needed_sendbye(mdns_service_t *service, mdns_subtype_item_t subtype[], - uint8_t num_items) +static mdns_subtype_t *service_find_subtype_needed_sendbye(mdns_service_t *service, mdns_subtype_item_t subtype[], + uint8_t num_items) { if (!service) { return NULL; @@ -1281,23 +1366,23 @@ esp_err_t mdns_service_subtype_update_multiple_items_for_host(const char *instan mdns_priv_service_lock(); esp_err_t ret = ESP_OK; int cur_index = 0; - ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service_type) && !_str_null_or_empty(proto), + ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service_type) && !_str_null_or_empty(proto), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_name, service_type, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); - mdns_subtype_t *goodbye_subtype = _mdns_service_find_subtype_needed_sendbye(s->service, subtype, num_items); + mdns_subtype_t *goodbye_subtype = service_find_subtype_needed_sendbye(s->service, subtype, num_items); if (goodbye_subtype) { _mdns_send_bye_subtype(s, instance_name, goodbye_subtype); } - _mdns_free_subtype(goodbye_subtype); - _mdns_free_service_subtype(s->service); + free_subtype(goodbye_subtype); + free_service_subtype(s->service); for (; cur_index < num_items; cur_index++) { - ret = _mdns_service_subtype_add_for_host(s, subtype[cur_index].subtype); + ret = service_subtype_add_for_host(s, subtype[cur_index].subtype); if (ret == ESP_OK) { continue; } else if (ret == ESP_ERR_NO_MEM) { @@ -1309,12 +1394,12 @@ esp_err_t mdns_service_subtype_update_multiple_items_for_host(const char *instan } } if (num_items) { - _mdns_announce_all_pcbs(&s, 1, false); + announce_all_pcbs(&s, 1, false); } err: if (ret == ESP_ERR_NO_MEM) { for (int idx = 0; idx < cur_index; idx++) { - _mdns_service_subtype_remove_for_host(s, subtype[idx].subtype); + service_subtype_remove_for_host(s, subtype[idx].subtype); } } exit: @@ -1327,21 +1412,21 @@ esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, cons { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : _mdns_server->hostname; + const char *hostname = host ? host : s_mdns_server->hostname; - ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && + ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(instance) && strlen(instance) <= (MDNS_NAME_BUF_LEN - 1), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_old, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); if (s->service->instance) { - mdns_responder_send_bye_service(&s, 1, false); + mdns_priv_pcb_send_bye_service(&s, 1, false); mdns_mem_free((char *)s->service->instance); } s->service->instance = mdns_mem_strndup(instance, MDNS_NAME_BUF_LEN - 1); ESP_GOTO_ON_FALSE(s->service->instance, ESP_ERR_NO_MEM, err, TAG, "Out of memory"); - mdns_responder_probe_all_pcbs(&s, 1, false, false); + mdns_priv_probe_all_pcbs(&s, 1, false, false); err: mdns_priv_service_unlock(); @@ -1350,7 +1435,7 @@ esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, cons esp_err_t mdns_service_instance_name_set(const char *service, const char *proto, const char *instance) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_instance_name_set_for_host(NULL, service, proto, NULL, instance); @@ -1360,25 +1445,25 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : _mdns_server->hostname; - ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto), + const char *hostname = host ? host : s_mdns_server->hostname; + ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); - mdns_srv_item_t *a = _mdns_server->services; + mdns_srv_item_t *a = s_mdns_server->services; mdns_srv_item_t *b = a; if (instance) { while (a) { if (mdns_utils_service_match_instance(a->service, instance, service, proto, hostname)) { - if (_mdns_server->services != a) { + if (s_mdns_server->services != a) { b->next = a->next; } else { - _mdns_server->services = a->next; + s_mdns_server->services = a->next; } - mdns_responder_send_bye_service(&a, 1, false); + mdns_priv_pcb_send_bye_service(&a, 1, false); _mdns_remove_scheduled_service_packets(a->service); - _mdns_free_service(a->service); + free_service(a->service); mdns_mem_free(a); break; } @@ -1388,14 +1473,14 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service } else { while (a) { if (mdns_utils_service_match(a->service, service, proto, hostname)) { - if (_mdns_server->services != a) { + if (s_mdns_server->services != a) { b->next = a->next; } else { - _mdns_server->services = a->next; + s_mdns_server->services = a->next; } - mdns_responder_send_bye_service(&a, 1, false); + mdns_priv_pcb_send_bye_service(&a, 1, false); _mdns_remove_scheduled_service_packets(a->service); - _mdns_free_service(a->service); + free_service(a->service); mdns_mem_free(a); break; } @@ -1411,7 +1496,7 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service esp_err_t mdns_service_remove(const char *service_type, const char *proto) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_remove_for_host(NULL, service_type, proto, NULL); @@ -1421,19 +1506,19 @@ esp_err_t mdns_service_remove_all(void) { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - ESP_GOTO_ON_FALSE(_mdns_server, ESP_ERR_INVALID_ARG, done, TAG, "Invalid state"); - if (!_mdns_server->services) { + ESP_GOTO_ON_FALSE(s_mdns_server, ESP_ERR_INVALID_ARG, done, TAG, "Invalid state"); + if (!s_mdns_server->services) { goto done; } - _mdns_send_final_bye(false); - mdns_srv_item_t *services = _mdns_server->services; - _mdns_server->services = NULL; + send_final_bye(false); + mdns_srv_item_t *services = s_mdns_server->services; + s_mdns_server->services = NULL; while (services) { mdns_srv_item_t *s = services; services = services->next; _mdns_remove_scheduled_service_packets(s->service); - _mdns_free_service(s->service); + free_service(s->service); mdns_mem_free(s); } @@ -1445,14 +1530,14 @@ esp_err_t mdns_service_remove_all(void) esp_err_t mdns_lookup_delegated_service(const char *instance, const char *service, const char *proto, size_t max_results, mdns_result_t **result) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } if (!result || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } mdns_priv_service_lock(); - *result = _mdns_lookup_service(instance, service, proto, max_results, false); + *result = lookup_service(instance, service, proto, max_results, false); mdns_priv_service_unlock(); return ESP_OK; } @@ -1460,93 +1545,14 @@ esp_err_t mdns_lookup_delegated_service(const char *instance, const char *servic esp_err_t mdns_lookup_selfhosted_service(const char *instance, const char *service, const char *proto, size_t max_results, mdns_result_t **result) { - if (!_mdns_server) { + if (!s_mdns_server) { return ESP_ERR_INVALID_STATE; } if (!result || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } mdns_priv_service_lock(); - *result = _mdns_lookup_service(instance, service, proto, max_results, true); + *result = lookup_service(instance, service, proto, max_results, true); mdns_priv_service_unlock(); return ESP_OK; } - -void mdns_priv_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) -{ - mdns_srv_item_t *service = _mdns_server->services; - - while (service) { - if (service->service->hostname && - strcmp(service->service->hostname, old_hostname) == 0) { - mdns_mem_free((char *)service->service->hostname); - service->service->hostname = mdns_mem_strdup(new_hostname); - } - service = service->next; - } -} - -void mdns_priv_responder_action(mdns_action_t *action, mdns_action_subtype_t type) -{ - if (type == ACTION_RUN) { - switch (action->type) { - case ACTION_HOSTNAME_SET: - _mdns_send_bye_all_pcbs_no_instance(true); - mdns_priv_remap_self_service_hostname(_mdns_server->hostname, action->data.hostname_set.hostname); - mdns_mem_free((char *)_mdns_server->hostname); - _mdns_server->hostname = action->data.hostname_set.hostname; - _mdns_self_host.hostname = action->data.hostname_set.hostname; - mdns_priv_restart_all_pcbs(); - break; - case ACTION_INSTANCE_SET: - _mdns_send_bye_all_pcbs_no_instance(false); - mdns_mem_free((char *)_mdns_server->instance); - _mdns_server->instance = action->data.instance; - mdns_priv_restart_all_pcbs_no_instance(); - break; - case ACTION_DELEGATE_HOSTNAME_ADD: - if (!mdns_priv_delegate_hostname_add(action->data.delegate_hostname.hostname, - action->data.delegate_hostname.address_list)) { - mdns_mem_free((char *)action->data.delegate_hostname.hostname); - mdns_utils_free_address_list(action->data.delegate_hostname.address_list); - } - break; - case ACTION_DELEGATE_HOSTNAME_SET_ADDR: - if (!_mdns_delegate_hostname_set_address(action->data.delegate_hostname.hostname, - action->data.delegate_hostname.address_list)) { - mdns_utils_free_address_list(action->data.delegate_hostname.address_list); - } - mdns_mem_free((char *)action->data.delegate_hostname.hostname); - break; - case ACTION_DELEGATE_HOSTNAME_REMOVE: - _mdns_delegate_hostname_remove(action->data.delegate_hostname.hostname); - mdns_mem_free((char *)action->data.delegate_hostname.hostname); - break; - default: - abort(); - } - return; - } - if (type == ACTION_CLEANUP) { - switch (action->type) { - case ACTION_HOSTNAME_SET: - mdns_mem_free(action->data.hostname_set.hostname); - break; - case ACTION_INSTANCE_SET: - mdns_mem_free(action->data.instance); - break; - case ACTION_DELEGATE_HOSTNAME_SET_ADDR: - case ACTION_DELEGATE_HOSTNAME_ADD: - mdns_mem_free((char *)action->data.delegate_hostname.hostname); - mdns_utils_free_address_list(action->data.delegate_hostname.address_list); - break; - case ACTION_DELEGATE_HOSTNAME_REMOVE: - mdns_mem_free((char *)action->data.delegate_hostname.hostname); - break; - default: - abort(); - } - return; - } - -} diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index f15d84d944..3c4600f589 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -14,6 +14,7 @@ #include "mdns_debug.h" #include "mdns_netif.h" #include "mdns_pcb.h" +#include "mdns_responder.h" static const char *TAG = "mdns_send"; static const char *MDNS_SUB_STR = "_sub"; diff --git a/components/mdns/mdns_service.c b/components/mdns/mdns_service.c index 91404640c1..66471573ab 100644 --- a/components/mdns/mdns_service.c +++ b/components/mdns/mdns_service.c @@ -30,7 +30,6 @@ static volatile TaskHandle_t _mdns_service_task_handle = NULL; static SemaphoreHandle_t _mdns_service_semaphore = NULL; static StackType_t *_mdns_stack_buffer; static QueueHandle_t s_action_queue; -static SemaphoreHandle_t s_action_sema; static esp_timer_handle_t s_timer_handle; static const char *TAG = "mdns_service"; @@ -159,13 +158,6 @@ static void _mdns_execute_action(mdns_action_t *action) case ACTION_SYSTEM_EVENT: perform_event_action(action->data.sys_event.interface, action->data.sys_event.event_action); break; - case ACTION_HOSTNAME_SET: - mdns_priv_responder_action(action, ACTION_RUN); - xSemaphoreGive(s_action_sema); - break; - case ACTION_INSTANCE_SET: - mdns_priv_responder_action(action, ACTION_RUN); - break; case ACTION_SEARCH_ADD: case ACTION_SEARCH_SEND: case ACTION_SEARCH_END: @@ -183,13 +175,10 @@ static void _mdns_execute_action(mdns_action_t *action) case ACTION_RX_HANDLE: mdns_priv_receive_action(action, ACTION_RUN); break; + case ACTION_HOSTNAME_SET: + case ACTION_INSTANCE_SET: case ACTION_DELEGATE_HOSTNAME_ADD: - mdns_priv_responder_action(action, ACTION_RUN); - xSemaphoreGive(s_action_sema); - break; case ACTION_DELEGATE_HOSTNAME_SET_ADDR: - mdns_priv_responder_action(action, ACTION_RUN); - break; case ACTION_DELEGATE_HOSTNAME_REMOVE: mdns_priv_responder_action(action, ACTION_RUN); break; @@ -359,26 +348,19 @@ esp_err_t mdns_init(void) return err; } - if (mdns_responder_init() != ESP_OK) { + if (mdns_priv_responder_init() != ESP_OK) { return ESP_ERR_NO_MEM; } s_action_queue = xQueueCreate(MDNS_ACTION_QUEUE_LEN, sizeof(mdns_action_t *)); if (!s_action_queue) { err = ESP_ERR_NO_MEM; - goto free_server; - } - - s_action_sema = xSemaphoreCreateBinary(); - if (!s_action_sema) { - err = ESP_ERR_NO_MEM; - goto free_queue; + goto free_responder; } - if (mdns_netif_init() != ESP_OK) { err = ESP_FAIL; - goto free_action_sema; + goto free_queue; } if (_mdns_service_task_start()) { @@ -391,12 +373,10 @@ esp_err_t mdns_init(void) free_all_and_disable_pcbs: mdns_netif_deinit(); -free_action_sema: - vSemaphoreDelete(s_action_sema); free_queue: vQueueDelete(s_action_queue); -free_server: - mdns_responder_free(); +free_responder: + mdns_priv_responder_free(); return err; } @@ -410,7 +390,7 @@ void mdns_free(void) mdns_netif_unregister_predefined_handlers(); mdns_service_remove_all(); - mdns_responder_free_delegated_hostnames(); + mdns_priv_free_delegated_hostnames(); _mdns_service_task_stop(); // at this point, the service task is deleted, so we can destroy the stack size mdns_mem_task_free(_mdns_stack_buffer); @@ -425,8 +405,7 @@ void mdns_free(void) _mdns_clear_tx_queue_head(); mdns_priv_query_free(); mdns_browse_free(); - vSemaphoreDelete(s_action_sema); - mdns_responder_free(); + mdns_priv_responder_free(); } bool mdns_priv_queue_action(mdns_action_t *action) @@ -436,8 +415,3 @@ bool mdns_priv_queue_action(mdns_action_t *action) } return true; } - -void mdns_priv_wait_action_complete(void) -{ - xSemaphoreTake(s_action_sema, portMAX_DELAY); -} diff --git a/components/mdns/mdns_utils.c b/components/mdns/mdns_utils.c index c52dbf8038..816ff903f5 100644 --- a/components/mdns/mdns_utils.c +++ b/components/mdns/mdns_utils.c @@ -8,6 +8,7 @@ #include "mdns_mem_caps.h" #include "esp_log.h" #include "mdns_utils.h" +#include "mdns_responder.h" static const char *MDNS_DEFAULT_DOMAIN = "local"; static const char *MDNS_SUB_STR = "_sub"; diff --git a/components/mdns/private_include/mdns_pcb.h b/components/mdns/private_include/mdns_pcb.h index 4d9cef87cf..f0e260b3b5 100644 --- a/components/mdns/private_include/mdns_pcb.h +++ b/components/mdns/private_include/mdns_pcb.h @@ -100,12 +100,12 @@ bool mdns_priv_pcb_check_for_duplicates(mdns_if_t tcpip_if); * @brief Sends bye for particular services on particular PCB * @note Called from mdns.c */ -void mdns_responder_send_bye_service(mdns_srv_item_t **services, size_t len, bool include_ip); +void mdns_priv_pcb_send_bye_service(mdns_srv_item_t **services, size_t len, bool include_ip); /** * @brief Send probe on all active PCBs */ -void mdns_responder_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe); +void mdns_priv_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe); /** * @brief Send probe for particular services on particular PCB @@ -114,7 +114,7 @@ void mdns_responder_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool * - If pcb probing then add only non-probing services and restarts probing * - If pcb not probing, run probing for all specified services */ -void mdns_responder_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip); +void mdns_priv_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip); #ifdef __cplusplus diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 7c009d39ac..4bcec0d1d1 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -395,21 +395,6 @@ typedef struct mdns_browse_sync { mdns_browse_result_sync_t *sync_result; } mdns_browse_sync_t; -typedef struct mdns_server_s { -// struct { -// mdns_pcb_t pcbs[MDNS_IP_PROTOCOL_MAX]; -// } interfaces[MDNS_MAX_INTERFACES]; - const char *hostname; - const char *instance; - mdns_srv_item_t *services; -// QueueHandle_t action_queue; -// SemaphoreHandle_t action_sema; -// mdns_tx_packet_t *tx_queue_head; -// mdns_search_once_t *search_once; -// esp_timer_handle_t timer_handle; -// mdns_browse_t *browse; -} mdns_server_t; - typedef struct { mdns_action_type_t type; union { @@ -443,60 +428,6 @@ typedef struct { } data; } mdns_action_t; -/** - * @brief Returns true if the mdns server is initialized - */ -bool mdns_priv_is_server_init(void); - -/** - * @brief get global (mdns_server->hostname) hostname - */ -const char *mdns_priv_get_global_hostname(void); - -/** - * @brief get service list - */ -mdns_srv_item_t *mdns_priv_get_services(void); - -/** - * @brief get host list - */ -mdns_host_item_t *mdns_priv_get_hosts(void); - -/** - * @brief get self host - */ -mdns_host_item_t *priv_get_self_host(void); - -/** - * @brief set global hostname - */ -void mdns_priv_set_global_hostname(const char *hostname); - -/** - * @brief set mdns_server->instance - */ -const char *mdns_priv_get_instance(void); - -/** - * @brief set mdns_server->instance - */ -void mdns_priv_set_instance(const char *instance); - -/** - * @brief Restart the responder on all services without instance - */ -void mdns_priv_restart_all_pcbs_no_instance(void); - -/** - * @brief Remaps hostname of self service - */ -void mdns_priv_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); - -/** - * @brief Restart the responder on all active PCBs - */ -void mdns_priv_restart_all_pcbs(void); /** * @brief Lock mdns service @@ -513,21 +444,6 @@ void mdns_priv_service_unlock(void); */ bool mdns_priv_queue_action(mdns_action_t *action); -esp_err_t mdns_responder_init(void); - -void mdns_responder_free(void); - -void mdns_priv_wait_action_complete(void); - -/** - * @brief Adds a delegated hostname to the linked list - * @param hostname Host name pointer - * @param address_list Address list - * @return true on success - * false if the host wasn't attached (this is our hostname, or alloc failure) so we have to free the structs - */ -bool mdns_priv_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *address_list); -void mdns_responder_free_delegated_hostnames(void); #endif /* MDNS_PRIVATE_H_ */ diff --git a/components/mdns/private_include/mdns_responder.h b/components/mdns/private_include/mdns_responder.h index 731d72d22b..ce4d8e7eca 100644 --- a/components/mdns/private_include/mdns_responder.h +++ b/components/mdns/private_include/mdns_responder.h @@ -19,6 +19,84 @@ extern "C" { */ void mdns_priv_responder_action(mdns_action_t *action, mdns_action_subtype_t type); +/** + * @brief Initializes responder storage + */ +esp_err_t mdns_priv_responder_init(void); + +/** + * @brief Frees responder storage + */ +void mdns_priv_responder_free(void); + +/** + * @brief get global (mdns_server->hostname) hostname + */ +const char *mdns_priv_get_global_hostname(void); + +/** + * @brief get service list + */ +mdns_srv_item_t *mdns_priv_get_services(void); + +/** + * @brief get host list + */ +mdns_host_item_t *mdns_priv_get_hosts(void); + +/** + * @brief get self host + */ +mdns_host_item_t *priv_get_self_host(void); + +/** + * @brief set global hostname + */ +void mdns_priv_set_global_hostname(const char *hostname); + +/** + * @brief get mdns_server->instance + */ +const char *mdns_priv_get_instance(void); + +/** + * @brief set mdns_server->instance + */ +void mdns_priv_set_instance(const char *instance); + +/** + * @brief Returns true if the mdns server is initialized + */ +bool mdns_priv_is_server_init(void); + +/** + * @brief Restart the responder on all services without instance + */ +void mdns_priv_restart_all_pcbs_no_instance(void); + +/** + * @brief Restart the responder on all active PCBs + */ +void mdns_priv_restart_all_pcbs(void); + +/** + * @brief Adds a delegated hostname to the linked list + * @param hostname Host name pointer + * @param address_list Address list + * @return true on success + * false if the host wasn't attached (this is our hostname, or alloc failure) so we have to free the structs + */ +bool mdns_priv_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *address_list); + +/** + * Fee delegated hostnames + */ +void mdns_priv_free_delegated_hostnames(void); + +/** + * @brief Remaps hostname of self service + */ +void mdns_priv_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); #ifdef __cplusplus From 0bd74cbea59b11427d48e20ae1b3815eac45b2e4 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 27 Mar 2025 17:20:18 +0100 Subject: [PATCH 14/27] fix(mdns): Refactor fuzzer test suite --- .github/workflows/mdns__host-tests.yml | 28 +- components/mdns/mdns_responder.c | 2 +- .../mdns/private_include/mdns_responder.h | 1 - .../mdns/tests/host_unit_test/CMakeLists.txt | 104 ++ .../host_unit_test/input/generate_cases.py | 173 ++++ components/mdns/tests/host_unit_test/main.c | 140 +++ .../tests/host_unit_test/sdkconfig.defaults | 6 + .../tests/host_unit_test/stubs/esp_assert.h | 6 + .../mdns/tests/host_unit_test/stubs/esp_idf.c | 82 ++ .../tests/host_unit_test/stubs/esp_random.h | 0 .../tests/host_unit_test/stubs/mdns_engine.c | 70 ++ .../host_unit_test/stubs/mdns_mem_caps.c | 71 ++ .../host_unit_test/stubs/mdns_networking.c | 89 ++ .../tests/host_unit_test/stubs/sdkconfig.h | 885 ++++++++++++++++++ .../tests/test_afl_fuzz_host/CMakeLists.txt | 3 +- 15 files changed, 1651 insertions(+), 9 deletions(-) create mode 100644 components/mdns/tests/host_unit_test/CMakeLists.txt create mode 100644 components/mdns/tests/host_unit_test/input/generate_cases.py create mode 100644 components/mdns/tests/host_unit_test/main.c create mode 100644 components/mdns/tests/host_unit_test/sdkconfig.defaults create mode 100644 components/mdns/tests/host_unit_test/stubs/esp_assert.h create mode 100644 components/mdns/tests/host_unit_test/stubs/esp_idf.c create mode 100644 components/mdns/tests/host_unit_test/stubs/esp_random.h create mode 100644 components/mdns/tests/host_unit_test/stubs/mdns_engine.c create mode 100644 components/mdns/tests/host_unit_test/stubs/mdns_mem_caps.c create mode 100644 components/mdns/tests/host_unit_test/stubs/mdns_networking.c create mode 100644 components/mdns/tests/host_unit_test/stubs/sdkconfig.h diff --git a/.github/workflows/mdns__host-tests.yml b/.github/workflows/mdns__host-tests.yml index b0ad0a788a..fe8cd1b310 100644 --- a/.github/workflows/mdns__host-tests.yml +++ b/.github/workflows/mdns__host-tests.yml @@ -55,8 +55,11 @@ jobs: shell: bash run: | . ${IDF_PATH}/export.sh - cd components/mdns/tests/test_afl_fuzz_host/ - make INSTR=off + cd components/mdns/tests/host_unit_test/ + idf.py reconfigure + mkdir build2 && cd build2 + cmake .. + cmake --build . - name: Test no malloc functions shell: bash run: | @@ -99,13 +102,28 @@ jobs: shell: bash run: | export IDF_PATH=$GITHUB_WORKSPACE/idf - cd components/mdns/tests/test_afl_fuzz_host/ - make fuzz + cd components/mdns/tests/host_unit_test/ + pip install dnslib + cd input && python generate_cases.py && cd .. + mkdir build2 && cd build2 + cmake -DCMAKE_C_COMPILER=afl-cc .. + cmake --build . + cd .. + timeout 10m afl-fuzz -i input -o out -- build2/mdns_host_unit_test || \ + if [ $? -eq 124 ]; then # timeout exit code + if [ -n "$(find out/default/crashes -type f 2>/dev/null)" ]; then + echo "Crashes found!"; + tar -czf out/default/crashes.tar.gz -C out/default crashes; + exit 1; + fi + else + exit 1; + fi - name: Upload Crash Artifacts if: failure() uses: actions/upload-artifact@v4 with: name: fuzz-crashes - path: components/mdns/tests/test_afl_fuzz_host/out/default/crashes.tar.gz + path: components/mdns/tests/host_unit_test/out/default/crashes.tar.gz if-no-files-found: ignore diff --git a/components/mdns/mdns_responder.c b/components/mdns/mdns_responder.c index 9aca73d010..41e0b4d1cc 100644 --- a/components/mdns/mdns_responder.c +++ b/components/mdns/mdns_responder.c @@ -68,7 +68,7 @@ const char *mdns_priv_get_global_hostname(void) mdns_srv_item_t *mdns_priv_get_services(void) { - return s_mdns_server->services; + return s_mdns_server ? s_mdns_server->services : NULL; } mdns_host_item_t *mdns_priv_get_hosts(void) diff --git a/components/mdns/private_include/mdns_responder.h b/components/mdns/private_include/mdns_responder.h index ce4d8e7eca..15f142c6ea 100644 --- a/components/mdns/private_include/mdns_responder.h +++ b/components/mdns/private_include/mdns_responder.h @@ -98,7 +98,6 @@ void mdns_priv_free_delegated_hostnames(void); */ void mdns_priv_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); - #ifdef __cplusplus } #endif diff --git a/components/mdns/tests/host_unit_test/CMakeLists.txt b/components/mdns/tests/host_unit_test/CMakeLists.txt new file mode 100644 index 0000000000..760b5847cf --- /dev/null +++ b/components/mdns/tests/host_unit_test/CMakeLists.txt @@ -0,0 +1,104 @@ +cmake_minimum_required(VERSION 3.5) +if(ESP_PLATFORM) + set(EXTRA_COMPONENT_DIRS ../../) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) + project(mdns_host_unit_test_config) + return() +endif () + +project(mdns_host_unit_test C) + +# Set variables for directories +set(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(COMPONENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../) +set(ESP_NETIF_LINUX_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../host_test/components/esp_netif_linux/include) +set(COMMON_COMPONENTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../common_components/linux_compat/) +set(IDF_COMPONENTS_DIR "$ENV{IDF_PATH}/components") + +# Debug prints to see directory values +message(STATUS "TEST_DIR: ${TEST_DIR}") +message(STATUS "COMPONENT_DIR: ${COMPONENT_DIR}") + +# Include directories for the test files and other required files +include_directories( + ${TEST_DIR} + ${TEST_DIR}/stubs + ${TEST_DIR}/build/config + ${COMMON_COMPONENTS_DIR}/freertos/include + ${COMMON_COMPONENTS_DIR}/esp_timer/include + ${IDF_COMPONENTS_DIR}/esp_event/include + ${IDF_COMPONENTS_DIR}/esp_netif/include + ${IDF_COMPONENTS_DIR}/esp_common/include + ${IDF_COMPONENTS_DIR}/esp_system/include + ${IDF_COMPONENTS_DIR}/log/include + ${IDF_COMPONENTS_DIR}/esp_rom/include + ${IDF_COMPONENTS_DIR}/heap/include + ${IDF_COMPONENTS_DIR}/esp_rom/linux/include/linux/ + ${ESP_NETIF_LINUX_DIR} + ${COMPONENT_DIR} + ${COMPONENT_DIR}/include + ${COMPONENT_DIR}/private_include +) + +# Unity testing framework +set(UNITY_DIR "$ENV{IDF_PATH}/components/unity") +include_directories(${UNITY_DIR}/unity/src) + +# Source files +set(SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/stubs/mdns_mem_caps.c + ${CMAKE_CURRENT_SOURCE_DIR}/stubs/esp_idf.c + ${CMAKE_CURRENT_SOURCE_DIR}/stubs/mdns_networking.c + ${CMAKE_CURRENT_SOURCE_DIR}/stubs/mdns_engine.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_receive.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_utils.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_browser.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_querier.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_responder.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_send.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_pcb.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_netif.c + ${UNITY_DIR}/unity/src/unity.c +) + +# Enable sanitizers +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer") +#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") + +# Setting C flags with debug symbols and disable optimization for better debugging +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0") + +# Create the test executable +add_executable(${PROJECT_NAME} ${SOURCES}) + +find_library(LIB_BSD bsd) +if(LIB_BSD) + target_link_libraries(${PROJECT_NAME} PRIVATE ${LIB_BSD}) +elseif(NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + message(WARNING "Missing LIBBSD library. Install libbsd-dev package and/or check linker directories.") +endif() +# Setting C flags +#set_target_properties(${PROJECT_NAME} PROPERTIES +# C_STANDARD 99 +# COMPILE_FLAGS "-Wall -Werror" +#) + +# Test command with ASAN options +#enable_testing() +#add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) +#set_tests_properties(${PROJECT_NAME} PROPERTIES +# ENVIRONMENT "ASAN_OPTIONS=detect_leaks=1:verbosity=1:log_path=asan.log:print_stats=1:malloc_context_size=20" +#) + +# Add libbsd dependency +#find_package(PkgConfig REQUIRED) +#pkg_check_modules(LIBBSD REQUIRED libbsd-overlay) + +# Link against libbsd for strlcat +#target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBBSD_LIBRARIES}) +#target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=address -fsanitize=undefined) +#target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=address -fsanitize=undefined) + +# Add include directories if needed +#target_include_directories(${PROJECT_NAME} PRIVATE ${LIBBSD_INCLUDE_DIRS}) diff --git a/components/mdns/tests/host_unit_test/input/generate_cases.py b/components/mdns/tests/host_unit_test/input/generate_cases.py new file mode 100644 index 0000000000..743bcffb08 --- /dev/null +++ b/components/mdns/tests/host_unit_test/input/generate_cases.py @@ -0,0 +1,173 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +from dnslib import (AAAA, PTR, RR, SRV, TXT, A, DNSHeader, DNSQuestion, + DNSRecord) + + +def create_mdns_packet(queries, answers, additional, output_file='mdns_packet.bin'): + dns_header = DNSHeader(id=0, qr=1, aa=1, ra=0) + dns_record = DNSRecord(dns_header) + for qname, qtype in queries: + dns_record.add_question(DNSQuestion(qname, qtype)) + for name, qtype, value, ttl in answers: + if qtype == 'A': + rr = RR(name, rdata=A(value), ttl=ttl) + elif qtype == 'PTR': + rr = RR(name, rdata=PTR(value), ttl=ttl) + elif qtype == 'TXT': + rr = RR(name, rdata=TXT(value), ttl=ttl) + elif qtype == 'AAAA': + rr = RR(name, rdata=AAAA(value), ttl=ttl) + elif qtype == 'SRV': + # SRV value should be in format: "priority weight port target" + parts = value.split() + priority, weight, port = map(int, parts[:3]) + target = parts[3] + rr = RR(name, rdata=SRV(priority, weight, port, target), ttl=ttl) + else: + print(f'Unsupported type: {qtype}') + continue + dns_record.add_answer(rr) + for name, qtype, value, ttl in additional: + if qtype == 'A': + rr = RR(name, rdata=A(value), ttl=ttl) + elif qtype == 'TXT': + rr = RR(name, rdata=TXT(value), ttl=ttl) + elif qtype == 'AAAA': + rr = RR(name, rdata=AAAA(value), ttl=ttl) + elif qtype == 'SRV': + parts = value.split() + priority, weight, port = map(int, parts[:3]) + target = parts[3] + rr = RR(name, rdata=SRV(priority, weight, port, target), ttl=ttl) + else: + print(f'Unsupported type: {qtype}') + continue + dns_record.add_ar(rr) + mdns_payload = dns_record.pack() + + with open(output_file, 'wb') as f: + f.write(mdns_payload) + + print(f'mDNS packet saved as {output_file}') + + +# Test case 1: Basic hostname queries +queries = [ + ('test.local.', 1), # A record for main hostname + ('test2.local.', 1), # A record for instance name + ('test3.local.', 1), # A record for delegate hostname + ('test4.local.', 28), # AAAA record for delegate hostname +] +answers = [ + ('test.local.', 'A', '192.168.1.100', 120), + ('test2.local.', 'A', '192.168.1.101', 120), + ('test3.local.', 'A', '192.168.1.102', 120), + ('test4.local.', 'AAAA', 'fe80::1', 120), +] +additional = [ + ('test.local.', 'TXT', 'board=esp32', 120), +] +create_mdns_packet(queries, answers, additional, 'test_hostname_queries.bin') +print('Test case 1: Hostname queries') + +# Test case 2: HTTP service discovery with subtypes +queries = [ + ('_http._tcp.local.', 12), # PTR query + ('subtype._sub._http._tcp.local.', 12), # Subtype query +] +answers = [ + ('_http._tcp.local.', 'PTR', 'inst1._http._tcp.local.', 120), + ('_http._tcp.local.', 'PTR', 'inst2._http._tcp.local.', 120), + ('subtype._sub._http._tcp.local.', 'PTR', 'inst1._http._tcp.local.', 120), +] +additional = [ + ('inst1._http._tcp.local.', 'SRV', '0 0 80 test.local.', 120), + ('inst1._http._tcp.local.', 'TXT', 'board=esp32\0tcp_check=no\0ssh_upload=no\0auth_upload=no', 120), + ('inst2._http._tcp.local.', 'SRV', '0 0 80 test.local.', 120), + ('inst2._http._tcp.local.', 'TXT', 'board=esp32\0tcp_check=no\0ssh_upload=no\0auth_upload=no', 120), +] +create_mdns_packet(queries, answers, additional, 'test_http_services.bin') +print('Test case 2: HTTP service discovery with subtypes') + +# Test case 3: Scanner service discovery +queries = [ + ('_scanner._tcp.local.', 12), # PTR query +] +answers = [ + ('_scanner._tcp.local.', 'PTR', 'inst4._scanner._tcp.local.', 120), + ('_scanner._tcp.local.', 'PTR', 'inst5._scanner._tcp.local.', 120), +] +additional = [ + ('inst4._scanner._tcp.local.', 'SRV', '0 0 80 test.local.', 120), + ('inst5._scanner._tcp.local.', 'SRV', '0 0 80 test.local.', 120), +] +create_mdns_packet(queries, answers, additional, 'test_scanner_services.bin') +print('Test case 3: Scanner service discovery') + +# Test case 4: UDP service (sleep protocol) +queries = [ + ('_sleep._udp.local.', 12), # PTR query +] +answers = [ + ('_sleep._udp.local.', 'PTR', 'inst7._sleep._udp.local.', 120), +] +additional = [ + ('inst7._sleep._udp.local.', 'SRV', '0 0 80 test.local.', 120), +] +create_mdns_packet(queries, answers, additional, 'test_udp_service.bin') +print('Test case 4: UDP service discovery') + +# Test case 5: Async queries from main.c +queries = [ + ('host_name.local.', 1), # A query + ('host_name2.local.', 28), # AAAA query + ('minifritz._http._tcp.local.', 12), # PTR query +] +answers = [ + ('host_name.local.', 'A', '192.168.1.10', 120), + ('host_name2.local.', 'AAAA', 'fe80::1234', 120), + ('minifritz._http._tcp.local.', 'PTR', 'minifritz._http._tcp.local.', 120), +] +additional = [ + ('minifritz._http._tcp.local.', 'SRV', '0 0 80 minifritz.local.', 120), + ('minifritz.local.', 'A', '192.168.1.20', 120), +] +create_mdns_packet(queries, answers, additional, 'test_async_queries.bin') +print('Test case 5: Async queries') + +# Test case 6: Multiple services on same instance +queries = [ + ('_http._tcp.local.', 12), + ('_scanner._tcp.local.', 12), +] +answers = [ + ('_http._tcp.local.', 'PTR', 'inst1._http._tcp.local.', 120), + ('_http._tcp.local.', 'PTR', 'inst2._http._tcp.local.', 120), + ('_http._tcp.local.', 'PTR', 'inst3._http._tcp.local.', 120), + ('_scanner._tcp.local.', 'PTR', 'inst4._scanner._tcp.local.', 120), +] +additional = [ + ('inst1._http._tcp.local.', 'SRV', '0 0 80 test.local.', 120), + ('inst2._http._tcp.local.', 'SRV', '0 0 80 test.local.', 120), + ('test.local.', 'A', '192.168.1.100', 120), +] +create_mdns_packet(queries, answers, additional, 'test_multiple_services.bin') +print('Test case 6: Multiple services') + +# Test case 7: Subtype queries for different hosts +queries = [ + ('subtype._sub._http._tcp.local.', 12), + ('subtype3._sub._http._tcp.local.', 12), +] +answers = [ + ('subtype._sub._http._tcp.local.', 'PTR', 'inst1._http._tcp.local.', 120), + ('subtype3._sub._http._tcp.local.', 'PTR', 'inst2._http._tcp.local.', 120), +] +additional = [ + ('inst1._http._tcp.local.', 'SRV', '0 0 80 test.local.', 120), + ('inst2._http._tcp.local.', 'SRV', '0 0 80 test.local.', 120), + ('test.local.', 'A', '192.168.1.100', 120), +] +create_mdns_packet(queries, answers, additional, 'test_subtype_queries.bin') +print('Test case 7: Subtype queries') diff --git a/components/mdns/tests/host_unit_test/main.c b/components/mdns/tests/host_unit_test/main.c new file mode 100644 index 0000000000..096e7f3f3a --- /dev/null +++ b/components/mdns/tests/host_unit_test/main.c @@ -0,0 +1,140 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include +#include "esp_err.h" +#include "unity.h" +#include "mdns_receive.h" +#include "mdns_responder.h" +#include "mdns_mem_caps.h" +// Define any mocks or stubs that might be needed +// For example, if mdns_receive.c requires networking functions, you might need to mock them + +void setUp(void) +{ + // This is run before each test +} + +void tearDown(void) +{ + // This is run after each test +} + +// Sample test case - update based on the actual functionality in mdns_receive.c +void test_mdns_receive_initialization(void) +{ + // Add your test implementation here + // Example: + // TEST_ASSERT_EQUAL(EXPECTED_VALUE, actual_value); +} + +// Add more test cases as needed + +esp_err_t mdns_packet_push(esp_ip_addr_t *addr, int port, mdns_if_t tcpip_if, uint8_t*data, size_t len); + +mdns_search_once_t *s_a, *s_aaaa, *s_ptr, *s_srv, *s_txt; + +void init_responder(void) +{ + mdns_ip_addr_t addr = { .addr = { .u_addr = ESP_IPADDR_TYPE_V4 } }; + addr.addr.u_addr.ip4.addr = 0x11111111; + mdns_txt_item_t txt[4] = { + {"board", "esp32"}, + {"tcp_check", "no"}, + {"ssh_upload", "no"}, + {"auth_upload", "no"} + }; + mdns_priv_responder_init(); + mdns_hostname_set("test"); + mdns_instance_name_set("test2"); + mdns_delegate_hostname_add("test3", NULL); + mdns_delegate_hostname_add("test4", &addr); + mdns_service_add("inst1", "_http", "_tcp", 80, txt, 4); + mdns_service_subtype_add_for_host("inst1", "_http", "_tcp", "test", "subtype"); + mdns_service_add("inst2", "_http", "_tcp", 80, txt, 1); + mdns_service_subtype_add_for_host("inst2", "_http", "_tcp", "test", "subtype3"); + mdns_service_add("inst3", "_http", "_tcp", 80, NULL, 0); + mdns_service_add_for_host("deleg1", "_http", "_tcp", "test3", 80, txt, 2); + mdns_service_add_for_host(NULL, "_http", "_tcp", "test4", 80, txt, 2); + mdns_service_add(NULL, "_scanner", "_tcp", 80, NULL, 0); + mdns_service_add("inst5", "_scanner", "_tcp", 80, NULL, 0); + mdns_service_add("inst6", "_http", "_tcp", 80, NULL, 0); + mdns_service_add("inst7", "_sleep", "_udp", 80, NULL, 0); + + s_a = mdns_query_async_new("host_name", NULL, NULL, MDNS_TYPE_A, 1000, 1, NULL); + s_aaaa = mdns_query_async_new("host_name2", NULL, NULL, MDNS_TYPE_AAAA, 1000, 1, NULL); + s_ptr = mdns_query_async_new("minifritz", "_http", "_tcp", MDNS_TYPE_PTR, 1000, 1, NULL); + s_srv = mdns_query_async_new("fritz", "_http", "_tcp", MDNS_TYPE_SRV, 1000, 1, NULL); + s_txt = mdns_query_async_new("fritz", "_http", "_tcp", MDNS_TYPE_TXT, 1000, 1, NULL); + +} + +void deinit_responder(void) +{ + mdns_query_async_delete(s_a); + mdns_query_async_delete(s_aaaa); + mdns_query_async_delete(s_ptr); + mdns_query_async_delete(s_srv); + mdns_query_async_delete(s_txt); + mdns_service_remove_all(); + mdns_priv_responder_free(); +} + +static void send_packet(bool ip4, bool mdns_port, uint8_t*data, size_t len) +{ + esp_ip_addr_t addr4 = ESP_IP4ADDR_INIT(192, 168, 1, 1); + esp_ip_addr_t addr6 = ESP_IP6ADDR_INIT(0x000002ff, 0, 0, 0xfe800000); + esp_ip_addr_t *addr = ip4 ? &addr4 : &addr6; + int port = mdns_port ? 53 : 5353; + + if (mdns_packet_push(addr, port, 0, data, len) != ESP_OK) { + printf("Failed to push packet\n"); + } +} +// UNITY_BEGIN(); +// mdns_free(); +// Register test cases +// RUN_TEST(test_mdns_receive_initialization); +// Add more test cases as needed + +// return UNITY_END(); +//} +int main(int argc, char **argv) +{ + init_responder(); + uint8_t buf[1460]; + FILE *file; + size_t len = 1460; + memset(buf, 0, len); +#ifndef __AFL_LOOP + if (argc != 2) { + printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n"); + return 1; + } else { + // + // Note: parameter1 is a file (mangled packet) which caused the crash + file = fopen(argv[1], "r"); + assert(file >= 0); + len = fread(buf, 1, 1460, file); + fclose(file); + } + { +#else + while (__AFL_LOOP(1000)) { + memset(buf, 0, 1460); + size_t len = read(0, buf, 1460); +#endif + send_packet(true, true, buf, len); + send_packet(true, false, buf, len); + send_packet(false, true, buf, len); + send_packet(false, false, buf, len); + } + deinit_responder(); + + return 0; +} diff --git a/components/mdns/tests/host_unit_test/sdkconfig.defaults b/components/mdns/tests/host_unit_test/sdkconfig.defaults new file mode 100644 index 0000000000..cd903adc40 --- /dev/null +++ b/components/mdns/tests/host_unit_test/sdkconfig.defaults @@ -0,0 +1,6 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) 5.5.0 Project Minimal Configuration +# +CONFIG_MDNS_PREDEF_NETIF_STA=n +CONFIG_MDNS_PREDEF_NETIF_AP=n +CONFIG_MDNS_PREDEF_NETIF_ETH=n diff --git a/components/mdns/tests/host_unit_test/stubs/esp_assert.h b/components/mdns/tests/host_unit_test/stubs/esp_assert.h new file mode 100644 index 0000000000..989f6cf277 --- /dev/null +++ b/components/mdns/tests/host_unit_test/stubs/esp_assert.h @@ -0,0 +1,6 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#define ESP_STATIC_ASSERT _Static_assert diff --git a/components/mdns/tests/host_unit_test/stubs/esp_idf.c b/components/mdns/tests/host_unit_test/stubs/esp_idf.c new file mode 100644 index 0000000000..0237a4091c --- /dev/null +++ b/components/mdns/tests/host_unit_test/stubs/esp_idf.c @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "esp_log.h" +#include "esp_netif.h" +#include "freertos/FreeRTOS.h" + +void esp_log(esp_log_config_t config, const char* tag, const char* format, ...) +{} + +uint32_t esp_log_timestamp(void) +{ + return 0; +} + +uint32_t esp_get_free_heap_size(void) +{ + return 0; +} + +esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key) +{ + return (esp_netif_t*)1; +} + +esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) +{ + ip_info->ip.addr = 0xC0A80164; // 192.168.1.100 + ip_info->netmask.addr = 0xFFFFFF00; // 255.255.255.0 + ip_info->gw.addr = 0xC0A80101; // 192.168.1.1 + return ESP_OK; +} + +esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6) +{ + if_ip6->addr[0] = 0xFE80; + if_ip6->addr[1] = 0x0000; + if_ip6->addr[2] = 0x0000; + if_ip6->addr[3] = 0x0001; + return ESP_OK; +} + +uint32_t esp_random(void) +{ + return 0; +} + +TickType_t xTaskGetTickCount(void) +{ + return 0; +} + +int esp_netif_get_all_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[]) +{ + if_ip6[0].addr[0] = 0xFE80; + if_ip6[0].addr[1] = 0x0000; + if_ip6[0].addr[2] = 0x0000; + if_ip6[0].addr[3] = 0x0001; + return 1; +} + + +BaseType_t xSemaphoreGive(QueueHandle_t xQueue) +{ + return pdPASS; +} + +BaseType_t xSemaphoreTake(QueueHandle_t xQueue, TickType_t xTicksToWait) +{ + return pdPASS; +} + +QueueHandle_t xSemaphoreCreateBinary(void) +{ + return (QueueHandle_t)1; +} + +void vQueueDelete(QueueHandle_t xQueue) +{ +} diff --git a/components/mdns/tests/host_unit_test/stubs/esp_random.h b/components/mdns/tests/host_unit_test/stubs/esp_random.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/components/mdns/tests/host_unit_test/stubs/mdns_engine.c b/components/mdns/tests/host_unit_test/stubs/mdns_engine.c new file mode 100644 index 0000000000..74251281d7 --- /dev/null +++ b/components/mdns/tests/host_unit_test/stubs/mdns_engine.c @@ -0,0 +1,70 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "mdns.h" +#include "mdns_private.h" +#include "mdns_querier.h" +#include "mdns_browser.h" +#include "mdns_send.h" +#include "mdns_responder.h" +#include "mdns_receive.h" +#include "mdns_mem_caps.h" + +static void execute_action(mdns_action_t *action) +{ + switch (action->type) { + case ACTION_SYSTEM_EVENT: + break; + case ACTION_SEARCH_ADD: + case ACTION_SEARCH_SEND: + case ACTION_SEARCH_END: + mdns_priv_query_action(action, ACTION_RUN); + break; + case ACTION_BROWSE_ADD: + case ACTION_BROWSE_SYNC: + case ACTION_BROWSE_END: + mdns_browse_action(action, ACTION_RUN); + break; + + case ACTION_TX_HANDLE: + mdns_send_action(action, ACTION_RUN); + break; + case ACTION_RX_HANDLE: + mdns_priv_receive_action(action, ACTION_RUN); + break; + case ACTION_HOSTNAME_SET: + case ACTION_INSTANCE_SET: + case ACTION_DELEGATE_HOSTNAME_ADD: + case ACTION_DELEGATE_HOSTNAME_SET_ADDR: + case ACTION_DELEGATE_HOSTNAME_REMOVE: + mdns_priv_responder_action(action, ACTION_RUN); + break; + default: + break; + } + mdns_mem_free(action); +} + +bool mdns_priv_queue_action(mdns_action_t *action) +{ + execute_action(action); + return true; +} + +void mdns_priv_service_lock(void) +{ +} + +void mdns_priv_service_unlock(void) +{ +} + +// void mdns_priv_service_init(void) +// { +// } + +// void mdns_priv_service_free(void) +// { +// } diff --git a/components/mdns/tests/host_unit_test/stubs/mdns_mem_caps.c b/components/mdns/tests/host_unit_test/stubs/mdns_mem_caps.c new file mode 100644 index 0000000000..7da2681a56 --- /dev/null +++ b/components/mdns/tests/host_unit_test/stubs/mdns_mem_caps.c @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "mdns_mem_caps.h" + +void *mdns_mem_malloc(size_t size) +{ + return malloc(size); +} + +void *mdns_mem_calloc(size_t num, size_t size) +{ + return calloc(num, size); +} + +void mdns_mem_free(void *ptr) +{ + free(ptr); +} + +char *mdns_mem_strdup(const char *s) +{ + if (s == NULL) { + return NULL; + } + + size_t len = strlen(s) + 1; + char *new_str = mdns_mem_malloc(len); + if (new_str == NULL) { + return NULL; + } + + return memcpy(new_str, s, len); +} + +char *mdns_mem_strndup(const char *s, size_t n) +{ + if (s == NULL) { + return NULL; + } + + size_t len = strlen(s); + if (len > n) { + len = n; + } + + char *new_str = mdns_mem_malloc(len + 1); + if (new_str == NULL) { + return NULL; + } + + memcpy(new_str, s, len); + new_str[len] = '\0'; + + return new_str; +} + +void *mdns_mem_task_malloc(size_t size) +{ + return malloc(size); +} + +void mdns_mem_task_free(void *ptr) +{ + free(ptr); +} diff --git a/components/mdns/tests/host_unit_test/stubs/mdns_networking.c b/components/mdns/tests/host_unit_test/stubs/mdns_networking.c new file mode 100644 index 0000000000..2258aa9507 --- /dev/null +++ b/components/mdns/tests/host_unit_test/stubs/mdns_networking.c @@ -0,0 +1,89 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "mdns_networking.h" +#include "mdns_mem_caps.h" + +struct pbuf { + void *payload; + size_t len; +}; + +bool mdns_is_netif_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + return true; // Default to ready for testing +} + +esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + return ESP_OK; +} + +esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + return ESP_OK; +} + +size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len) +{ + return len; // Return the input length as if all data was sent successfully +} + +void *_mdns_get_packet_data(mdns_rx_packet_t *packet) +{ + return packet->pb->payload; +} + +size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +{ + return packet->pb->len; +} + +void _mdns_packet_free(mdns_rx_packet_t *packet) +{ + mdns_mem_free(packet->pb->payload); + mdns_mem_free(packet->pb); + mdns_mem_free(packet); +} + +esp_err_t mdns_packet_push(esp_ip_addr_t *addr, int port, mdns_if_t tcpip_if, uint8_t*data, size_t len) +{ + // Allocate the packet structure and pass it to the mdns main engine + mdns_rx_packet_t *packet = (mdns_rx_packet_t *) mdns_mem_calloc(1, sizeof(mdns_rx_packet_t)); + struct pbuf *packet_pbuf = mdns_mem_calloc(1, sizeof(struct pbuf)); + uint8_t *buf = mdns_mem_malloc(len); + if (packet == NULL || packet_pbuf == NULL || buf == NULL) { + mdns_mem_free(buf); + mdns_mem_free(packet_pbuf); + mdns_mem_free(packet); + return ESP_ERR_NO_MEM; + } + memcpy(buf, data, len); + packet_pbuf->payload = buf; + packet_pbuf->len = len; + packet->tcpip_if = tcpip_if; + packet->pb = packet_pbuf; + packet->src_port = port; + memcpy(&packet->src, addr, sizeof(esp_ip_addr_t)); + memset(&packet->dest, 0, sizeof(esp_ip_addr_t)); + packet->multicast = 1; + packet->dest.type = packet->src.type; + packet->ip_protocol = packet->src.type == ESP_IPADDR_TYPE_V4 ? MDNS_IP_PROTOCOL_V4 : MDNS_IP_PROTOCOL_V6; + mdns_action_t *action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + return ESP_ERR_NO_MEM; + } + + action->type = ACTION_RX_HANDLE; + action->data.rx_handle.packet = packet; + if (!mdns_priv_queue_action(action)) { + mdns_mem_free(action); + mdns_mem_free(packet->pb->payload); + mdns_mem_free(packet->pb); + mdns_mem_free(packet); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} diff --git a/components/mdns/tests/host_unit_test/stubs/sdkconfig.h b/components/mdns/tests/host_unit_test/stubs/sdkconfig.h new file mode 100644 index 0000000000..2e7649f23d --- /dev/null +++ b/components/mdns/tests/host_unit_test/stubs/sdkconfig.h @@ -0,0 +1,885 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* + * Automatically generated file. DO NOT EDIT. + * Espressif IoT Development Framework (ESP-IDF) 5.5.0 Configuration Header + */ +#pragma once +#define CONFIG_SOC_BROWNOUT_RESET_SUPPORTED "Not determined" +#define CONFIG_SOC_TWAI_BRP_DIV_SUPPORTED "Not determined" +#define CONFIG_SOC_DPORT_WORKAROUND "Not determined" +#define CONFIG_SOC_CAPS_ECO_VER_MAX 301 +#define CONFIG_SOC_ADC_SUPPORTED 1 +#define CONFIG_SOC_DAC_SUPPORTED 1 +#define CONFIG_SOC_UART_SUPPORTED 1 +#define CONFIG_SOC_MCPWM_SUPPORTED 1 +#define CONFIG_SOC_GPTIMER_SUPPORTED 1 +#define CONFIG_SOC_SDMMC_HOST_SUPPORTED 1 +#define CONFIG_SOC_BT_SUPPORTED 1 +#define CONFIG_SOC_PCNT_SUPPORTED 1 +#define CONFIG_SOC_PHY_SUPPORTED 1 +#define CONFIG_SOC_WIFI_SUPPORTED 1 +#define CONFIG_SOC_SDIO_SLAVE_SUPPORTED 1 +#define CONFIG_SOC_TWAI_SUPPORTED 1 +#define CONFIG_SOC_EFUSE_SUPPORTED 1 +#define CONFIG_SOC_EMAC_SUPPORTED 1 +#define CONFIG_SOC_ULP_SUPPORTED 1 +#define CONFIG_SOC_CCOMP_TIMER_SUPPORTED 1 +#define CONFIG_SOC_RTC_FAST_MEM_SUPPORTED 1 +#define CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED 1 +#define CONFIG_SOC_RTC_MEM_SUPPORTED 1 +#define CONFIG_SOC_I2S_SUPPORTED 1 +#define CONFIG_SOC_RMT_SUPPORTED 1 +#define CONFIG_SOC_SDM_SUPPORTED 1 +#define CONFIG_SOC_GPSPI_SUPPORTED 1 +#define CONFIG_SOC_LEDC_SUPPORTED 1 +#define CONFIG_SOC_I2C_SUPPORTED 1 +#define CONFIG_SOC_SUPPORT_COEXISTENCE 1 +#define CONFIG_SOC_AES_SUPPORTED 1 +#define CONFIG_SOC_MPI_SUPPORTED 1 +#define CONFIG_SOC_SHA_SUPPORTED 1 +#define CONFIG_SOC_FLASH_ENC_SUPPORTED 1 +#define CONFIG_SOC_SECURE_BOOT_SUPPORTED 1 +#define CONFIG_SOC_TOUCH_SENSOR_SUPPORTED 1 +#define CONFIG_SOC_BOD_SUPPORTED 1 +#define CONFIG_SOC_ULP_FSM_SUPPORTED 1 +#define CONFIG_SOC_CLK_TREE_SUPPORTED 1 +#define CONFIG_SOC_MPU_SUPPORTED 1 +#define CONFIG_SOC_WDT_SUPPORTED 1 +#define CONFIG_SOC_SPI_FLASH_SUPPORTED 1 +#define CONFIG_SOC_RNG_SUPPORTED 1 +#define CONFIG_SOC_LIGHT_SLEEP_SUPPORTED 1 +#define CONFIG_SOC_DEEP_SLEEP_SUPPORTED 1 +#define CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT 1 +#define CONFIG_SOC_PM_SUPPORTED 1 +#define CONFIG_SOC_DPORT_WORKAROUND_DIS_INTERRUPT_LVL 5 +#define CONFIG_SOC_XTAL_SUPPORT_26M 1 +#define CONFIG_SOC_XTAL_SUPPORT_40M 1 +#define CONFIG_SOC_XTAL_SUPPORT_AUTO_DETECT 1 +#define CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED 1 +#define CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED 1 +#define CONFIG_SOC_ADC_DMA_SUPPORTED 1 +#define CONFIG_SOC_ADC_PERIPH_NUM 2 +#define CONFIG_SOC_ADC_MAX_CHANNEL_NUM 10 +#define CONFIG_SOC_ADC_ATTEN_NUM 4 +#define CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM 2 +#define CONFIG_SOC_ADC_PATT_LEN_MAX 16 +#define CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH 9 +#define CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH 12 +#define CONFIG_SOC_ADC_DIGI_RESULT_BYTES 2 +#define CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV 4 +#define CONFIG_SOC_ADC_DIGI_MONITOR_NUM 0 +#define CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH 2 +#define CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW 20 +#define CONFIG_SOC_ADC_RTC_MIN_BITWIDTH 9 +#define CONFIG_SOC_ADC_RTC_MAX_BITWIDTH 12 +#define CONFIG_SOC_ADC_SHARED_POWER 1 +#define CONFIG_SOC_SHARED_IDCACHE_SUPPORTED 1 +#define CONFIG_SOC_IDCACHE_PER_CORE 1 +#define CONFIG_SOC_CPU_CORES_NUM 2 +#define CONFIG_SOC_CPU_INTR_NUM 32 +#define CONFIG_SOC_CPU_HAS_FPU 1 +#define CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES 1 +#define CONFIG_SOC_CPU_BREAKPOINTS_NUM 2 +#define CONFIG_SOC_CPU_WATCHPOINTS_NUM 2 +#define CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 64 +#define CONFIG_SOC_DAC_CHAN_NUM 2 +#define CONFIG_SOC_DAC_RESOLUTION 8 +#define CONFIG_SOC_DAC_DMA_16BIT_ALIGN 1 +#define CONFIG_SOC_GPIO_PORT 1 +#define CONFIG_SOC_GPIO_PIN_COUNT 40 +#define CONFIG_SOC_GPIO_VALID_GPIO_MASK 0xFFFFFFFFFF +#define CONFIG_SOC_GPIO_IN_RANGE_MAX 39 +#define CONFIG_SOC_GPIO_OUT_RANGE_MAX 33 +#define CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0xEF0FEA +#define CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX 1 +#define CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM 3 +#define CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP 1 +#define CONFIG_SOC_I2C_NUM 2 +#define CONFIG_SOC_HP_I2C_NUM 2 +#define CONFIG_SOC_I2C_FIFO_LEN 32 +#define CONFIG_SOC_I2C_CMD_REG_NUM 16 +#define CONFIG_SOC_I2C_SUPPORT_SLAVE 1 +#define CONFIG_SOC_I2C_SUPPORT_APB 1 +#define CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR 1 +#define CONFIG_SOC_I2C_STOP_INDEPENDENT 1 +#define CONFIG_SOC_I2S_NUM 2 +#define CONFIG_SOC_I2S_HW_VERSION_1 1 +#define CONFIG_SOC_I2S_SUPPORTS_APLL 1 +#define CONFIG_SOC_I2S_SUPPORTS_PLL_F160M 1 +#define CONFIG_SOC_I2S_SUPPORTS_PDM 1 +#define CONFIG_SOC_I2S_SUPPORTS_PDM_TX 1 +#define CONFIG_SOC_I2S_SUPPORTS_PCM2PDM 1 +#define CONFIG_SOC_I2S_SUPPORTS_PDM_RX 1 +#define CONFIG_SOC_I2S_SUPPORTS_PDM2PCM 1 +#define CONFIG_SOC_I2S_PDM_MAX_TX_LINES 1 +#define CONFIG_SOC_I2S_PDM_MAX_RX_LINES 1 +#define CONFIG_SOC_I2S_SUPPORTS_ADC_DAC 1 +#define CONFIG_SOC_I2S_SUPPORTS_ADC 1 +#define CONFIG_SOC_I2S_SUPPORTS_DAC 1 +#define CONFIG_SOC_I2S_SUPPORTS_LCD_CAMERA 1 +#define CONFIG_SOC_I2S_MAX_DATA_WIDTH 24 +#define CONFIG_SOC_I2S_TRANS_SIZE_ALIGN_WORD 1 +#define CONFIG_SOC_I2S_LCD_I80_VARIANT 1 +#define CONFIG_SOC_LCD_I80_SUPPORTED 1 +#define CONFIG_SOC_LCD_I80_BUSES 2 +#define CONFIG_SOC_LCD_I80_BUS_WIDTH 24 +#define CONFIG_SOC_LEDC_HAS_TIMER_SPECIFIC_MUX 1 +#define CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK 1 +#define CONFIG_SOC_LEDC_SUPPORT_REF_TICK 1 +#define CONFIG_SOC_LEDC_SUPPORT_HS_MODE 1 +#define CONFIG_SOC_LEDC_TIMER_NUM 4 +#define CONFIG_SOC_LEDC_CHANNEL_NUM 8 +#define CONFIG_SOC_LEDC_TIMER_BIT_WIDTH 20 +#define CONFIG_SOC_MCPWM_GROUPS 2 +#define CONFIG_SOC_MCPWM_TIMERS_PER_GROUP 3 +#define CONFIG_SOC_MCPWM_OPERATORS_PER_GROUP 3 +#define CONFIG_SOC_MCPWM_COMPARATORS_PER_OPERATOR 2 +#define CONFIG_SOC_MCPWM_GENERATORS_PER_OPERATOR 2 +#define CONFIG_SOC_MCPWM_TRIGGERS_PER_OPERATOR 2 +#define CONFIG_SOC_MCPWM_GPIO_FAULTS_PER_GROUP 3 +#define CONFIG_SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP 1 +#define CONFIG_SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER 3 +#define CONFIG_SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP 3 +#define CONFIG_SOC_MMU_PERIPH_NUM 2 +#define CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM 3 +#define CONFIG_SOC_MPU_MIN_REGION_SIZE 0x20000000 +#define CONFIG_SOC_MPU_REGIONS_MAX_NUM 8 +#define CONFIG_SOC_PCNT_GROUPS 1 +#define CONFIG_SOC_PCNT_UNITS_PER_GROUP 8 +#define CONFIG_SOC_PCNT_CHANNELS_PER_UNIT 2 +#define CONFIG_SOC_PCNT_THRES_POINT_PER_UNIT 2 +#define CONFIG_SOC_RMT_GROUPS 1 +#define CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP 8 +#define CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP 8 +#define CONFIG_SOC_RMT_CHANNELS_PER_GROUP 8 +#define CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL 64 +#define CONFIG_SOC_RMT_SUPPORT_REF_TICK 1 +#define CONFIG_SOC_RMT_SUPPORT_APB 1 +#define CONFIG_SOC_RMT_CHANNEL_CLK_INDEPENDENT 1 +#define CONFIG_SOC_RTCIO_PIN_COUNT 18 +#define CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED 1 +#define CONFIG_SOC_RTCIO_HOLD_SUPPORTED 1 +#define CONFIG_SOC_RTCIO_WAKE_SUPPORTED 1 +#define CONFIG_SOC_SDM_GROUPS 1 +#define CONFIG_SOC_SDM_CHANNELS_PER_GROUP 8 +#define CONFIG_SOC_SDM_CLK_SUPPORT_APB 1 +#define CONFIG_SOC_SPI_HD_BOTH_INOUT_SUPPORTED 1 +#define CONFIG_SOC_SPI_AS_CS_SUPPORTED 1 +#define CONFIG_SOC_SPI_PERIPH_NUM 3 +#define CONFIG_SOC_SPI_DMA_CHAN_NUM 2 +#define CONFIG_SOC_SPI_MAX_CS_NUM 3 +#define CONFIG_SOC_SPI_SUPPORT_CLK_APB 1 +#define CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE 64 +#define CONFIG_SOC_SPI_MAX_PRE_DIVIDER 8192 +#define CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1 +#define CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1 +#define CONFIG_SOC_MEMSPI_SRC_FREQ_26M_SUPPORTED 1 +#define CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED 1 +#define CONFIG_SOC_TIMER_GROUPS 2 +#define CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP 2 +#define CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH 64 +#define CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS 4 +#define CONFIG_SOC_TIMER_GROUP_SUPPORT_APB 1 +#define CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO 32 +#define CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI 16 +#define CONFIG_SOC_TOUCH_SENSOR_VERSION 1 +#define CONFIG_SOC_TOUCH_SENSOR_NUM 10 +#define CONFIG_SOC_TOUCH_SUPPORT_SLEEP_WAKEUP 1 +#define CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM 1 +#define CONFIG_SOC_TWAI_CONTROLLER_NUM 1 +#define CONFIG_SOC_TWAI_BRP_MIN 2 +#define CONFIG_SOC_TWAI_CLK_SUPPORT_APB 1 +#define CONFIG_SOC_TWAI_SUPPORT_MULTI_ADDRESS_LAYOUT 1 +#define CONFIG_SOC_UART_NUM 3 +#define CONFIG_SOC_UART_HP_NUM 3 +#define CONFIG_SOC_UART_SUPPORT_APB_CLK 1 +#define CONFIG_SOC_UART_SUPPORT_REF_TICK 1 +#define CONFIG_SOC_UART_FIFO_LEN 128 +#define CONFIG_SOC_UART_BITRATE_MAX 5000000 +#define CONFIG_SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE 1 +#define CONFIG_SOC_SPIRAM_SUPPORTED 1 +#define CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE 1 +#define CONFIG_SOC_SHA_SUPPORT_PARALLEL_ENG 1 +#define CONFIG_SOC_SHA_ENDIANNESS_BE 1 +#define CONFIG_SOC_SHA_SUPPORT_SHA1 1 +#define CONFIG_SOC_SHA_SUPPORT_SHA256 1 +#define CONFIG_SOC_SHA_SUPPORT_SHA384 1 +#define CONFIG_SOC_SHA_SUPPORT_SHA512 1 +#define CONFIG_SOC_MPI_MEM_BLOCKS_NUM 4 +#define CONFIG_SOC_MPI_OPERATIONS_NUM 1 +#define CONFIG_SOC_RSA_MAX_BIT_LEN 4096 +#define CONFIG_SOC_AES_SUPPORT_AES_128 1 +#define CONFIG_SOC_AES_SUPPORT_AES_192 1 +#define CONFIG_SOC_AES_SUPPORT_AES_256 1 +#define CONFIG_SOC_SECURE_BOOT_V1 1 +#define CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 1 +#define CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX 32 +#define CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE 21 +#define CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP 1 +#define CONFIG_SOC_PM_SUPPORT_EXT1_WAKEUP 1 +#define CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP 1 +#define CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP 1 +#define CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD 1 +#define CONFIG_SOC_PM_SUPPORT_RTC_FAST_MEM_PD 1 +#define CONFIG_SOC_PM_SUPPORT_RTC_SLOW_MEM_PD 1 +#define CONFIG_SOC_PM_SUPPORT_RC_FAST_PD 1 +#define CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD 1 +#define CONFIG_SOC_PM_SUPPORT_MODEM_PD 1 +#define CONFIG_SOC_CONFIGURABLE_VDDSDIO_SUPPORTED 1 +#define CONFIG_SOC_PM_MODEM_PD_BY_SW 1 +#define CONFIG_SOC_CLK_APLL_SUPPORTED 1 +#define CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED 1 +#define CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 1 +#define CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION 1 +#define CONFIG_SOC_CLK_XTAL32K_SUPPORTED 1 +#define CONFIG_SOC_CLK_LP_FAST_SUPPORT_XTAL_D4 1 +#define CONFIG_SOC_SDMMC_USE_IOMUX 1 +#define CONFIG_SOC_SDMMC_NUM_SLOTS 2 +#define CONFIG_SOC_WIFI_WAPI_SUPPORT 1 +#define CONFIG_SOC_WIFI_CSI_SUPPORT 1 +#define CONFIG_SOC_WIFI_MESH_SUPPORT 1 +#define CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW 1 +#define CONFIG_SOC_WIFI_NAN_SUPPORT 1 +#define CONFIG_SOC_BLE_SUPPORTED 1 +#define CONFIG_SOC_BLE_MESH_SUPPORTED 1 +#define CONFIG_SOC_BT_CLASSIC_SUPPORTED 1 +#define CONFIG_SOC_BLUFI_SUPPORTED 1 +#define CONFIG_SOC_BT_H2C_ENC_KEY_CTRL_ENH_VSC_SUPPORTED 1 +#define CONFIG_SOC_ULP_HAS_ADC 1 +#define CONFIG_SOC_PHY_COMBO_MODULE 1 +#define CONFIG_SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK 1 +#define CONFIG_IDF_CMAKE 1 +#define CONFIG_IDF_TOOLCHAIN "gcc" +#define CONFIG_IDF_TOOLCHAIN_GCC 1 +#define CONFIG_IDF_TARGET_ARCH_XTENSA 1 +#define CONFIG_IDF_TARGET_ARCH "xtensa" +#define CONFIG_IDF_TARGET "esp32" +#define CONFIG_IDF_INIT_VERSION "5.5.0" +#define CONFIG_IDF_TARGET_ESP32 1 +#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 +#define CONFIG_APP_BUILD_TYPE_APP_2NDBOOT 1 +#define CONFIG_APP_BUILD_GENERATE_BINARIES 1 +#define CONFIG_APP_BUILD_BOOTLOADER 1 +#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1 +#define CONFIG_BOOTLOADER_COMPILE_TIME_DATE 1 +#define CONFIG_BOOTLOADER_PROJECT_VER 1 +#define CONFIG_BOOTLOADER_OFFSET_IN_FLASH 0x1000 +#define CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE 1 +#define CONFIG_BOOTLOADER_LOG_VERSION_1 1 +#define CONFIG_BOOTLOADER_LOG_VERSION 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL_INFO 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL 3 +#define CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS 1 +#define CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT 1 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 +#define CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE 1 +#define CONFIG_BOOTLOADER_WDT_ENABLE 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#define CONFIG_BOOTLOADER_RESERVE_RTC_SIZE 0x0 +#define CONFIG_SECURE_BOOT_V1_SUPPORTED 1 +#define CONFIG_APP_COMPILE_TIME_DATE 1 +#define CONFIG_APP_RETRIEVE_LEN_ELF_SHA 9 +#define CONFIG_ESP_ROM_HAS_CRC_LE 1 +#define CONFIG_ESP_ROM_HAS_CRC_BE 1 +#define CONFIG_ESP_ROM_HAS_MZ_CRC32 1 +#define CONFIG_ESP_ROM_HAS_JPEG_DECODE 1 +#define CONFIG_ESP_ROM_HAS_UART_BUF_SWITCH 1 +#define CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND 1 +#define CONFIG_ESP_ROM_HAS_NEWLIB 1 +#define CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT 1 +#define CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME 1 +#define CONFIG_ESP_ROM_HAS_SW_FLOAT 1 +#define CONFIG_ESP_ROM_USB_OTG_NUM -1 +#define CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM -1 +#define CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB 1 +#define CONFIG_ESP_ROM_HAS_OUTPUT_PUTC_FUNC 1 +#define CONFIG_ESPTOOLPY_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR 1 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" +#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB" +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_ESPTOOLPY_MONITOR_BAUD 115200 +#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_COMPILER_OPTIMIZATION_DEBUG 1 +#define CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE 1 +#define CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE 1 +#define CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB 1 +#define CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL 2 +#define CONFIG_COMPILER_HIDE_PATHS_MACROS 1 +#define CONFIG_COMPILER_STACK_CHECK_MODE_NONE 1 +#define CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS 1 +#define CONFIG_COMPILER_RT_LIB_GCCLIB 1 +#define CONFIG_COMPILER_RT_LIB_NAME "gcc" +#define CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING 1 +#define CONFIG_APPTRACE_DEST_NONE 1 +#define CONFIG_APPTRACE_DEST_UART_NONE 1 +#define CONFIG_APPTRACE_UART_TASK_PRIO 1 +#define CONFIG_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_TWAI_ERRATA_FIX_BUS_OFF_REC 1 +#define CONFIG_TWAI_ERRATA_FIX_TX_INTR_LOST 1 +#define CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID 1 +#define CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT 1 +#define CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM 1 +#define CONFIG_ADC_DISABLE_DAC 1 +#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 +#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 +#define CONFIG_ADC_CAL_LUT_ENABLE 1 +#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 +#define CONFIG_EFUSE_MAX_BLK_LEN 192 +#define CONFIG_ESP_TLS_USING_MBEDTLS 1 +#define CONFIG_ADC_CALI_EFUSE_TP_ENABLE 1 +#define CONFIG_ADC_CALI_EFUSE_VREF_ENABLE 1 +#define CONFIG_ADC_CALI_LUT_ENABLE 1 +#define CONFIG_ADC_DISABLE_DAC_OUTPUT 1 +#define CONFIG_ESP_COEX_ENABLED 1 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_DAC_DMA_AUTO_16BIT_ALIGN 1 +#define CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM 1 +#define CONFIG_GPTIMER_OBJ_CACHE_SAFE 1 +#define CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM 1 +#define CONFIG_RMT_ISR_HANDLER_IN_IRAM 1 +#define CONFIG_RMT_OBJ_CACHE_SAFE 1 +#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 +#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 +#define CONFIG_ETH_ENABLED 1 +#define CONFIG_ETH_USE_ESP32_EMAC 1 +#define CONFIG_ETH_PHY_INTERFACE_RMII 1 +#define CONFIG_ETH_RMII_CLK_INPUT 1 +#define CONFIG_ETH_RMII_CLK_IN_GPIO 0 +#define CONFIG_ETH_DMA_BUFFER_SIZE 512 +#define CONFIG_ETH_DMA_RX_BUFFER_NUM 10 +#define CONFIG_ETH_DMA_TX_BUFFER_NUM 10 +#define CONFIG_ETH_USE_SPI_ETHERNET 1 +#define CONFIG_ESP_EVENT_POST_FROM_ISR 1 +#define CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 1 +#define CONFIG_ESP_GDBSTUB_ENABLED 1 +#define CONFIG_ESP_GDBSTUB_SUPPORT_TASKS 1 +#define CONFIG_ESP_GDBSTUB_MAX_TASKS 32 +#define CONFIG_ESPHID_TASK_SIZE_BT 2048 +#define CONFIG_ESPHID_TASK_SIZE_BLE 4096 +#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 +#define CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT 2000 +#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 1024 +#define CONFIG_HTTPD_MAX_URI_LEN 512 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 +#define CONFIG_HTTPD_PURGE_BUF_LEN 32 +#define CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT 2000 +#define CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT 2000 +#define CONFIG_ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT 2000 +#define CONFIG_ESP32_REV_MIN_0 1 +#define CONFIG_ESP32_REV_MIN 0 +#define CONFIG_ESP32_REV_MIN_FULL 0 +#define CONFIG_ESP_REV_MIN_FULL 0 +#define CONFIG_ESP32_REV_MAX_FULL 399 +#define CONFIG_ESP_REV_MAX_FULL 399 +#define CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL 0 +#define CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL 99 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH 1 +#define CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR 1 +#define CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES 4 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR 1 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES 4 +#define CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND 1 +#define CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND 1 +#define CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY 2000 +#define CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS 1 +#define CONFIG_RTC_CLK_SRC_INT_RC 1 +#define CONFIG_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_PERIPH_CTRL_FUNC_IN_IRAM 1 +#define CONFIG_XTAL_FREQ_40 1 +#define CONFIG_XTAL_FREQ 40 +#define CONFIG_ESP_BROWNOUT_DET 1 +#define CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP_BROWNOUT_DET_LVL 0 +#define CONFIG_ESP_BROWNOUT_USE_INTR 1 +#define CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM 1 +#define CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_ESP_NETIF_TCPIP_LWIP 1 +#define CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API 1 +#define CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC 1 +#define CONFIG_ESP_PHY_ENABLED 1 +#define CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_ESP_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_ESP_PHY_MAX_TX_POWER 20 +#define CONFIG_ESP_PHY_RF_CAL_PARTIAL 1 +#define CONFIG_ESP_PHY_CALIBRATION_MODE 0 +#define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 1 +#define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_ESP32_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT 1 +#define CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS 0 +#define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0 1 +#define CONFIG_ESP_MAIN_TASK_AFFINITY 0x0 +#define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048 +#define CONFIG_ESP_CONSOLE_UART_DEFAULT 1 +#define CONFIG_ESP_CONSOLE_UART 1 +#define CONFIG_ESP_CONSOLE_UART_NUM 0 +#define CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM 0 +#define CONFIG_ESP_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_ESP_INT_WDT 1 +#define CONFIG_ESP_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESP_INT_WDT_CHECK_CPU1 1 +#define CONFIG_ESP_TASK_WDT_EN 1 +#define CONFIG_ESP_TASK_WDT_INIT 1 +#define CONFIG_ESP_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 +#define CONFIG_ESP_DEBUG_OCDAWARE 1 +#define CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4 1 +#define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_ESP_IPC_USES_CALLERS_PRIORITY 1 +#define CONFIG_ESP_IPC_ISR_ENABLE 1 +#define CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER 1 +#define CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER 1 +#define CONFIG_ESP_TIMER_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_TIMER_INTERRUPT_LEVEL 1 +#define CONFIG_ESP_TIMER_TASK_AFFINITY 0x0 +#define CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0 1 +#define CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0 1 +#define CONFIG_ESP_TIMER_IMPL_TG0_LAC 1 +#define CONFIG_ESP_WIFI_ENABLED 1 +#define CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_ESP_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER 1 +#define CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF 0 +#define CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF 5 +#define CONFIG_ESP_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_ESP_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_ESP_WIFI_RX_BA_WIN 6 +#define CONFIG_ESP_WIFI_NVS_ENABLED 1 +#define CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0 1 +#define CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN 752 +#define CONFIG_ESP_WIFI_MGMT_SBUF_NUM 32 +#define CONFIG_ESP_WIFI_IRAM_OPT 1 +#define CONFIG_ESP_WIFI_RX_IRAM_OPT 1 +#define CONFIG_ESP_WIFI_ENABLE_WPA3_SAE 1 +#define CONFIG_ESP_WIFI_ENABLE_SAE_PK 1 +#define CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT 1 +#define CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA 1 +#define CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME 50 +#define CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME 10 +#define CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME 15 +#define CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE 1 +#define CONFIG_ESP_WIFI_GMAC_SUPPORT 1 +#define CONFIG_ESP_WIFI_SOFTAP_SUPPORT 1 +#define CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM 7 +#define CONFIG_ESP_WIFI_MBEDTLS_CRYPTO 1 +#define CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT 1 +#define CONFIG_ESP_COREDUMP_ENABLE_TO_NONE 1 +#define CONFIG_FATFS_VOLUME_COUNT 2 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_FATFS_SECTOR_4096 1 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_FATFS_USE_STRFUNC_NONE 1 +#define CONFIG_FATFS_VFS_FSTAT_BLKSIZE 0 +#define CONFIG_FATFS_LINK_LOCK 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_FREERTOS_USE_TIMERS 1 +#define CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME "Tmr Svc" +#define CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY 1 +#define CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY 0x7FFFFFFF +#define CONFIG_FREERTOS_TIMER_TASK_PRIORITY 1 +#define CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH 2048 +#define CONFIG_FREERTOS_TIMER_QUEUE_LENGTH 10 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES 1 +#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 +#define CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER 1 +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_FREERTOS_SYSTICK_USES_CCOUNT 1 +#define CONFIG_FREERTOS_PORT 1 +#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF +#define CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION 1 +#define CONFIG_FREERTOS_DEBUG_OCDAWARE 1 +#define CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT 1 +#define CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH 1 +#define CONFIG_FREERTOS_NUMBER_OF_CORES 2 +#define CONFIG_HAL_ASSERTION_EQUALS_SYSTEM 1 +#define CONFIG_HAL_DEFAULT_ASSERTION_LEVEL 2 +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_HEAP_TRACING_OFF 1 +#define CONFIG_LOG_VERSION_1 1 +#define CONFIG_LOG_VERSION 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT 1 +#define CONFIG_LOG_MAXIMUM_LEVEL 3 +#define CONFIG_LOG_DYNAMIC_LEVEL_CONTROL 1 +#define CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST 1 +#define CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP 1 +#define CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE 31 +#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1 +#define CONFIG_LWIP_ENABLE 1 +#define CONFIG_LWIP_LOCAL_HOSTNAME "espressif" +#define CONFIG_LWIP_TCPIP_TASK_PRIO 18 +#define CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES 1 +#define CONFIG_LWIP_TIMERS_ONDEMAND 1 +#define CONFIG_LWIP_ND6 1 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_LWIP_IP_DEFAULT_TTL 64 +#define CONFIG_LWIP_IP4_FRAG 1 +#define CONFIG_LWIP_IP6_FRAG 1 +#define CONFIG_LWIP_IP_REASS_MAX_PBUFS 10 +#define CONFIG_LWIP_ESP_GRATUITOUS_ARP 1 +#define CONFIG_LWIP_GARP_TMR_INTERVAL 60 +#define CONFIG_LWIP_ESP_MLDV6_REPORT 1 +#define CONFIG_LWIP_MLDV6_TMR_INTERVAL 40 +#define CONFIG_LWIP_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID 1 +#define CONFIG_LWIP_DHCP_OPTIONS_LEN 68 +#define CONFIG_LWIP_NUM_NETIF_CLIENT_DATA 0 +#define CONFIG_LWIP_DHCP_COARSE_TIMER_SECS 1 +#define CONFIG_LWIP_DHCPS 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_LWIP_DHCPS_STATIC_ENTRIES 1 +#define CONFIG_LWIP_DHCPS_ADD_DNS 1 +#define CONFIG_LWIP_IPV4 1 +#define CONFIG_LWIP_IPV6 1 +#define CONFIG_LWIP_IPV6_NUM_ADDRESSES 3 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION 1 +#define CONFIG_LWIP_TCP_MAXRTX 12 +#define CONFIG_LWIP_TCP_SYNMAXRTX 12 +#define CONFIG_LWIP_TCP_MSS 1440 +#define CONFIG_LWIP_TCP_TMR_INTERVAL 250 +#define CONFIG_LWIP_TCP_MSL 60000 +#define CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT 20000 +#define CONFIG_LWIP_TCP_SND_BUF_DEFAULT 5760 +#define CONFIG_LWIP_TCP_WND_DEFAULT 5760 +#define CONFIG_LWIP_TCP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE 6 +#define CONFIG_LWIP_TCP_QUEUE_OOSEQ 1 +#define CONFIG_LWIP_TCP_OOSEQ_TIMEOUT 6 +#define CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS 4 +#define CONFIG_LWIP_TCP_OVERSIZE_MSS 1 +#define CONFIG_LWIP_TCP_RTO_TIME 1500 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_LWIP_UDP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_CHECKSUM_CHECK_ICMP 1 +#define CONFIG_LWIP_TCPIP_TASK_STACK_SIZE 3072 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY 0x7FFFFFFF +#define CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE 3 +#define CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS 5 +#define CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES 5 +#define CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS 3 +#define CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS 10 +#define CONFIG_LWIP_ICMP 1 +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_LWIP_SNTP_MAX_SERVERS 1 +#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000 +#define CONFIG_LWIP_SNTP_STARTUP_DELAY 1 +#define CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY 5000 +#define CONFIG_LWIP_DNS_MAX_HOST_IP 1 +#define CONFIG_LWIP_DNS_MAX_SERVERS 3 +#define CONFIG_LWIP_BRIDGEIF_MAX_PORTS 7 +#define CONFIG_LWIP_ESP_LWIP_ASSERT 1 +#define CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT 1 +#define CONFIG_LWIP_HOOK_IP6_ROUTE_NONE 1 +#define CONFIG_LWIP_HOOK_ND6_GET_GW_NONE 1 +#define CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE 1 +#define CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_NONE 1 +#define CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE 1 +#define CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE 1 +#define CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT 1 +#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 +#define CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN 1 +#define CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN 16384 +#define CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN 4096 +#define CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE 1 +#define CONFIG_MBEDTLS_PKCS7_C 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS 200 +#define CONFIG_MBEDTLS_CMAC_C 1 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER 1 +#define CONFIG_MBEDTLS_HARDWARE_MPI 1 +#define CONFIG_MBEDTLS_HARDWARE_SHA 1 +#define CONFIG_MBEDTLS_ROM_MD5 1 +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_MBEDTLS_ECDSA_DETERMINISTIC 1 +#define CONFIG_MBEDTLS_SHA512_C 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED 1 +#define CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_MBEDTLS_ERROR_STRINGS 1 +#define CONFIG_MBEDTLS_FS_IO 1 +#define CONFIG_MQTT_PROTOCOL_311 1 +#define CONFIG_MQTT_TRANSPORT_SSL 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 +#define CONFIG_LIBC_NEWLIB 1 +#define CONFIG_LIBC_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_LIBC_STDIN_LINE_ENDING_CR 1 +#define CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT 1 +#define CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0 1 +#define CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1 1 +#define CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2 1 +#define CONFIG_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_PTHREAD_STACK_MIN 768 +#define CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY 1 +#define CONFIG_PTHREAD_TASK_CORE_DEFAULT -1 +#define CONFIG_PTHREAD_TASK_NAME_DEFAULT "pthread" +#define CONFIG_MMU_PAGE_SIZE_64KB 1 +#define CONFIG_MMU_PAGE_MODE "64KB" +#define CONFIG_MMU_PAGE_SIZE 0x10000 +#define CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC 1 +#define CONFIG_SPI_FLASH_BROWNOUT_RESET 1 +#define CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US 50 +#define CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM 1 +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS 1 +#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 +#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 +#define CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE 8192 +#define CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORTED 1 +#define CONFIG_SPI_FLASH_VENDOR_GD_SUPPORTED 1 +#define CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORTED 1 +#define CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORTED 1 +#define CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORTED 1 +#define CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_GD_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP 1 +#define CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_WS_TRANSPORT 1 +#define CONFIG_WS_BUFFER_SIZE 1024 +#define CONFIG_UNITY_ENABLE_FLOAT 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 +#define CONFIG_VFS_SUPPORT_IO 1 +#define CONFIG_VFS_SUPPORT_DIR 1 +#define CONFIG_VFS_SUPPORT_SELECT 1 +#define CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT 1 +#define CONFIG_VFS_SUPPORT_TERMIOS 1 +#define CONFIG_VFS_MAX_COUNT 8 +#define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1 +#define CONFIG_VFS_INITIALIZE_DEV_NULL 1 +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 +#define CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT 30 +#define CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN 1 +#define CONFIG_MDNS_MAX_INTERFACES 3 +#define CONFIG_MDNS_MAX_SERVICES 10 +#define CONFIG_MDNS_TASK_PRIORITY 1 +#define CONFIG_MDNS_ACTION_QUEUE_LEN 16 +#define CONFIG_MDNS_TASK_STACK_SIZE 4096 +#define CONFIG_MDNS_TASK_AFFINITY_CPU0 1 +#define CONFIG_MDNS_TASK_AFFINITY 0x0 +#define CONFIG_MDNS_TASK_CREATE_FROM_INTERNAL 1 +#define CONFIG_MDNS_MEMORY_ALLOC_INTERNAL 1 +#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 2000 +#define CONFIG_MDNS_TIMER_PERIOD_MS 100 +#define CONFIG_MDNS_ENABLE_CONSOLE_CLI 1 +#define CONFIG_MDNS_MULTIPLE_INSTANCE 1 + +/* List of deprecated options */ +#define CONFIG_ADC2_DISABLE_DAC CONFIG_ADC_DISABLE_DAC +#define CONFIG_BROWNOUT_DET CONFIG_ESP_BROWNOUT_DET +#define CONFIG_BROWNOUT_DET_LVL CONFIG_ESP_BROWNOUT_DET_LVL +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0 +#define CONFIG_COMPILER_OPTIMIZATION_DEFAULT CONFIG_COMPILER_OPTIMIZATION_DEBUG +#define CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEBUG +#define CONFIG_CONSOLE_UART CONFIG_ESP_CONSOLE_UART +#define CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE +#define CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT +#define CONFIG_CONSOLE_UART_NUM CONFIG_ESP_CONSOLE_UART_NUM +#define CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE +#define CONFIG_ESP32_APPTRACE_LOCK_ENABLE CONFIG_APPTRACE_LOCK_ENABLE +#define CONFIG_ESP32_BROWNOUT_DET CONFIG_ESP_BROWNOUT_DET +#define CONFIG_ESP32_BROWNOUT_DET_LVL CONFIG_ESP_BROWNOUT_DET_LVL +#define CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0 +#define CONFIG_ESP32_DEBUG_OCDAWARE CONFIG_ESP_DEBUG_OCDAWARE +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ +#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE CONFIG_ESP_COREDUMP_ENABLE_TO_NONE +#define CONFIG_ESP32_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE +#define CONFIG_ESP32_PHY_MAX_TX_POWER CONFIG_ESP_PHY_MAX_TX_POWER +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER CONFIG_ESP_PHY_MAX_WIFI_TX_POWER +#define CONFIG_ESP32_PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN +#define CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT CONFIG_PTHREAD_TASK_CORE_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT CONFIG_PTHREAD_TASK_NAME_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT CONFIG_PTHREAD_TASK_PRIO_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES CONFIG_RTC_CLK_CAL_CYCLES +#define CONFIG_ESP32_RTC_CLK_SRC_INT_RC CONFIG_RTC_CLK_SRC_INT_RC +#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC CONFIG_RTC_CLK_SRC_INT_RC +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_HRT CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED CONFIG_ESP_WIFI_AMPDU_RX_ENABLED +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED CONFIG_ESP_WIFI_AMPDU_TX_ENABLED +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM +#define CONFIG_ESP32_WIFI_ENABLED CONFIG_ESP_WIFI_ENABLED +#define CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA +#define CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE CONFIG_ESP_WIFI_ENABLE_WPA3_SAE +#define CONFIG_ESP32_WIFI_IRAM_OPT CONFIG_ESP_WIFI_IRAM_OPT +#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM CONFIG_ESP_WIFI_MGMT_SBUF_NUM +#define CONFIG_ESP32_WIFI_NVS_ENABLED CONFIG_ESP_WIFI_NVS_ENABLED +#define CONFIG_ESP32_WIFI_RX_BA_WIN CONFIG_ESP_WIFI_RX_BA_WIN +#define CONFIG_ESP32_WIFI_RX_IRAM_OPT CONFIG_ESP_WIFI_RX_IRAM_OPT +#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM +#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0 +#define CONFIG_ESP32_WIFI_TX_BA_WIN CONFIG_ESP_WIFI_TX_BA_WIN +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE CONFIG_ESP_WIFI_TX_BUFFER_TYPE +#define CONFIG_ESP32_XTAL_FREQ CONFIG_XTAL_FREQ +#define CONFIG_ESP32_XTAL_FREQ_40 CONFIG_XTAL_FREQ_40 +#define CONFIG_ESP_GRATUITOUS_ARP CONFIG_LWIP_ESP_GRATUITOUS_ARP +#define CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY +#define CONFIG_ESP_SYSTEM_BROWNOUT_INTR CONFIG_ESP_BROWNOUT_USE_INTR +#define CONFIG_ESP_TASK_WDT CONFIG_ESP_TASK_WDT_INIT +#define CONFIG_FLASHMODE_DIO CONFIG_ESPTOOLPY_FLASHMODE_DIO +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR +#define CONFIG_GARP_TMR_INTERVAL CONFIG_LWIP_GARP_TMR_INTERVAL +#define CONFIG_GDBSTUB_MAX_TASKS CONFIG_ESP_GDBSTUB_MAX_TASKS +#define CONFIG_GDBSTUB_SUPPORT_TASKS CONFIG_ESP_GDBSTUB_SUPPORT_TASKS +#define CONFIG_INT_WDT CONFIG_ESP_INT_WDT +#define CONFIG_INT_WDT_CHECK_CPU1 CONFIG_ESP_INT_WDT_CHECK_CPU1 +#define CONFIG_INT_WDT_TIMEOUT_MS CONFIG_ESP_INT_WDT_TIMEOUT_MS +#define CONFIG_IPC_TASK_STACK_SIZE CONFIG_ESP_IPC_TASK_STACK_SIZE +#define CONFIG_LOG_BOOTLOADER_LEVEL CONFIG_BOOTLOADER_LOG_LEVEL +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO CONFIG_BOOTLOADER_LOG_LEVEL_INFO +#define CONFIG_MAIN_TASK_STACK_SIZE CONFIG_ESP_MAIN_TASK_STACK_SIZE +#define CONFIG_MONITOR_BAUD CONFIG_ESPTOOLPY_MONITOR_BAUD +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR CONFIG_LIBC_STDIN_LINE_ENDING_CR +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF CONFIG_LIBC_STDOUT_LINE_ENDING_CRLF +#define CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT +#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE +#define CONFIG_OPTIMIZATION_ASSERTION_LEVEL CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEBUG +#define CONFIG_POST_EVENTS_FROM_IRAM_ISR CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR +#define CONFIG_POST_EVENTS_FROM_ISR CONFIG_ESP_EVENT_POST_FROM_ISR +#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS +#define CONFIG_STACK_CHECK_NONE CONFIG_COMPILER_STACK_CHECK_MODE_NONE +#define CONFIG_SUPPORT_TERMIOS CONFIG_VFS_SUPPORT_TERMIOS +#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE +#define CONFIG_TASK_WDT CONFIG_ESP_TASK_WDT_INIT +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 +#define CONFIG_TASK_WDT_TIMEOUT_S CONFIG_ESP_TASK_WDT_TIMEOUT_S +#define CONFIG_TCPIP_RECVMBOX_SIZE CONFIG_LWIP_TCPIP_RECVMBOX_SIZE +#define CONFIG_TCPIP_TASK_AFFINITY CONFIG_LWIP_TCPIP_TASK_AFFINITY +#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY +#define CONFIG_TCPIP_TASK_STACK_SIZE CONFIG_LWIP_TCPIP_TASK_STACK_SIZE +#define CONFIG_TCP_MAXRTX CONFIG_LWIP_TCP_MAXRTX +#define CONFIG_TCP_MSL CONFIG_LWIP_TCP_MSL +#define CONFIG_TCP_MSS CONFIG_LWIP_TCP_MSS +#define CONFIG_TCP_OVERSIZE_MSS CONFIG_LWIP_TCP_OVERSIZE_MSS +#define CONFIG_TCP_QUEUE_OOSEQ CONFIG_LWIP_TCP_QUEUE_OOSEQ +#define CONFIG_TCP_RECVMBOX_SIZE CONFIG_LWIP_TCP_RECVMBOX_SIZE +#define CONFIG_TCP_SND_BUF_DEFAULT CONFIG_LWIP_TCP_SND_BUF_DEFAULT +#define CONFIG_TCP_SYNMAXRTX CONFIG_LWIP_TCP_SYNMAXRTX +#define CONFIG_TCP_WND_DEFAULT CONFIG_LWIP_TCP_WND_DEFAULT +#define CONFIG_TIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH +#define CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY +#define CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH +#define CONFIG_TIMER_TASK_STACK_SIZE CONFIG_ESP_TIMER_TASK_STACK_SIZE +#define CONFIG_TRACEMEM_RESERVE_DRAM CONFIG_ESP32_TRACEMEM_RESERVE_DRAM +#define CONFIG_UDP_RECVMBOX_SIZE CONFIG_LWIP_UDP_RECVMBOX_SIZE +#define CONFIG_WPA_MBEDTLS_CRYPTO CONFIG_ESP_WIFI_MBEDTLS_CRYPTO +#define CONFIG_WPA_MBEDTLS_TLS_CLIENT CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT diff --git a/components/mdns/tests/test_afl_fuzz_host/CMakeLists.txt b/components/mdns/tests/test_afl_fuzz_host/CMakeLists.txt index d65845194f..f4933a3cb8 100644 --- a/components/mdns/tests/test_afl_fuzz_host/CMakeLists.txt +++ b/components/mdns/tests/test_afl_fuzz_host/CMakeLists.txt @@ -1,7 +1,6 @@ # The following four lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) - +set(EXTRA_COMPONENT_DIRS ../../) include($ENV{IDF_PATH}/tools/cmake/project.cmake) - project(fuzz_test_update) From 6db95afc62e1bee254dbf0ec3cec3d0ad91881e0 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Sun, 30 Mar 2025 14:07:05 +0200 Subject: [PATCH 15/27] fix(mdns): Add host unit tests --- components/mdns/mdns_send.c | 30 ----- components/mdns/mdns_utils.c | 10 ++ .../mdns/private_include/mdns_querier.h | 4 + components/mdns/private_include/mdns_send.h | 5 - components/mdns/private_include/mdns_utils.h | 19 +++ .../mdns/tests/host_unit_test/CMakeLists.txt | 124 +++++++++++++++++- .../host_unit_test/input/generate_cases.py | 9 +- components/mdns/tests/host_unit_test/main.c | 114 ++++++++++++---- 8 files changed, 242 insertions(+), 73 deletions(-) diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index 3c4600f589..f99033d2be 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -25,36 +25,6 @@ static mdns_tx_packet_t *s_tx_queue_head; #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) #endif - -/** - * @brief appends byte in a packet, incrementing the index - * - * @param packet MDNS packet - * @param index offset in the packet - * @param value the value to set - * - * @return length of added data: 0 on error or 1 on success - */ -static inline uint8_t _mdns_append_u8(uint8_t *packet, uint16_t *index, uint8_t value) -{ - if (*index >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - packet[*index] = value; - *index += 1; - return 1; -} - -uint8_t mdns_utils_append_u16(uint8_t *packet, uint16_t *index, uint16_t value) -{ - if ((*index + 1) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, (value >> 8) & 0xFF); - _mdns_append_u8(packet, index, value & 0xFF); - return 2; -} - /** * @brief appends uint32_t in a packet, incrementing the index * diff --git a/components/mdns/mdns_utils.c b/components/mdns/mdns_utils.c index 816ff903f5..0017a0c7f8 100644 --- a/components/mdns/mdns_utils.c +++ b/components/mdns/mdns_utils.c @@ -255,3 +255,13 @@ bool mdns_utils_ipv6_address_is_zero(esp_ip6_addr_t ip6) return true; } #endif /* CONFIG_LWIP_IPV6 */ + +uint8_t mdns_utils_append_u16(uint8_t *packet, uint16_t *index, uint16_t value) +{ + if ((*index + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, (value >> 8) & 0xFF); + _mdns_append_u8(packet, index, value & 0xFF); + return 2; +} diff --git a/components/mdns/private_include/mdns_querier.h b/components/mdns/private_include/mdns_querier.h index 545a6ef9b7..663700335c 100644 --- a/components/mdns/private_include/mdns_querier.h +++ b/components/mdns/private_include/mdns_querier.h @@ -101,6 +101,10 @@ static inline void mdns_priv_query_update_result_ttl(mdns_result_t *r, uint32_t r->ttl = r->ttl < ttl ? r->ttl : ttl; } +/** + * @brief Send a search query packet on the specified interface and protocol + */ +void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); #ifdef __cplusplus } diff --git a/components/mdns/private_include/mdns_send.h b/components/mdns/private_include/mdns_send.h index 2817bb98ce..47fcee4f64 100644 --- a/components/mdns/private_include/mdns_send.h +++ b/components/mdns/private_include/mdns_send.h @@ -12,11 +12,6 @@ extern "C" { #endif -/** - * @brief Send a search query packet on the specified interface and protocol - */ -void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); - /** * @brief Free a transmit packet and its associated resources */ diff --git a/components/mdns/private_include/mdns_utils.h b/components/mdns/private_include/mdns_utils.h index 9bec567d0d..d574a07257 100644 --- a/components/mdns/private_include/mdns_utils.h +++ b/components/mdns/private_include/mdns_utils.h @@ -134,3 +134,22 @@ void mdns_utils_free_address_list(mdns_ip_addr_t *address_list); * @return length of added data: 0 on error or 2 on success */ uint8_t mdns_utils_append_u16(uint8_t *packet, uint16_t *index, uint16_t value); + +/** + * @brief appends byte in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 1 on success + */ +static inline uint8_t _mdns_append_u8(uint8_t *packet, uint16_t *index, uint8_t value) +{ + if (*index >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + packet[*index] = value; + *index += 1; + return 1; +} diff --git a/components/mdns/tests/host_unit_test/CMakeLists.txt b/components/mdns/tests/host_unit_test/CMakeLists.txt index 760b5847cf..63294129e8 100644 --- a/components/mdns/tests/host_unit_test/CMakeLists.txt +++ b/components/mdns/tests/host_unit_test/CMakeLists.txt @@ -44,6 +44,92 @@ include_directories( set(UNITY_DIR "$ENV{IDF_PATH}/components/unity") include_directories(${UNITY_DIR}/unity/src) +# Add option to enable unit testing +option(ENABLE_UNIT_TESTS "Enable Unity-based unit tests" OFF) + +# Add preprocessor definition based on the option +if(ENABLE_UNIT_TESTS) + add_definitions(-DENABLE_UNIT_TESTS) +endif() + +# Add CMock options +if(ENABLE_UNIT_TESTS) + # CMock paths + set(CMOCK_DIR "$ENV{IDF_PATH}/components/cmock") + + # Use ruby command directly instead of looking for ruby.exe + find_program(RUBY_EXECUTABLE ruby) + if(NOT RUBY_EXECUTABLE) + message(FATAL_ERROR "Ruby is required for CMock but was not found!") + endif() + + # Define list of files to mock + set(MOCK_FILES + "mdns_pcb" + "mdns_send" + # Add more files here as needed, without .h extension + ) + + # Verify headers exist and create mock commands for each + foreach(mock_file ${MOCK_FILES}) + set(header_path "${COMPONENT_DIR}/private_include/${mock_file}.h") + if(NOT EXISTS ${header_path}) + message(FATAL_ERROR "Cannot find ${mock_file}.h at ${header_path}") + endif() + + list(APPEND MOCK_OUTPUTS + ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.c + ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.h + ) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.c + ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.h + COMMAND ${RUBY_EXECUTABLE} + ${CMOCK_DIR}/CMock/lib/cmock.rb + -o${CMAKE_CURRENT_SOURCE_DIR}/cmock_config.yml + ${header_path} + DEPENDS ${header_path} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating mock for ${mock_file}.h" + ) + endforeach() + + # Include CMock headers + include_directories( + ${CMOCK_DIR}/CMock/src + ${CMAKE_CURRENT_BINARY_DIR}/mocks + ${UNITY_DIR}/unity/src + ${UNITY_DIR}/include + ) + + # Create directory for generated mocks + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mocks) + + # Create CMock config file if it doesn't exist + if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/cmock_config.yml) + file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/cmock_config.yml +"--- +:cmock: + :mock_prefix: mock_ + :plugins: + - :callback + - :ignore + - :expect_any_args + - :array + - :return_thru_ptr + :strippables: + - '(?:extern|static)\\s+' + :treat_as: + uint8_t: HEX8 + uint16_t: HEX16 + uint32_t: UINT32 + int8_t: INT8 + bool: UINT8" + ) + endif() +endif() + # Source files set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.c @@ -59,9 +145,26 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_send.c ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_pcb.c ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_netif.c - ${UNITY_DIR}/unity/src/unity.c ) +if(ENABLE_UNIT_TESTS) + # Remove real implementations of mocked files + foreach(mock_file ${MOCK_FILES}) + list(REMOVE_ITEM SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../${mock_file}.c) + endforeach() + + # Add test-related sources + list(APPEND SOURCES + ${UNITY_DIR}/unity/src/unity.c + ${CMOCK_DIR}/CMock/src/cmock.c + ) + + # Add all generated mock files + foreach(mock_file ${MOCK_FILES}) + list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.c) + endforeach() +endif() + # Enable sanitizers #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer") #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") @@ -84,12 +187,11 @@ endif() # COMPILE_FLAGS "-Wall -Werror" #) -# Test command with ASAN options -#enable_testing() -#add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) -#set_tests_properties(${PROJECT_NAME} PROPERTIES -# ENVIRONMENT "ASAN_OPTIONS=detect_leaks=1:verbosity=1:log_path=asan.log:print_stats=1:malloc_context_size=20" -#) +# Enable testing if unit tests are enabled +if(ENABLE_UNIT_TESTS) + enable_testing() + add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME} --test) +endif() # Add libbsd dependency #find_package(PkgConfig REQUIRED) @@ -102,3 +204,11 @@ endif() # Add include directories if needed #target_include_directories(${PROJECT_NAME} PRIVATE ${LIBBSD_INCLUDE_DIRS}) + +# Add mock generation as dependency +if(ENABLE_UNIT_TESTS) + add_custom_target(generate_mocks + DEPENDS ${MOCK_OUTPUTS} + ) + add_dependencies(${PROJECT_NAME} generate_mocks) +endif() diff --git a/components/mdns/tests/host_unit_test/input/generate_cases.py b/components/mdns/tests/host_unit_test/input/generate_cases.py index 743bcffb08..5bf0193eee 100644 --- a/components/mdns/tests/host_unit_test/input/generate_cases.py +++ b/components/mdns/tests/host_unit_test/input/generate_cases.py @@ -54,19 +54,12 @@ def create_mdns_packet(queries, answers, additional, output_file='mdns_packet.bi # Test case 1: Basic hostname queries queries = [ + ('test4.local.', 1), # A record for main hostname ('test.local.', 1), # A record for main hostname - ('test2.local.', 1), # A record for instance name - ('test3.local.', 1), # A record for delegate hostname - ('test4.local.', 28), # AAAA record for delegate hostname ] answers = [ - ('test.local.', 'A', '192.168.1.100', 120), - ('test2.local.', 'A', '192.168.1.101', 120), - ('test3.local.', 'A', '192.168.1.102', 120), - ('test4.local.', 'AAAA', 'fe80::1', 120), ] additional = [ - ('test.local.', 'TXT', 'board=esp32', 120), ] create_mdns_packet(queries, answers, additional, 'test_hostname_queries.bin') print('Test case 1: Hostname queries') diff --git a/components/mdns/tests/host_unit_test/main.c b/components/mdns/tests/host_unit_test/main.c index 096e7f3f3a..c567c611b8 100644 --- a/components/mdns/tests/host_unit_test/main.c +++ b/components/mdns/tests/host_unit_test/main.c @@ -12,28 +12,28 @@ #include "mdns_receive.h" #include "mdns_responder.h" #include "mdns_mem_caps.h" -// Define any mocks or stubs that might be needed -// For example, if mdns_receive.c requires networking functions, you might need to mock them +#ifdef ENABLE_UNIT_TESTS +#include "mock_mdns_pcb.h" +#include "mock_mdns_send.h" void setUp(void) { - // This is run before each test } void tearDown(void) { - // This is run after each test } // Sample test case - update based on the actual functionality in mdns_receive.c void test_mdns_receive_initialization(void) { - // Add your test implementation here - // Example: - // TEST_ASSERT_EQUAL(EXPECTED_VALUE, actual_value); +// mdns_priv_probe_all_pcbs_ExpectAnyArgs(); + // Example of using mocks + // mock_mdns_pcb_init_ExpectAndReturn(ESP_OK); + // Add more mock expectations as needed } -// Add more test cases as needed +#endif esp_err_t mdns_packet_push(esp_ip_addr_t *addr, int port, mdns_if_t tcpip_if, uint8_t*data, size_t len); @@ -96,33 +96,99 @@ static void send_packet(bool ip4, bool mdns_port, uint8_t*data, size_t len) printf("Failed to push packet\n"); } } -// UNITY_BEGIN(); -// mdns_free(); -// Register test cases -// RUN_TEST(test_mdns_receive_initialization); -// Add more test cases as needed - -// return UNITY_END(); -//} + +#ifdef ENABLE_UNIT_TESTS +// Add new test cases for mdns_receive +void test_mdns_receive_from_file(const char* filename) +{ + uint8_t buf[1460]; + FILE *file = fopen(filename, "r"); + TEST_ASSERT_NOT_NULL_MESSAGE(file, "Failed to open test packet file"); + + size_t len = fread(buf, 1, 1460, file); + fclose(file); + + // Test with different packet configurations + send_packet(true, true, buf, len); + send_packet(true, false, buf, len); + send_packet(false, true, buf, len); + send_packet(false, false, buf, len); + + // Add assertions here based on expected behavior + // For example: + // TEST_ASSERT_EQUAL(expected_result, actual_result); +} + +void run_unity_tests(int argc, char **argv) +{ + UNITY_BEGIN(); + + // Run basic initialization test + RUN_TEST(test_mdns_receive_initialization); + + // If a packet file is provided as argument, run packet-based tests + if (argc > 2 && strcmp(argv[1], "--test") == 0) { + for (int i = 2; i < argc; i++) { + printf("Testing with packet file: %s\n", argv[i]); + test_mdns_receive_from_file(argv[i]); + } + } + + UNITY_END(); +} + +void mdns_priv_probe_all_pcbs_Callback(mdns_srv_item_t** services, size_t len, bool probe_ip, bool clear_old_probe, int cmock_num_calls) +{ + +} + +void mdns_priv_create_answer_from_parsed_packet_Callback(mdns_parsed_packet_t* parsed_packet, int cmock_num_calls) +{ + printf("callback\n"); +} +#endif + int main(int argc, char **argv) { +#ifdef ENABLE_UNIT_TESTS + if (argc >= 2 && strcmp(argv[1], "--test") == 0) { + mdns_priv_probe_all_pcbs_CMockIgnore(); + mdns_priv_pcb_announce_CMockIgnore(); + mdns_priv_pcb_send_bye_service_CMockIgnore(); + mdns_priv_pcb_check_probing_services_CMockIgnore(); + mdns_priv_pcb_is_after_probing_IgnoreAndReturn(true); + + _mdns_clear_tx_queue_head_CMockIgnore(); + _mdns_remove_scheduled_service_packets_CMockIgnore(); + mdns_priv_create_answer_from_parsed_packet_Stub(mdns_priv_create_answer_from_parsed_packet_Callback); + // mdns_priv_probe_all_pcbs_AddCallback(mdns_priv_probe_all_pcbs_Callback); + // mdns_priv_probe_all_pcbs_ExpectAnyArgs(); + + init_responder(); + run_unity_tests(argc, argv); + deinit_responder(); + return 0; + } +#endif + init_responder(); + + // Original fuzzing code uint8_t buf[1460]; FILE *file; size_t len = 1460; memset(buf, 0, len); #ifndef __AFL_LOOP + // + // Note: parameter1 is a file (mangled packet) which caused the crash if (argc != 2) { printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n"); return 1; - } else { - // - // Note: parameter1 is a file (mangled packet) which caused the crash - file = fopen(argv[1], "r"); - assert(file >= 0); - len = fread(buf, 1, 1460, file); - fclose(file); } + file = fopen(argv[1], "r"); + assert(file >= 0); + len = fread(buf, 1, 1460, file); + fclose(file); { #else while (__AFL_LOOP(1000)) { @@ -136,5 +202,7 @@ int main(int argc, char **argv) } deinit_responder(); + // ... rest of the existing fuzzing code ... + return 0; } From 0974c6b6226821d1465345e871a33fec7772423b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 31 Mar 2025 14:04:39 +0200 Subject: [PATCH 16/27] fix(mdns): Add receiver unit tests --- .github/workflows/mdns__host-tests.yml | 27 +++ .../mdns/tests/host_unit_test/CMakeLists.txt | 191 +++--------------- components/mdns/tests/host_unit_test/main.c | 98 --------- .../host_unit_test/unity/cmock_config.yml | 17 ++ .../host_unit_test/unity/create_test_packet.c | 160 +++++++++++++++ .../host_unit_test/unity/create_test_packet.h | 31 +++ .../host_unit_test/unity/enable_testing.cmake | 11 + .../unity/test_receiver/test_receiver.c | 73 +++++++ .../unity/test_receiver/unit_test.cmake | 7 + .../host_unit_test/unity/unit_test.cmake | 83 ++++++++ .../tests/host_unit_test/unity/unity_main.c | 161 +++++++++++++++ .../tests/host_unit_test/unity/unity_main.h | 10 + 12 files changed, 611 insertions(+), 258 deletions(-) create mode 100644 components/mdns/tests/host_unit_test/unity/cmock_config.yml create mode 100644 components/mdns/tests/host_unit_test/unity/create_test_packet.c create mode 100644 components/mdns/tests/host_unit_test/unity/create_test_packet.h create mode 100644 components/mdns/tests/host_unit_test/unity/enable_testing.cmake create mode 100644 components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c create mode 100644 components/mdns/tests/host_unit_test/unity/test_receiver/unit_test.cmake create mode 100644 components/mdns/tests/host_unit_test/unity/unit_test.cmake create mode 100644 components/mdns/tests/host_unit_test/unity/unity_main.c create mode 100644 components/mdns/tests/host_unit_test/unity/unity_main.h diff --git a/.github/workflows/mdns__host-tests.yml b/.github/workflows/mdns__host-tests.yml index fe8cd1b310..b92d78ea56 100644 --- a/.github/workflows/mdns__host-tests.yml +++ b/.github/workflows/mdns__host-tests.yml @@ -72,6 +72,33 @@ jobs: echo "OK" done + host_unit_test: + if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push' + name: Unit tests on host + strategy: + matrix: + idf_ver: ["latest"] + + runs-on: ubuntu-22.04 + container: espressif/idf:${{ matrix.idf_ver }} + steps: + - name: Checkout esp-protocols + uses: actions/checkout@v4 + - name: Install bsdlib and ruby + run: | + apt-get update -y + apt-get install -y libbsd-dev ruby + - name: Build and run unit tests + shell: bash + run: | + . ${IDF_PATH}/export.sh + cd components/mdns/tests/host_unit_test/ + idf.py reconfigure + mkdir build2 && cd build2 + cmake -DUNIT_TESTS=test_receiver .. + cmake --build . + ctest --extra-verbose + fuzz_test: if: contains(github.event.pull_request.labels.*.name, 'mdns-fuzz') || github.event_name == 'push' diff --git a/components/mdns/tests/host_unit_test/CMakeLists.txt b/components/mdns/tests/host_unit_test/CMakeLists.txt index 63294129e8..40d8c60e88 100644 --- a/components/mdns/tests/host_unit_test/CMakeLists.txt +++ b/components/mdns/tests/host_unit_test/CMakeLists.txt @@ -1,28 +1,35 @@ cmake_minimum_required(VERSION 3.5) if(ESP_PLATFORM) + # Used for reconfiguration of the project + # Executed by idf.py reconfigure set(EXTRA_COMPONENT_DIRS ../../) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mdns_host_unit_test_config) return() -endif () +endif() project(mdns_host_unit_test C) +# Set ENABLE_UNIT_TESTS with a default of OFF +if(NOT DEFINED UNIT_TESTS) + set(UNIT_TESTS "OFF" CACHE STRING "Unit tests: OFF, test_receiver, test_sender") +else() + set(ENABLE_UNIT_TESTS 1) + message(STATUS "Unit testing enabled with UNIT_TESTS=${UNIT_TESTS}") +endif() + # Set variables for directories set(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(STUB_DIR ${TEST_DIR}/stubs) +set(MDNS_DIR ${TEST_DIR}/../../) set(COMPONENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../) set(ESP_NETIF_LINUX_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../host_test/components/esp_netif_linux/include) set(COMMON_COMPONENTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../common_components/linux_compat/) set(IDF_COMPONENTS_DIR "$ENV{IDF_PATH}/components") -# Debug prints to see directory values -message(STATUS "TEST_DIR: ${TEST_DIR}") -message(STATUS "COMPONENT_DIR: ${COMPONENT_DIR}") - -# Include directories for the test files and other required files include_directories( ${TEST_DIR} - ${TEST_DIR}/stubs + ${STUB_DIR} ${TEST_DIR}/build/config ${COMMON_COMPONENTS_DIR}/freertos/include ${COMMON_COMPONENTS_DIR}/esp_timer/include @@ -40,175 +47,39 @@ include_directories( ${COMPONENT_DIR}/private_include ) -# Unity testing framework -set(UNITY_DIR "$ENV{IDF_PATH}/components/unity") -include_directories(${UNITY_DIR}/unity/src) - -# Add option to enable unit testing -option(ENABLE_UNIT_TESTS "Enable Unity-based unit tests" OFF) - -# Add preprocessor definition based on the option -if(ENABLE_UNIT_TESTS) - add_definitions(-DENABLE_UNIT_TESTS) -endif() - -# Add CMock options -if(ENABLE_UNIT_TESTS) - # CMock paths - set(CMOCK_DIR "$ENV{IDF_PATH}/components/cmock") - - # Use ruby command directly instead of looking for ruby.exe - find_program(RUBY_EXECUTABLE ruby) - if(NOT RUBY_EXECUTABLE) - message(FATAL_ERROR "Ruby is required for CMock but was not found!") - endif() - - # Define list of files to mock - set(MOCK_FILES - "mdns_pcb" - "mdns_send" - # Add more files here as needed, without .h extension - ) - - # Verify headers exist and create mock commands for each - foreach(mock_file ${MOCK_FILES}) - set(header_path "${COMPONENT_DIR}/private_include/${mock_file}.h") - if(NOT EXISTS ${header_path}) - message(FATAL_ERROR "Cannot find ${mock_file}.h at ${header_path}") - endif() - - list(APPEND MOCK_OUTPUTS - ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.c - ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.h - ) - - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.c - ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.h - COMMAND ${RUBY_EXECUTABLE} - ${CMOCK_DIR}/CMock/lib/cmock.rb - -o${CMAKE_CURRENT_SOURCE_DIR}/cmock_config.yml - ${header_path} - DEPENDS ${header_path} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating mock for ${mock_file}.h" - ) - endforeach() - - # Include CMock headers - include_directories( - ${CMOCK_DIR}/CMock/src - ${CMAKE_CURRENT_BINARY_DIR}/mocks - ${UNITY_DIR}/unity/src - ${UNITY_DIR}/include - ) - - # Create directory for generated mocks - file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mocks) - - # Create CMock config file if it doesn't exist - if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/cmock_config.yml) - file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/cmock_config.yml -"--- -:cmock: - :mock_prefix: mock_ - :plugins: - - :callback - - :ignore - - :expect_any_args - - :array - - :return_thru_ptr - :strippables: - - '(?:extern|static)\\s+' - :treat_as: - uint8_t: HEX8 - uint16_t: HEX16 - uint32_t: UINT32 - int8_t: INT8 - bool: UINT8" - ) - endif() -endif() - # Source files set(SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/stubs/mdns_mem_caps.c - ${CMAKE_CURRENT_SOURCE_DIR}/stubs/esp_idf.c - ${CMAKE_CURRENT_SOURCE_DIR}/stubs/mdns_networking.c - ${CMAKE_CURRENT_SOURCE_DIR}/stubs/mdns_engine.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_receive.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_utils.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_browser.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_querier.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_responder.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_send.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_pcb.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../mdns_netif.c + ${STUB_DIR}/mdns_mem_caps.c + ${STUB_DIR}/esp_idf.c + ${STUB_DIR}/mdns_networking.c + ${STUB_DIR}/mdns_engine.c + ${MDNS_DIR}/mdns_receive.c + ${MDNS_DIR}/mdns_utils.c + ${MDNS_DIR}/mdns_browser.c + ${MDNS_DIR}/mdns_querier.c + ${MDNS_DIR}/mdns_responder.c + ${MDNS_DIR}/mdns_send.c + ${MDNS_DIR}/mdns_pcb.c + ${MDNS_DIR}/mdns_netif.c ) if(ENABLE_UNIT_TESTS) - # Remove real implementations of mocked files - foreach(mock_file ${MOCK_FILES}) - list(REMOVE_ITEM SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../${mock_file}.c) - endforeach() - - # Add test-related sources - list(APPEND SOURCES - ${UNITY_DIR}/unity/src/unity.c - ${CMOCK_DIR}/CMock/src/cmock.c - ) - - # Add all generated mock files - foreach(mock_file ${MOCK_FILES}) - list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.c) - endforeach() + include(unity/unit_test.cmake) +else() + list(APPEND SOURCES main.c) endif() -# Enable sanitizers -#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer") -#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") - -# Setting C flags with debug symbols and disable optimization for better debugging -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0") - -# Create the test executable add_executable(${PROJECT_NAME} ${SOURCES}) +# Add libbsd if available find_library(LIB_BSD bsd) if(LIB_BSD) target_link_libraries(${PROJECT_NAME} PRIVATE ${LIB_BSD}) elseif(NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") message(WARNING "Missing LIBBSD library. Install libbsd-dev package and/or check linker directories.") endif() -# Setting C flags -#set_target_properties(${PROJECT_NAME} PROPERTIES -# C_STANDARD 99 -# COMPILE_FLAGS "-Wall -Werror" -#) # Enable testing if unit tests are enabled if(ENABLE_UNIT_TESTS) - enable_testing() - add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME} --test) -endif() - -# Add libbsd dependency -#find_package(PkgConfig REQUIRED) -#pkg_check_modules(LIBBSD REQUIRED libbsd-overlay) - -# Link against libbsd for strlcat -#target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBBSD_LIBRARIES}) -#target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=address -fsanitize=undefined) -#target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=address -fsanitize=undefined) - -# Add include directories if needed -#target_include_directories(${PROJECT_NAME} PRIVATE ${LIBBSD_INCLUDE_DIRS}) - -# Add mock generation as dependency -if(ENABLE_UNIT_TESTS) - add_custom_target(generate_mocks - DEPENDS ${MOCK_OUTPUTS} - ) - add_dependencies(${PROJECT_NAME} generate_mocks) + include(unity/enable_testing.cmake) endif() diff --git a/components/mdns/tests/host_unit_test/main.c b/components/mdns/tests/host_unit_test/main.c index c567c611b8..a507fba9ad 100644 --- a/components/mdns/tests/host_unit_test/main.c +++ b/components/mdns/tests/host_unit_test/main.c @@ -8,32 +8,9 @@ #include #include #include "esp_err.h" -#include "unity.h" #include "mdns_receive.h" #include "mdns_responder.h" #include "mdns_mem_caps.h" -#ifdef ENABLE_UNIT_TESTS -#include "mock_mdns_pcb.h" -#include "mock_mdns_send.h" - -void setUp(void) -{ -} - -void tearDown(void) -{ -} - -// Sample test case - update based on the actual functionality in mdns_receive.c -void test_mdns_receive_initialization(void) -{ -// mdns_priv_probe_all_pcbs_ExpectAnyArgs(); - // Example of using mocks - // mock_mdns_pcb_init_ExpectAndReturn(ESP_OK); - // Add more mock expectations as needed -} - -#endif esp_err_t mdns_packet_push(esp_ip_addr_t *addr, int port, mdns_if_t tcpip_if, uint8_t*data, size_t len); @@ -71,7 +48,6 @@ void init_responder(void) s_ptr = mdns_query_async_new("minifritz", "_http", "_tcp", MDNS_TYPE_PTR, 1000, 1, NULL); s_srv = mdns_query_async_new("fritz", "_http", "_tcp", MDNS_TYPE_SRV, 1000, 1, NULL); s_txt = mdns_query_async_new("fritz", "_http", "_tcp", MDNS_TYPE_TXT, 1000, 1, NULL); - } void deinit_responder(void) @@ -97,80 +73,8 @@ static void send_packet(bool ip4, bool mdns_port, uint8_t*data, size_t len) } } -#ifdef ENABLE_UNIT_TESTS -// Add new test cases for mdns_receive -void test_mdns_receive_from_file(const char* filename) -{ - uint8_t buf[1460]; - FILE *file = fopen(filename, "r"); - TEST_ASSERT_NOT_NULL_MESSAGE(file, "Failed to open test packet file"); - - size_t len = fread(buf, 1, 1460, file); - fclose(file); - - // Test with different packet configurations - send_packet(true, true, buf, len); - send_packet(true, false, buf, len); - send_packet(false, true, buf, len); - send_packet(false, false, buf, len); - - // Add assertions here based on expected behavior - // For example: - // TEST_ASSERT_EQUAL(expected_result, actual_result); -} - -void run_unity_tests(int argc, char **argv) -{ - UNITY_BEGIN(); - - // Run basic initialization test - RUN_TEST(test_mdns_receive_initialization); - - // If a packet file is provided as argument, run packet-based tests - if (argc > 2 && strcmp(argv[1], "--test") == 0) { - for (int i = 2; i < argc; i++) { - printf("Testing with packet file: %s\n", argv[i]); - test_mdns_receive_from_file(argv[i]); - } - } - - UNITY_END(); -} - -void mdns_priv_probe_all_pcbs_Callback(mdns_srv_item_t** services, size_t len, bool probe_ip, bool clear_old_probe, int cmock_num_calls) -{ - -} - -void mdns_priv_create_answer_from_parsed_packet_Callback(mdns_parsed_packet_t* parsed_packet, int cmock_num_calls) -{ - printf("callback\n"); -} -#endif - int main(int argc, char **argv) { -#ifdef ENABLE_UNIT_TESTS - if (argc >= 2 && strcmp(argv[1], "--test") == 0) { - mdns_priv_probe_all_pcbs_CMockIgnore(); - mdns_priv_pcb_announce_CMockIgnore(); - mdns_priv_pcb_send_bye_service_CMockIgnore(); - mdns_priv_pcb_check_probing_services_CMockIgnore(); - mdns_priv_pcb_is_after_probing_IgnoreAndReturn(true); - - _mdns_clear_tx_queue_head_CMockIgnore(); - _mdns_remove_scheduled_service_packets_CMockIgnore(); - mdns_priv_create_answer_from_parsed_packet_Stub(mdns_priv_create_answer_from_parsed_packet_Callback); - // mdns_priv_probe_all_pcbs_AddCallback(mdns_priv_probe_all_pcbs_Callback); - // mdns_priv_probe_all_pcbs_ExpectAnyArgs(); - - init_responder(); - run_unity_tests(argc, argv); - deinit_responder(); - return 0; - } -#endif - init_responder(); // Original fuzzing code @@ -202,7 +106,5 @@ int main(int argc, char **argv) } deinit_responder(); - // ... rest of the existing fuzzing code ... - return 0; } diff --git a/components/mdns/tests/host_unit_test/unity/cmock_config.yml b/components/mdns/tests/host_unit_test/unity/cmock_config.yml new file mode 100644 index 0000000000..2487467f2f --- /dev/null +++ b/components/mdns/tests/host_unit_test/unity/cmock_config.yml @@ -0,0 +1,17 @@ +--- +:cmock: + :mock_prefix: mock_ + :plugins: + - :callback + - :ignore + - :expect_any_args + - :array + - :return_thru_ptr + :strippables: + - '(?:extern|static)\s+' + :treat_as: + uint8_t: HEX8 + uint16_t: HEX16 + uint32_t: UINT32 + int8_t: INT8 + bool: UINT8 diff --git a/components/mdns/tests/host_unit_test/unity/create_test_packet.c b/components/mdns/tests/host_unit_test/unity/create_test_packet.c new file mode 100644 index 0000000000..eb25a228ab --- /dev/null +++ b/components/mdns/tests/host_unit_test/unity/create_test_packet.c @@ -0,0 +1,160 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include +#include "esp_err.h" +#include "unity.h" +#include "create_test_packet.h" + +// Encode a domain name in DNS format (length byte + characters) +size_t encode_dns_name(uint8_t* buffer, const char* name) +{ + size_t pos = 0; + const char* segment_start = name; + + // Process each segment (separated by dots) + for (const char* p = name; ; p++) { + if (*p == '.' || *p == 0) { + // Calculate segment length + size_t segment_len = p - segment_start; + + // Write length byte + buffer[pos++] = segment_len; + + // Write segment characters + for (size_t i = 0; i < segment_len; i++) { + buffer[pos++] = segment_start[i]; + } + + // If at end of string, exit loop + if (*p == 0) { + break; + } + + // Move to next segment + segment_start = p + 1; + } + } + + // Add null terminator + buffer[pos++] = 0; + + return pos; +} + +// Create an mDNS test packet from arrays of queries and answers +uint8_t* create_mdns_test_packet( + mdns_test_query_t queries[], size_t query_count, + mdns_test_answer_t answers[], size_t answer_count, + mdns_test_answer_t additional[], size_t additional_count, + size_t* packet_len) +{ + // Allocate buffer for packet (max reasonable size for test) + uint8_t* packet = malloc(1460); + size_t pos = 0; + + // DNS Header (12 bytes) + // Transaction ID + packet[pos++] = 0x00; + packet[pos++] = 0x00; + + // Flags (QR=1 for response if there are answers, AA=1) + uint16_t flags = 0x0000; + if (answer_count > 0) { + flags |= 0x8400; // QR=1, AA=1 + } + packet[pos++] = (flags >> 8) & 0xFF; + packet[pos++] = flags & 0xFF; + + // Counts + packet[pos++] = 0x00; + packet[pos++] = query_count & 0xFF; // QDCOUNT + packet[pos++] = 0x00; + packet[pos++] = answer_count & 0xFF; // ANCOUNT + packet[pos++] = 0x00; + packet[pos++] = 0x00; // NSCOUNT + packet[pos++] = 0x00; + packet[pos++] = additional_count & 0xFF; // ARCOUNT + + // Add queries + for (size_t i = 0; i < query_count; i++) { + // Encode name + pos += encode_dns_name(packet + pos, queries[i].name); + + // Type + packet[pos++] = (queries[i].type >> 8) & 0xFF; + packet[pos++] = queries[i].type & 0xFF; + + // Class + packet[pos++] = (queries[i].class >> 8) & 0xFF; + packet[pos++] = queries[i].class & 0xFF; + } + + // Add answers + for (size_t i = 0; i < answer_count; i++) { + // Encode name + pos += encode_dns_name(packet + pos, answers[i].name); + + // Type + packet[pos++] = (answers[i].type >> 8) & 0xFF; + packet[pos++] = answers[i].type & 0xFF; + + // Class + packet[pos++] = (answers[i].class >> 8) & 0xFF; + packet[pos++] = answers[i].class & 0xFF; + + // TTL (4 bytes) + packet[pos++] = (answers[i].ttl >> 24) & 0xFF; + packet[pos++] = (answers[i].ttl >> 16) & 0xFF; + packet[pos++] = (answers[i].ttl >> 8) & 0xFF; + packet[pos++] = answers[i].ttl & 0xFF; + + // Data length + packet[pos++] = (answers[i].data_len >> 8) & 0xFF; + packet[pos++] = answers[i].data_len & 0xFF; + + // Data + if (answers[i].data && answers[i].data_len > 0) { + memcpy(packet + pos, answers[i].data, answers[i].data_len); + pos += answers[i].data_len; + } + } + + // Add additional records + for (size_t i = 0; i < additional_count; i++) { + // Encode name + pos += encode_dns_name(packet + pos, additional[i].name); + + // Type + packet[pos++] = (additional[i].type >> 8) & 0xFF; + packet[pos++] = additional[i].type & 0xFF; + + // Class + packet[pos++] = (additional[i].class >> 8) & 0xFF; + packet[pos++] = additional[i].class & 0xFF; + + // TTL (4 bytes) + packet[pos++] = (additional[i].ttl >> 24) & 0xFF; + packet[pos++] = (additional[i].ttl >> 16) & 0xFF; + packet[pos++] = (additional[i].ttl >> 8) & 0xFF; + packet[pos++] = additional[i].ttl & 0xFF; + + // Data length + packet[pos++] = (additional[i].data_len >> 8) & 0xFF; + packet[pos++] = additional[i].data_len & 0xFF; + + // Data + if (additional[i].data && additional[i].data_len > 0) { + memcpy(packet + pos, additional[i].data, additional[i].data_len); + pos += additional[i].data_len; + } + } + + *packet_len = pos; + return packet; +} diff --git a/components/mdns/tests/host_unit_test/unity/create_test_packet.h b/components/mdns/tests/host_unit_test/unity/create_test_packet.h new file mode 100644 index 0000000000..25201c905c --- /dev/null +++ b/components/mdns/tests/host_unit_test/unity/create_test_packet.h @@ -0,0 +1,31 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#pragma once +// Structure for a DNS query +typedef struct { + const char* name; // Name to query (e.g., "test.local") + uint16_t type; // Query type (e.g., MDNS_TYPE_A) + uint16_t class; // Query class (typically 1 for IN) +} mdns_test_query_t; + +// Structure for a DNS answer record +typedef struct { + const char* name; // Name this record refers to + uint16_t type; // Record type + uint16_t class; // Record class + uint32_t ttl; // Time to live + uint16_t data_len; // Length of data + uint8_t* data; // Record data +} mdns_test_answer_t; + + +uint8_t* create_mdns_test_packet( + mdns_test_query_t queries[], size_t query_count, + mdns_test_answer_t answers[], size_t answer_count, + mdns_test_answer_t additional[], size_t additional_count, + size_t* packet_len); + +size_t encode_dns_name(uint8_t* buffer, const char* name); diff --git a/components/mdns/tests/host_unit_test/unity/enable_testing.cmake b/components/mdns/tests/host_unit_test/unity/enable_testing.cmake new file mode 100644 index 0000000000..5812cf463c --- /dev/null +++ b/components/mdns/tests/host_unit_test/unity/enable_testing.cmake @@ -0,0 +1,11 @@ +enable_testing() +add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME} --test) + +add_custom_target(generate_mocks + DEPENDS ${MOCK_OUTPUTS} +) +add_dependencies(${PROJECT_NAME} generate_mocks) + +# Add sanitizers: Please comment out when debugging +target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=address -fsanitize=undefined) +target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=address -fsanitize=undefined) diff --git a/components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c b/components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c new file mode 100644 index 0000000000..157aa5f8f2 --- /dev/null +++ b/components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c @@ -0,0 +1,73 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include "unity.h" +#include "create_test_packet.h" +#include "unity_main.h" + +static void test_mdns_hostname_queries(void) +{ + // Define the queries for test4.local and test.local + mdns_test_query_t queries[] = { + { "test4.local", 1, 1 }, // A record for test4.local + { "test.local", 1, 1 } // A record for test.local + }; + + // Create and send the packet + size_t packet_len; + uint8_t* packet = create_mdns_test_packet( + queries, 2, // Queries + NULL, 0, // No answers + NULL, 0, // No additional records + &packet_len + ); + + send_test_packet_multiple(packet, packet_len); +} + +// Example of a more complex test with answers and additional records +static void test_mdns_with_answers(void) +{ + // Define a query for _http._tcp.local PTR record + mdns_test_query_t queries[] = { + { "_http._tcp.local", 12, 1 } // PTR record + }; + + // Example data for a PTR record (simplified) + uint8_t ptr_data[200]; + size_t ptr_data_len = encode_dns_name(ptr_data, "test._http._tcp.local"); + + // Define an answer for the PTR record + mdns_test_answer_t answers[] = { + { "_http._tcp.local", 12, 1, 120, ptr_data_len, ptr_data } + }; + + // Create and send the packet + size_t packet_len; + uint8_t* packet = create_mdns_test_packet( + queries, 1, // Single query + answers, 1, // Single answer + NULL, 0, // No additional records + &packet_len + ); + + send_test_packet_multiple(packet, packet_len); + +} + + +void run_unity_tests(void) +{ + UNITY_BEGIN(); + + // Run hostname queries test + RUN_TEST(test_mdns_hostname_queries); + + // Run test with answers + RUN_TEST(test_mdns_with_answers); + + UNITY_END(); +} diff --git a/components/mdns/tests/host_unit_test/unity/test_receiver/unit_test.cmake b/components/mdns/tests/host_unit_test/unity/test_receiver/unit_test.cmake new file mode 100644 index 0000000000..b08bbe6c4d --- /dev/null +++ b/components/mdns/tests/host_unit_test/unity/test_receiver/unit_test.cmake @@ -0,0 +1,7 @@ +# Testing mDNS receiver, so mocking pbb and send +set(MOCK_FILES + "mdns_pcb" + "mdns_send" +) + +list(APPEND SOURCES unity/${UNIT_TESTS}/test_receiver.c) diff --git a/components/mdns/tests/host_unit_test/unity/unit_test.cmake b/components/mdns/tests/host_unit_test/unity/unit_test.cmake new file mode 100644 index 0000000000..3e14d81a0e --- /dev/null +++ b/components/mdns/tests/host_unit_test/unity/unit_test.cmake @@ -0,0 +1,83 @@ +set(UNITY_DIR "$ENV{IDF_PATH}/components/unity") +set(CMOCK_DIR "$ENV{IDF_PATH}/components/cmock") + +include_directories(${UNITY_DIR}/unity/src) +add_definitions(-DENABLE_UNIT_TESTS) + +# Use ruby command directly instead of looking for ruby.exe +find_program(RUBY_EXECUTABLE ruby) +if(NOT RUBY_EXECUTABLE) + message(FATAL_ERROR "Ruby is required for CMock but was not found!") +endif() + +include(unity/${UNIT_TESTS}/unit_test.cmake) + +# Define list of files to mock +#set(MOCK_FILES +# "mdns_pcb" +# "mdns_send" +# # Add more files here as needed, without .h extension +#) + +# Verify headers exist and create mock commands for each +foreach(mock_file ${MOCK_FILES}) + set(header_path "${COMPONENT_DIR}/private_include/${mock_file}.h") + if(NOT EXISTS ${header_path}) + message(FATAL_ERROR "Cannot find ${mock_file}.h at ${header_path}") + endif() + + list(APPEND MOCK_OUTPUTS + ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.c + ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.h + ) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.c + ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.h + COMMAND ${RUBY_EXECUTABLE} + ${CMOCK_DIR}/CMock/lib/cmock.rb + -o${CMAKE_CURRENT_SOURCE_DIR}/unity/cmock_config.yml + ${header_path} + DEPENDS ${header_path} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating mock for ${mock_file}.h" + ) +endforeach() + +# Include CMock headers +include_directories( + ${CMOCK_DIR}/CMock/src + ${CMAKE_CURRENT_BINARY_DIR}/mocks + ${UNITY_DIR}/unity/src + ${UNITY_DIR}/include + unity +) + +# Create directory for generated mocks +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mocks) + +foreach(mock_file ${MOCK_FILES}) + list(REMOVE_ITEM SOURCES ${MDNS_DIR}/${mock_file}.c) +endforeach() + +# Add test-related sources +list(APPEND SOURCES + ${UNITY_DIR}/unity/src/unity.c + ${CMOCK_DIR}/CMock/src/cmock.c + unity/unity_main.c + unity/create_test_packet.c +) + +# Add all generated mock files +foreach(mock_file ${MOCK_FILES}) + list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/mocks/mock_${mock_file}.c) +endforeach() + +#enable_testing() +#add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME} --test) +#add_custom_target(generate_mocks +# DEPENDS ${MOCK_OUTPUTS} +#) +#add_dependencies(${PROJECT_NAME} generate_mocks) +#target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=address -fsanitize=undefined) +#target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=address -fsanitize=undefined) diff --git a/components/mdns/tests/host_unit_test/unity/unity_main.c b/components/mdns/tests/host_unit_test/unity/unity_main.c new file mode 100644 index 0000000000..4319932508 --- /dev/null +++ b/components/mdns/tests/host_unit_test/unity/unity_main.c @@ -0,0 +1,161 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include +#include "esp_err.h" +#include "unity.h" +#include "mdns_receive.h" +#include "mdns_responder.h" +#include "mdns_mem_caps.h" +#include "mock_mdns_pcb.h" +#include "mock_mdns_send.h" +#include "create_test_packet.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +// Sample test case - update based on the actual functionality in mdns_receive.c +void test_init(void) +{ + + +} + +esp_err_t mdns_packet_push(esp_ip_addr_t *addr, int port, mdns_if_t tcpip_if, uint8_t*data, size_t len); + +mdns_search_once_t *s_a, *s_aaaa, *s_ptr, *s_srv, *s_txt; + +void init_responder(void) +{ + mdns_ip_addr_t addr = { .addr = { .u_addr = ESP_IPADDR_TYPE_V4 } }; + addr.addr.u_addr.ip4.addr = 0x11111111; + mdns_txt_item_t txt[4] = { + {"board", "esp32"}, + {"tcp_check", "no"}, + {"ssh_upload", "no"}, + {"auth_upload", "no"} + }; + mdns_priv_responder_init(); + mdns_hostname_set("test"); + mdns_instance_name_set("test2"); + mdns_delegate_hostname_add("test3", NULL); + mdns_delegate_hostname_add("test4", &addr); + mdns_service_add("inst1", "_http", "_tcp", 80, txt, 4); + mdns_service_subtype_add_for_host("inst1", "_http", "_tcp", "test", "subtype"); + mdns_service_add("inst2", "_http", "_tcp", 80, txt, 1); + mdns_service_subtype_add_for_host("inst2", "_http", "_tcp", "test", "subtype3"); + mdns_service_add("inst3", "_http", "_tcp", 80, NULL, 0); + mdns_service_add_for_host("deleg1", "_http", "_tcp", "test3", 80, txt, 2); + mdns_service_add_for_host(NULL, "_http", "_tcp", "test4", 80, txt, 2); + mdns_service_add(NULL, "_scanner", "_tcp", 80, NULL, 0); + mdns_service_add("inst5", "_scanner", "_tcp", 80, NULL, 0); + mdns_service_add("inst6", "_http", "_tcp", 80, NULL, 0); + mdns_service_add("inst7", "_sleep", "_udp", 80, NULL, 0); + + s_a = mdns_query_async_new("host_name", NULL, NULL, MDNS_TYPE_A, 1000, 1, NULL); + s_aaaa = mdns_query_async_new("host_name2", NULL, NULL, MDNS_TYPE_AAAA, 1000, 1, NULL); + s_ptr = mdns_query_async_new("minifritz", "_http", "_tcp", MDNS_TYPE_PTR, 1000, 1, NULL); + s_srv = mdns_query_async_new("fritz", "_http", "_tcp", MDNS_TYPE_SRV, 1000, 1, NULL); + s_txt = mdns_query_async_new("fritz", "_http", "_tcp", MDNS_TYPE_TXT, 1000, 1, NULL); + +} + +void deinit_responder(void) +{ + mdns_query_async_delete(s_a); + mdns_query_async_delete(s_aaaa); + mdns_query_async_delete(s_ptr); + mdns_query_async_delete(s_srv); + mdns_query_async_delete(s_txt); + mdns_service_remove_all(); + mdns_priv_responder_free(); +} + +void send_packet(bool ip4, bool mdns_port, uint8_t*data, size_t len) +{ + esp_ip_addr_t addr4 = ESP_IP4ADDR_INIT(192, 168, 1, 1); + esp_ip_addr_t addr6 = ESP_IP6ADDR_INIT(0x000002ff, 0, 0, 0xfe800000); + esp_ip_addr_t *addr = ip4 ? &addr4 : &addr6; + int port = mdns_port ? 53 : 5353; + + if (mdns_packet_push(addr, port, 0, data, len) != ESP_OK) { + printf("Failed to push packet\n"); + } +} + +// Helper function to send a test packet with different configurations and clean up +void send_test_packet_multiple(uint8_t* packet, size_t packet_len) +{ + if (packet) { + // Test with different packet configurations + send_packet(true, true, packet, packet_len); + send_packet(true, false, packet, packet_len); + send_packet(false, true, packet, packet_len); + send_packet(false, false, packet, packet_len); + + // Free the packet + free(packet); + } else { + printf("Failed to create test packet\n"); + } +} + +void test_mdns_receive_from_file(const char* filename) +{ + uint8_t buf[1460]; + FILE *file = fopen(filename, "r"); + TEST_ASSERT_NOT_NULL_MESSAGE(file, "Failed to open test packet file"); + + size_t len = fread(buf, 1, 1460, file); + fclose(file); + + // Test with different packet configurations + send_packet(true, true, buf, len); + send_packet(true, false, buf, len); + send_packet(false, true, buf, len); + send_packet(false, false, buf, len); + + // Add assertions here based on expected behavior + // For example: + // TEST_ASSERT_EQUAL(expected_result, actual_result); +} + + +void run_unity_tests(void); + +void mdns_priv_create_answer_from_parsed_packet_Callback(mdns_parsed_packet_t* parsed_packet, int cmock_num_calls) +{ + printf("callback\n"); +} + +int main(int argc, char **argv) +{ + if (argc >= 2 && strcmp(argv[1], "--test") == 0) { + mdns_priv_probe_all_pcbs_CMockIgnore(); + mdns_priv_pcb_announce_CMockIgnore(); + mdns_priv_pcb_send_bye_service_CMockIgnore(); + mdns_priv_pcb_check_probing_services_CMockIgnore(); + mdns_priv_pcb_is_after_probing_IgnoreAndReturn(true); + + _mdns_clear_tx_queue_head_CMockIgnore(); + _mdns_remove_scheduled_service_packets_CMockIgnore(); + mdns_priv_create_answer_from_parsed_packet_Stub(mdns_priv_create_answer_from_parsed_packet_Callback); + + init_responder(); + run_unity_tests(); + deinit_responder(); + return 0; + } + printf("Unit test configuration: run with --test argument\n"); + return 1; +} diff --git a/components/mdns/tests/host_unit_test/unity/unity_main.h b/components/mdns/tests/host_unit_test/unity/unity_main.h new file mode 100644 index 0000000000..b69098df00 --- /dev/null +++ b/components/mdns/tests/host_unit_test/unity/unity_main.h @@ -0,0 +1,10 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#pragma once +#include + +void send_packet(bool ip4, bool mdns_port, uint8_t*data, size_t len); +void send_test_packet_multiple(uint8_t* packet, size_t packet_len); From afbec7d98f762b7bc6cc046a7567d275b1579935 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 31 Mar 2025 15:51:35 +0200 Subject: [PATCH 17/27] feat(mdns): Add test template for mdns-sender --- .github/workflows/mdns__host-tests.yml | 5 +++ .../unity/test_receiver/test_receiver.c | 20 ++++++++++ .../unity/test_sender/test_sender.c | 40 +++++++++++++++++++ .../unity/test_sender/unit_test.cmake | 6 +++ .../tests/host_unit_test/unity/unity_main.c | 19 +-------- 5 files changed, 73 insertions(+), 17 deletions(-) create mode 100644 components/mdns/tests/host_unit_test/unity/test_sender/test_sender.c create mode 100644 components/mdns/tests/host_unit_test/unity/test_sender/unit_test.cmake diff --git a/.github/workflows/mdns__host-tests.yml b/.github/workflows/mdns__host-tests.yml index b92d78ea56..76895f778f 100644 --- a/.github/workflows/mdns__host-tests.yml +++ b/.github/workflows/mdns__host-tests.yml @@ -98,6 +98,11 @@ jobs: cmake -DUNIT_TESTS=test_receiver .. cmake --build . ctest --extra-verbose + cd .. + mkdir build3 && cd build3 + cmake -DUNIT_TESTS=test_sender .. + cmake --build . + ctest --extra-verbose fuzz_test: diff --git a/components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c b/components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c index 157aa5f8f2..b872ba997f 100644 --- a/components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c +++ b/components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c @@ -7,6 +7,9 @@ #include "unity.h" #include "create_test_packet.h" #include "unity_main.h" +#include "mock_mdns_pcb.h" +#include "mock_mdns_send.h" +#include "create_test_packet.h" static void test_mdns_hostname_queries(void) { @@ -58,6 +61,23 @@ static void test_mdns_with_answers(void) } +static void mdns_priv_create_answer_from_parsed_packet_Callback(mdns_parsed_packet_t* parsed_packet, int cmock_num_calls) +{ + printf("callback\n"); +} + +void setup_cmock(void) +{ + mdns_priv_probe_all_pcbs_CMockIgnore(); + mdns_priv_pcb_announce_CMockIgnore(); + mdns_priv_pcb_send_bye_service_CMockIgnore(); + mdns_priv_pcb_check_probing_services_CMockIgnore(); + mdns_priv_pcb_is_after_probing_IgnoreAndReturn(true); + + _mdns_clear_tx_queue_head_CMockIgnore(); + _mdns_remove_scheduled_service_packets_CMockIgnore(); + mdns_priv_create_answer_from_parsed_packet_Stub(mdns_priv_create_answer_from_parsed_packet_Callback); +} void run_unity_tests(void) { diff --git a/components/mdns/tests/host_unit_test/unity/test_sender/test_sender.c b/components/mdns/tests/host_unit_test/unity/test_sender/test_sender.c new file mode 100644 index 0000000000..8fb326cec4 --- /dev/null +++ b/components/mdns/tests/host_unit_test/unity/test_sender/test_sender.c @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include "unity.h" +#include "unity_main.h" +#include "mock_mdns_pcb.h" +#include "mdns_send.h" + +void setup_cmock(void) +{ + mdns_priv_probe_all_pcbs_CMockIgnore(); + mdns_priv_pcb_announce_CMockIgnore(); + mdns_priv_pcb_send_bye_service_CMockIgnore(); + mdns_priv_pcb_check_probing_services_CMockIgnore(); + mdns_priv_pcb_is_after_probing_IgnoreAndReturn(true); +} + + + +// Example of a more complex test with answers and additional records +static void test_dispatch_tx_packet(void) +{ + mdns_tx_packet_t p = {}; + _mdns_dispatch_tx_packet(&p); +} + + +void run_unity_tests(void) +{ + UNITY_BEGIN(); + + // Run hostname queries test + RUN_TEST(test_dispatch_tx_packet); + + + UNITY_END(); +} diff --git a/components/mdns/tests/host_unit_test/unity/test_sender/unit_test.cmake b/components/mdns/tests/host_unit_test/unity/test_sender/unit_test.cmake new file mode 100644 index 0000000000..2fa0b64337 --- /dev/null +++ b/components/mdns/tests/host_unit_test/unity/test_sender/unit_test.cmake @@ -0,0 +1,6 @@ +# Testing mDNS sender, need to mock pbb +set(MOCK_FILES + "mdns_pcb" +) + +list(APPEND SOURCES unity/${UNIT_TESTS}/test_sender.c) diff --git a/components/mdns/tests/host_unit_test/unity/unity_main.c b/components/mdns/tests/host_unit_test/unity/unity_main.c index 4319932508..cee65d98bb 100644 --- a/components/mdns/tests/host_unit_test/unity/unity_main.c +++ b/components/mdns/tests/host_unit_test/unity/unity_main.c @@ -12,9 +12,6 @@ #include "mdns_receive.h" #include "mdns_responder.h" #include "mdns_mem_caps.h" -#include "mock_mdns_pcb.h" -#include "mock_mdns_send.h" -#include "create_test_packet.h" void setUp(void) { @@ -132,24 +129,12 @@ void test_mdns_receive_from_file(const char* filename) void run_unity_tests(void); - -void mdns_priv_create_answer_from_parsed_packet_Callback(mdns_parsed_packet_t* parsed_packet, int cmock_num_calls) -{ - printf("callback\n"); -} +void setup_cmock(void); int main(int argc, char **argv) { if (argc >= 2 && strcmp(argv[1], "--test") == 0) { - mdns_priv_probe_all_pcbs_CMockIgnore(); - mdns_priv_pcb_announce_CMockIgnore(); - mdns_priv_pcb_send_bye_service_CMockIgnore(); - mdns_priv_pcb_check_probing_services_CMockIgnore(); - mdns_priv_pcb_is_after_probing_IgnoreAndReturn(true); - - _mdns_clear_tx_queue_head_CMockIgnore(); - _mdns_remove_scheduled_service_packets_CMockIgnore(); - mdns_priv_create_answer_from_parsed_packet_Stub(mdns_priv_create_answer_from_parsed_packet_Callback); + setup_cmock(); init_responder(); run_unity_tests(); From d8476779759e6efa91d9160b052621a4267ff1e4 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 1 Apr 2025 14:04:39 +0200 Subject: [PATCH 18/27] fix(mdns): Minor cleanup --- components/mdns/mdns_browser.c | 181 +++++++-------- components/mdns/mdns_netif.c | 208 +++++++++--------- components/mdns/mdns_networking_lwip.c | 38 ++-- components/mdns/mdns_networking_socket.c | 30 +-- components/mdns/mdns_pcb.c | 28 +-- components/mdns/mdns_querier.c | 22 +- components/mdns/mdns_receive.c | 59 ++--- components/mdns/mdns_send.c | 28 +-- components/mdns/mdns_service.c | 16 +- .../mdns/private_include/mdns_browser.h | 25 +-- components/mdns/private_include/mdns_netif.h | 13 +- .../mdns/private_include/mdns_networking.h | 25 ++- .../tests/host_unit_test/stubs/mdns_engine.c | 2 +- .../host_unit_test/stubs/mdns_networking.c | 14 +- .../tests/test_afl_fuzz_host/esp32_mock.h | 6 +- .../mdns/tests/test_afl_fuzz_host/mdns_mock.h | 8 +- 16 files changed, 358 insertions(+), 345 deletions(-) diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index 3476e3b064..ca3c0c1421 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -22,7 +22,7 @@ static mdns_browse_t *s_browse; /** * @brief Browse action */ -static esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse) +static esp_err_t send_browse_action(mdns_action_type_t type, mdns_browse_t *browse) { mdns_action_t *action = NULL; @@ -45,7 +45,7 @@ static esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t /** * @brief Free a browse item (Not free the list). */ -static void _mdns_browse_item_free(mdns_browse_t *browse) +static void browse_item_free(mdns_browse_t *browse) { mdns_mem_free(browse->service); mdns_mem_free(browse->proto); @@ -55,7 +55,7 @@ static void _mdns_browse_item_free(mdns_browse_t *browse) mdns_mem_free(browse); } -static void _mdns_browse_sync(mdns_browse_sync_t *browse_sync) +static void browse_sync(mdns_browse_sync_t *browse_sync) { mdns_browse_t *browse = browse_sync->browse; mdns_browse_result_sync_t *sync_result = browse_sync->sync_result; @@ -76,7 +76,7 @@ static void _mdns_browse_sync(mdns_browse_sync_t *browse_sync) /** * @brief Send PTR query packet to all available interfaces for browsing. */ -static void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface) +static void browse_send(mdns_browse_t *browse, mdns_if_t interface) { // Using search once for sending the PTR query mdns_search_once_t search = {0}; @@ -94,28 +94,28 @@ static void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface) } } -void mdns_browse_send_all(mdns_if_t mdns_if) +void mdns_priv_browse_send_all(mdns_if_t mdns_if) { mdns_browse_t *browse = s_browse; while (browse) { - _mdns_browse_send(browse, mdns_if); + browse_send(browse, mdns_if); browse = browse->next; } } -void mdns_browse_free(void) +void mdns_priv_browse_free(void) { while (s_browse) { mdns_browse_t *b = s_browse; s_browse = s_browse->next; - _mdns_browse_item_free(b); + browse_item_free(b); } } /** * @brief Mark browse as finished, remove and free it from browse chain */ -static void _mdns_browse_finish(mdns_browse_t *browse) +static void browse_finish(mdns_browse_t *browse) { browse->state = BROWSE_OFF; mdns_browse_t *b = s_browse; @@ -126,18 +126,18 @@ static void _mdns_browse_finish(mdns_browse_t *browse) target_free = b; b = b->next; queueDetach(mdns_browse_t, s_browse, target_free); - _mdns_browse_item_free(target_free); + browse_item_free(target_free); } else { b = b->next; } } - _mdns_browse_item_free(browse); + browse_item_free(browse); } /** * @brief Allocate new browse structure */ -static mdns_browse_t *_mdns_browse_init(const char *service, const char *proto, mdns_browse_notify_t notifier) +static mdns_browse_t *browse_init(const char *service, const char *proto, mdns_browse_notify_t notifier) { mdns_browse_t *browse = (mdns_browse_t *)mdns_mem_malloc(sizeof(mdns_browse_t)); @@ -151,7 +151,7 @@ static mdns_browse_t *_mdns_browse_init(const char *service, const char *proto, if (!mdns_utils_str_null_or_empty(service)) { browse->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); if (!browse->service) { - _mdns_browse_item_free(browse); + browse_item_free(browse); return NULL; } } @@ -159,7 +159,7 @@ static mdns_browse_t *_mdns_browse_init(const char *service, const char *proto, if (!mdns_utils_str_null_or_empty(proto)) { browse->proto = mdns_mem_strndup(proto, MDNS_NAME_BUF_LEN - 1); if (!browse->proto) { - _mdns_browse_item_free(browse); + browse_item_free(browse); return NULL; } } @@ -168,51 +168,10 @@ static mdns_browse_t *_mdns_browse_init(const char *service, const char *proto, return browse; } -mdns_browse_t *mdns_browse_new(const char *service, const char *proto, mdns_browse_notify_t notifier) -{ - mdns_browse_t *browse = NULL; - - if (mdns_priv_is_server_init() || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { - return NULL; - } - - browse = _mdns_browse_init(service, proto, notifier); - if (!browse) { - return NULL; - } - - if (_mdns_send_browse_action(ACTION_BROWSE_ADD, browse)) { - _mdns_browse_item_free(browse); - return NULL; - } - - return browse; -} - -esp_err_t mdns_browse_delete(const char *service, const char *proto) -{ - mdns_browse_t *browse = NULL; - - if (!mdns_priv_is_server_init() || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { - return ESP_FAIL; - } - - browse = _mdns_browse_init(service, proto, NULL); - if (!browse) { - return ESP_ERR_NO_MEM; - } - - if (_mdns_send_browse_action(ACTION_BROWSE_END, browse)) { - _mdns_browse_item_free(browse); - return ESP_ERR_NO_MEM; - } - return ESP_OK; -} - /** * @brief Add new browse to the browse chain */ -static void _mdns_browse_add(mdns_browse_t *browse) +static void browse_add(mdns_browse_t *browse) { browse->state = BROWSE_RUNNING; mdns_browse_t *queue = s_browse; @@ -231,17 +190,17 @@ static void _mdns_browse_add(mdns_browse_t *browse) s_browse = browse; } for (uint8_t interface_idx = 0; interface_idx < MDNS_MAX_INTERFACES; interface_idx++) { - _mdns_browse_send(browse, (mdns_if_t)interface_idx); + browse_send(browse, (mdns_if_t) interface_idx); } if (found) { - _mdns_browse_item_free(browse); + browse_item_free(browse); } } /** * @brief Called from packet parser to find matching running search */ -mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +mdns_browse_t *mdns_priv_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_browse_t *b = s_browse; // For browse, we only care about the SRV, TXT, A and AAAA @@ -260,7 +219,7 @@ mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcp } else if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { r = b->result; while (r) { - if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { + if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { return b; } r = r->next; @@ -272,7 +231,7 @@ mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcp return b; } -static void _mdns_sync_browse_result_link_free(mdns_browse_sync_t *browse_sync) +static void sync_browse_result_link_free(mdns_browse_sync_t *browse_sync) { mdns_browse_result_sync_t *current = browse_sync->sync_result; mdns_browse_result_sync_t *need_free; @@ -284,19 +243,19 @@ static void _mdns_sync_browse_result_link_free(mdns_browse_sync_t *browse_sync) mdns_mem_free(browse_sync); } -void mdns_browse_action(mdns_action_t *action, mdns_action_subtype_t type) +void mdns_priv_browse_action(mdns_action_t *action, mdns_action_subtype_t type) { if (type == ACTION_RUN) { switch (action->type) { case ACTION_BROWSE_ADD: - _mdns_browse_add(action->data.browse_add.browse); + browse_add(action->data.browse_add.browse); break; case ACTION_BROWSE_SYNC: - _mdns_browse_sync(action->data.browse_sync.browse_sync); - _mdns_sync_browse_result_link_free(action->data.browse_sync.browse_sync); + browse_sync(action->data.browse_sync.browse_sync); + sync_browse_result_link_free(action->data.browse_sync.browse_sync); break; case ACTION_BROWSE_END: - _mdns_browse_finish(action->data.browse_add.browse); + browse_finish(action->data.browse_add.browse); break; default: abort(); @@ -308,10 +267,10 @@ void mdns_browse_action(mdns_action_t *action, mdns_action_subtype_t type) case ACTION_BROWSE_ADD: //fallthrough case ACTION_BROWSE_END: - _mdns_browse_item_free(action->data.browse_add.browse); + browse_item_free(action->data.browse_add.browse); break; case ACTION_BROWSE_SYNC: - _mdns_sync_browse_result_link_free(action->data.browse_sync.browse_sync); + sync_browse_result_link_free(action->data.browse_sync.browse_sync); break; default: abort(); @@ -324,7 +283,7 @@ void mdns_browse_action(mdns_action_t *action, mdns_action_subtype_t type) /** * @brief Add result to browse, only add when the result is a new one. */ -static esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r) +static esp_err_t add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r) { mdns_browse_result_sync_t *sync_r = sync_browse->sync_result; while (sync_r) { @@ -351,8 +310,8 @@ static esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_r /** * @brief Called from parser to add A/AAAA data to search result */ -void mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +void mdns_priv_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) { if (out_sync_browse->browse == NULL) { return; @@ -368,7 +327,7 @@ void mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ while (r) { if (r->ip_protocol == ip_protocol) { // Find the target result in browse result. - if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { r_a = r->addr; // Check if the address has already added in result. while (r_a) { @@ -400,7 +359,7 @@ void mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ mdns_priv_query_update_result_ttl(r, ttl); } } - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + if (add_browse_result(out_sync_browse, r) != ESP_OK) { return; } break; @@ -430,9 +389,9 @@ static bool is_txt_item_in_list(mdns_txt_item_t txt, uint8_t txt_value_len, mdns /** * @brief Called from parser to add TXT data to search result */ -void mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, - mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +void mdns_priv_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, + mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl, mdns_browse_sync_t *out_sync_browse) { if (out_sync_browse->browse == NULL) { return; @@ -443,7 +402,7 @@ void mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, con } mdns_result_t *r = browse->result; while (r) { - if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && + if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && !mdns_utils_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && !mdns_utils_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { @@ -483,7 +442,7 @@ void mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, con } } if (should_update) { - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + if (add_browse_result(out_sync_browse, r) != ESP_OK) { return; } } @@ -510,12 +469,12 @@ void mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, con r->txt = txt; r->txt_value_len = txt_value_len; r->txt_count = txt_count; - r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); + r->esp_netif = mdns_priv_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = browse->result; browse->result = r; - _mdns_add_browse_result(out_sync_browse, r); + add_browse_result(out_sync_browse, r); return; free_txt: @@ -528,7 +487,7 @@ void mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, con return; } -static esp_err_t _mdns_copy_address_in_previous_result(mdns_result_t *result_list, mdns_result_t *r) +static esp_err_t copy_address_in_previous_result(mdns_result_t *result_list, mdns_result_t *r) { while (result_list) { if (!mdns_utils_str_null_or_empty(result_list->hostname) && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(result_list->hostname, r->hostname) && @@ -549,8 +508,8 @@ static esp_err_t _mdns_copy_address_in_previous_result(mdns_result_t *result_lis /** * @brief Called from parser to add SRV data to search result */ -void mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, - uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +void mdns_priv_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, + uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) { if (out_sync_browse->browse == NULL) { return; @@ -561,7 +520,7 @@ void mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, con } mdns_result_t *r = browse->result; while (r) { - if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && + if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && !mdns_utils_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && !mdns_utils_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { @@ -573,12 +532,12 @@ void mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, con return; } if (!r->addr) { - esp_err_t err = _mdns_copy_address_in_previous_result(browse->result, r); + esp_err_t err = copy_address_in_previous_result(browse->result, r); if (err == ESP_ERR_NO_MEM) { return; } } - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + if (add_browse_result(out_sync_browse, r) != ESP_OK) { return; } } @@ -590,7 +549,7 @@ void mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, con mdns_priv_query_update_result_ttl(r, ttl); } if (previous_ttl != r->ttl) { - if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + if (add_browse_result(out_sync_browse, r) != ESP_OK) { return; } } @@ -620,11 +579,55 @@ void mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, con return; } r->port = port; - r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); + r->esp_netif = mdns_priv_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = browse->result; browse->result = r; - _mdns_add_browse_result(out_sync_browse, r); + add_browse_result(out_sync_browse, r); return; } + +/** + * @defgroup MDNS_PUBCLIC_API + */ +mdns_browse_t *mdns_browse_new(const char *service, const char *proto, mdns_browse_notify_t notifier) +{ + mdns_browse_t *browse = NULL; + + if (mdns_priv_is_server_init() || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + return NULL; + } + + browse = browse_init(service, proto, notifier); + if (!browse) { + return NULL; + } + + if (send_browse_action(ACTION_BROWSE_ADD, browse)) { + browse_item_free(browse); + return NULL; + } + + return browse; +} + +esp_err_t mdns_browse_delete(const char *service, const char *proto) +{ + mdns_browse_t *browse = NULL; + + if (!mdns_priv_is_server_init() || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + return ESP_FAIL; + } + + browse = browse_init(service, proto, NULL); + if (!browse) { + return ESP_ERR_NO_MEM; + } + + if (send_browse_action(ACTION_BROWSE_END, browse)) { + browse_item_free(browse); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c index 73edffed05..88ead18e8a 100644 --- a/components/mdns/mdns_netif.c +++ b/components/mdns/mdns_netif.c @@ -66,12 +66,11 @@ static mdns_interfaces_t s_esp_netifs[MDNS_MAX_INTERFACES] = { }; - /** * @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_netif_get_other_interface(mdns_if_t tcpip_if) +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; @@ -85,7 +84,7 @@ mdns_if_t mdns_netif_get_other_interface(mdns_if_t tcpip_if) * @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_if(mdns_predef_if_t predef_if) +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) { @@ -100,7 +99,7 @@ static mdns_if_t mdns_if_from_preset_if(mdns_predef_if_t predef_if) * @param predef_if Predefined interface enum * @return esp_netif pointer from system list of network interfaces */ -static inline esp_netif_t *esp_netif_from_preset_if(mdns_predef_if_t predef_if) +static inline esp_netif_t *netif_from_preset(mdns_predef_if_t predef_if) { switch (predef_if) { case MDNS_IF_STA: @@ -116,12 +115,12 @@ static inline esp_netif_t *esp_netif_from_preset_if(mdns_predef_if_t predef_if) } } -esp_netif_t *mdns_netif_get_esp_netif(mdns_if_t tcpip_if) +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 = esp_netif_from_preset_if(s_esp_netifs[tcpip_if].predef_if); + 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; @@ -129,28 +128,26 @@ esp_netif_t *mdns_netif_get_esp_netif(mdns_if_t tcpip_if) return NULL; } - /* * @brief Clean internal mdns interface's pointer */ -void mdns_netif_disable(mdns_if_t tcpip_if) +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 _mdns_get_if_from_esp_netif(esp_netif_t *esp_netif) +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 = esp_netif_from_preset_if(s_esp_netifs[i].predef_if); + s_esp_netifs[i].netif = netif_from_preset(s_esp_netifs[i].predef_if); } if (esp_netif == s_esp_netifs[i].netif) { return i; @@ -159,7 +156,7 @@ static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *esp_netif) return MDNS_MAX_INTERFACES; } -static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action) +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; @@ -184,24 +181,27 @@ static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_ /** * @brief Dispatch interface changes based on system events */ -static inline void post_mdns_disable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) +static inline void post_disable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) { - mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(preset_if), protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_DISABLE_IP4 : MDNS_EVENT_DISABLE_IP6); + 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_mdns_enable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) +static inline void post_enable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) { - mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(preset_if), protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_ENABLE_IP4 : MDNS_EVENT_ENABLE_IP6); + 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_mdns_announce_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) +static inline void post_announce_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) { - mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(preset_if), protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_ANNOUNCE_IP4 : MDNS_EVENT_ANNOUNCE_IP6); + 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 -void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) +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; @@ -212,22 +212,22 @@ void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, if (event_base == WIFI_EVENT) { switch (event_id) { case WIFI_EVENT_STA_CONNECTED: - if (!esp_netif_dhcpc_get_status(esp_netif_from_preset_if(MDNS_IF_STA), &dcst)) { + if (!esp_netif_dhcpc_get_status(netif_from_preset(MDNS_IF_STA), &dcst)) { if (dcst == ESP_NETIF_DHCP_STOPPED) { - post_mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + post_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); } } break; case WIFI_EVENT_STA_DISCONNECTED: - post_mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); - post_mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6); + 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_mdns_enable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); + post_enable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); break; case WIFI_EVENT_AP_STOP: - post_mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); - post_mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V6); + post_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); + post_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V6); break; default: break; @@ -238,15 +238,15 @@ void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, if (event_base == ETH_EVENT) { switch (event_id) { case ETHERNET_EVENT_CONNECTED: - if (!esp_netif_dhcpc_get_status(esp_netif_from_preset_if(MDNS_IF_ETH), &dcst)) { + if (!esp_netif_dhcpc_get_status(netif_from_preset(MDNS_IF_ETH), &dcst)) { if (dcst == ESP_NETIF_DHCP_STOPPED) { - post_mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + post_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); } } break; case ETHERNET_EVENT_DISCONNECTED: - post_mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); - post_mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V6); + post_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + post_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V6); break; default: break; @@ -256,23 +256,23 @@ void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, if (event_base == IP_EVENT) { switch (event_id) { case IP_EVENT_STA_GOT_IP: - post_mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); - post_mdns_announce_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6); + 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_mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + 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 = _mdns_get_if_from_esp_netif(event->esp_netif); + mdns_if_t mdns_if = get_if_from_netif(event->esp_netif); if (mdns_if >= MDNS_MAX_INTERFACES) { return; } - post_mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); - post_mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); - mdns_browse_send_all(mdns_if); + 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; @@ -302,74 +302,20 @@ static inline void set_default_duplicated_interfaces(void) } } -void mdns_netif_unregister_predefined_handlers(void) +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, mdns_preset_if_handle_system_event); + 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, mdns_preset_if_handle_system_event); + 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, mdns_preset_if_handle_system_event); + esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, handle_system_event_for_preset); #endif } -/* - * Public Methods - * */ - -esp_err_t mdns_netif_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action) -{ - return mdns_post_custom_action_tcpip_if(_mdns_get_if_from_esp_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; -} - -esp_err_t mdns_netif_init(void) +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 @@ -377,17 +323,17 @@ esp_err_t mdns_netif_init(void) 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, mdns_preset_if_handle_system_event, NULL)) != ESP_OK) { + 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, mdns_preset_if_handle_system_event, NULL)) != ESP_OK) { + 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, mdns_preset_if_handle_system_event, NULL)) != ESP_OK) { + 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 @@ -406,12 +352,12 @@ esp_err_t mdns_netif_init(void) for (i = 0; i < MDNS_MAX_INTERFACES; i++) { #ifdef CONFIG_LWIP_IPV6 - if (!esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(i), &tmp_addr6) && !mdns_utils_ipv6_address_is_zero(tmp_addr6)) { + 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_netif_get_esp_netif(i), &if_ip_info) && if_ip_info.ip.addr) { + 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 @@ -419,12 +365,12 @@ esp_err_t mdns_netif_init(void) return ESP_OK; #if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH free_event_handlers: - mdns_netif_unregister_predefined_handlers(); + mdns_priv_netif_unregister_predefined_handlers(); #endif return err; } -esp_err_t mdns_netif_deinit(void) +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); @@ -433,3 +379,57 @@ esp_err_t mdns_netif_deinit(void) } 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; +} diff --git a/components/mdns/mdns_networking_lwip.c b/components/mdns/mdns_networking_lwip.c index c7ae6d30a9..e320b7c037 100644 --- a/components/mdns/mdns_networking_lwip.c +++ b/components/mdns/mdns_networking_lwip.c @@ -106,7 +106,7 @@ static void _udp_pcb_main_deinit(void) static esp_err_t _udp_join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protocol, bool join) { struct netif *netif = NULL; - esp_netif_t *tcpip_if = mdns_netif_get_esp_netif(if_inx); + esp_netif_t *tcpip_if = mdns_priv_get_esp_netif(if_inx); if (!esp_netif_is_netif_up(tcpip_if)) { // Network interface went down before event propagated, skipping IGMP config @@ -207,7 +207,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip struct netif *netif = NULL; bool found = false; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { - netif = esp_netif_get_netif_impl(mdns_netif_get_esp_netif(i)); + netif = esp_netif_get_netif_impl(mdns_priv_get_esp_netif(i)); if (s_interfaces[i].proto && netif && netif == ip_current_input_netif()) { #if LWIP_IPV4 if (packet->src.type == IPADDR_TYPE_V4) { @@ -231,7 +231,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip } -bool mdns_is_netif_ready(mdns_if_t netif, mdns_ip_protocol_t ip_proto) +bool mdns_priv_if_ready(mdns_if_t netif, mdns_ip_protocol_t ip_proto) { return s_interfaces[netif].ready && s_interfaces[netif].proto & (ip_proto == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6); @@ -245,7 +245,7 @@ static bool _udp_pcb_is_in_use(void) int i, p; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { for (p = 0; p < MDNS_IP_PROTOCOL_MAX; p++) { - if (mdns_is_netif_ready(i, p)) { + if (mdns_priv_if_ready(i, p)) { return true; } } @@ -273,7 +273,7 @@ static void _udp_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) */ static esp_err_t _udp_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { - if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { + if (mdns_priv_if_ready(tcpip_if, ip_protocol)) { return ESP_ERR_INVALID_STATE; } @@ -305,7 +305,7 @@ typedef struct { /** * @brief Start PCB from LwIP thread */ -static err_t _mdns_pcb_init_api(struct tcpip_api_call_data *api_call_msg) +static err_t mdns_priv_if_init_api(struct tcpip_api_call_data *api_call_msg) { mdns_api_call_t *msg = (mdns_api_call_t *)api_call_msg; msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol) == ESP_OK ? ERR_OK : ERR_IF; @@ -315,7 +315,7 @@ static err_t _mdns_pcb_init_api(struct tcpip_api_call_data *api_call_msg) /** * @brief Stop PCB from LwIP thread */ -static err_t _mdns_pcb_deinit_api(struct tcpip_api_call_data *api_call_msg) +static err_t mdns_priv_if_deinit_api(struct tcpip_api_call_data *api_call_msg) { mdns_api_call_t *msg = (mdns_api_call_t *)api_call_msg; _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol); @@ -328,32 +328,32 @@ static err_t _mdns_pcb_deinit_api(struct tcpip_api_call_data *api_call_msg) * - _mdns prefixed * - commented in mdns_networking.h header */ -esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +esp_err_t mdns_priv_if_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_api_call_t msg = { .tcpip_if = tcpip_if, .ip_protocol = ip_protocol }; - tcpip_api_call(_mdns_pcb_init_api, &msg.call); + tcpip_api_call(mdns_priv_if_init_api, &msg.call); return msg.err; } -esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +esp_err_t mdns_priv_if_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_api_call_t msg = { .tcpip_if = tcpip_if, .ip_protocol = ip_protocol }; - tcpip_api_call(_mdns_pcb_deinit_api, &msg.call); + tcpip_api_call(mdns_priv_if_deinit_api, &msg.call); return msg.err; } -static err_t _mdns_udp_pcb_write_api(struct tcpip_api_call_data *api_call_msg) +static err_t mdns_priv_if_write_api(struct tcpip_api_call_data *api_call_msg) { void *nif = NULL; mdns_api_call_t *msg = (mdns_api_call_t *)api_call_msg; - nif = esp_netif_get_netif_impl(mdns_netif_get_esp_netif(msg->tcpip_if)); - if (!nif || !mdns_is_netif_ready(msg->tcpip_if, msg->ip_protocol) || _pcb_main == NULL) { + nif = esp_netif_get_netif_impl(mdns_priv_get_esp_netif(msg->tcpip_if)); + if (!nif || !mdns_priv_if_ready(msg->tcpip_if, msg->ip_protocol) || _pcb_main == NULL) { pbuf_free(msg->pbt); msg->err = ERR_IF; return ERR_IF; @@ -364,7 +364,7 @@ static err_t _mdns_udp_pcb_write_api(struct tcpip_api_call_data *api_call_msg) return err; } -size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len) +size_t mdns_priv_if_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len) { struct pbuf *pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); if (pbt == NULL) { @@ -392,7 +392,7 @@ size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, c .ip = &ip_add_copy, .port = port }; - tcpip_api_call(_mdns_udp_pcb_write_api, &msg.call); + tcpip_api_call(mdns_priv_if_write_api, &msg.call); if (msg.err) { return 0; @@ -400,17 +400,17 @@ size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, c return len; } -void *_mdns_get_packet_data(mdns_rx_packet_t *packet) +void *mdns_priv_get_packet_data(mdns_rx_packet_t *packet) { return packet->pb->payload; } -size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +size_t mdns_priv_get_packet_len(mdns_rx_packet_t *packet) { return packet->pb->len; } -void _mdns_packet_free(mdns_rx_packet_t *packet) +void mdns_priv_packet_free(mdns_rx_packet_t *packet) { pbuf_free(packet->pb); mdns_mem_free(packet); diff --git a/components/mdns/mdns_networking_socket.c b/components/mdns/mdns_networking_socket.c index 6d967d8025..61124126f9 100644 --- a/components/mdns/mdns_networking_socket.c +++ b/components/mdns/mdns_networking_socket.c @@ -60,7 +60,7 @@ struct pbuf { #define s6_addr32 un.u32_addr #endif // CONFIG_IDF_TARGET_LINUX -static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) +static esp_err_t send_rx_action(mdns_rx_packet_t *packet) { mdns_action_t *action = NULL; @@ -93,29 +93,29 @@ static void delete_socket(int sock) close(sock); } -bool mdns_is_netif_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +bool mdns_priv_if_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { return s_interfaces[tcpip_if].proto & (ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6); } -void *_mdns_get_packet_data(mdns_rx_packet_t *packet) +void *mdns_priv_get_packet_data(mdns_rx_packet_t *packet) { return packet->pb->payload; } -size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +size_t mdns_priv_get_packet_len(mdns_rx_packet_t *packet) { return packet->pb->len; } -void _mdns_packet_free(mdns_rx_packet_t *packet) +void mdns_priv_packet_free(mdns_rx_packet_t *packet) { mdns_mem_free(packet->pb->payload); mdns_mem_free(packet->pb); mdns_mem_free(packet); } -esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +esp_err_t mdns_priv_if_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { s_interfaces[tcpip_if].proto &= ~(ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6); if (s_interfaces[tcpip_if].proto == 0) { @@ -214,7 +214,7 @@ static inline size_t espaddr_to_inet(const esp_ip_addr_t *addr, const uint16_t p return ss_addr_len; } -size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len) +size_t mdns_priv_if_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len) { if (!(s_interfaces[tcpip_if].proto & (ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6))) { return 0; @@ -232,7 +232,7 @@ size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, c ESP_LOGD(TAG, "[sock=%d]: Sending to IP %s port %d", sock, get_string_address(&in_addr), port); ssize_t actual_len = sendto(sock, data, len, 0, (struct sockaddr *)&in_addr, ss_size); if (actual_len < 0) { - ESP_LOGE(TAG, "[sock=%d]: _mdns_udp_pcb_write sendto() has failed\n errno=%d: %s", sock, errno, strerror(errno)); + ESP_LOGE(TAG, "[sock=%d]: mdns_priv_if_write sendto() has failed\n errno=%d: %s", sock, errno, strerror(errno)); } return actual_len; } @@ -347,8 +347,8 @@ void sock_recv_task(void *arg) packet->dest.type = packet->src.type; packet->ip_protocol = packet->src.type == ESP_IPADDR_TYPE_V4 ? MDNS_IP_PROTOCOL_V4 : MDNS_IP_PROTOCOL_V6; - if (_mdns_send_rx_action(packet) != ESP_OK) { - ESP_LOGE(TAG, "_mdns_send_rx_action failed!"); + if (send_rx_action(packet) != ESP_OK) { + ESP_LOGE(TAG, "send_rx_action failed!"); mdns_mem_free(packet->pb->payload); mdns_mem_free(packet->pb); mdns_mem_free(packet); @@ -360,7 +360,7 @@ void sock_recv_task(void *arg) vTaskDelete(NULL); } -static void mdns_networking_init(void) +static void networking_init(void) { if (s_run_sock_recv_task == false) { s_run_sock_recv_task = true; @@ -374,7 +374,7 @@ static bool create_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) return true; } int sock = s_interfaces[tcpip_if].sock; - esp_netif_t *netif = mdns_netif_get_esp_netif(tcpip_if); + esp_netif_t *netif = mdns_priv_get_esp_netif(tcpip_if); if (sock < 0) { sock = create_socket(netif); } @@ -391,14 +391,14 @@ static bool create_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) return true; } -esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +esp_err_t mdns_priv_if_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { - ESP_LOGI(TAG, "_mdns_pcb_init(tcpip_if=%lu, ip_protocol=%lu)", (unsigned long)tcpip_if, (unsigned long)ip_protocol); + ESP_LOGI(TAG, "mdns_priv_if_init(tcpip_if=%lu, ip_protocol=%lu)", (unsigned long)tcpip_if, (unsigned long)ip_protocol); if (!create_pcb(tcpip_if, ip_protocol)) { return ESP_FAIL; } - mdns_networking_init(); + networking_init(); return ESP_OK; } diff --git a/components/mdns/mdns_pcb.c b/components/mdns/mdns_pcb.c index f559c0c43e..a646b2cdb5 100644 --- a/components/mdns/mdns_pcb.c +++ b/components/mdns/mdns_pcb.c @@ -35,7 +35,7 @@ void mdns_priv_pcb_announce(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, { mdns_pcb_t *_pcb = &s_pcbs[tcpip_if][ip_protocol]; size_t i; - if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { + if (mdns_priv_if_ready(tcpip_if, ip_protocol)) { if (PCB_STATE_IS_PROBING(_pcb)) { mdns_priv_init_pcb_probe(tcpip_if, ip_protocol, services, len, include_ip); } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { @@ -76,7 +76,7 @@ void mdns_priv_pcb_announce(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, */ bool mdns_priv_pcb_check_for_duplicates(mdns_if_t tcpip_if) { - mdns_if_t ifaces[MDNS_MAX_INTERFACES] = {tcpip_if, mdns_netif_get_other_interface(tcpip_if) }; + mdns_if_t ifaces[MDNS_MAX_INTERFACES] = {tcpip_if, mdns_priv_netif_get_other_interface(tcpip_if) }; if (ifaces[1] == MDNS_MAX_INTERFACES) { return false; } @@ -94,7 +94,7 @@ bool mdns_priv_pcb_check_for_duplicates(mdns_if_t tcpip_if) static esp_err_t mdns_pcb_deinit_local(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_proto) { - esp_err_t err = _mdns_pcb_deinit(tcpip_if, ip_proto); + esp_err_t err = mdns_priv_if_deinit(tcpip_if, ip_proto); mdns_pcb_t *_pcb = &s_pcbs[tcpip_if][ip_proto]; if (_pcb == NULL || err != ESP_OK) { return err; @@ -140,12 +140,12 @@ static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol */ void mdns_priv_pcb_disable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { - mdns_netif_disable(tcpip_if); + mdns_priv_netif_disable(tcpip_if); - if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { + if (mdns_priv_if_ready(tcpip_if, ip_protocol)) { _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); mdns_pcb_deinit_local(tcpip_if, ip_protocol); - mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); + mdns_if_t other_if = mdns_priv_netif_get_other_interface(tcpip_if); if (other_if != MDNS_MAX_INTERFACES && s_pcbs[other_if][ip_protocol].state == PCB_DUP) { s_pcbs[other_if][ip_protocol].state = PCB_OFF; mdns_priv_pcb_enable(other_if, ip_protocol); @@ -159,8 +159,8 @@ void mdns_priv_pcb_disable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) */ void mdns_priv_pcb_enable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { - if (!mdns_is_netif_ready(tcpip_if, ip_protocol)) { - if (_mdns_pcb_init(tcpip_if, ip_protocol)) { + if (!mdns_priv_if_ready(tcpip_if, ip_protocol)) { + if (mdns_priv_if_init(tcpip_if, ip_protocol)) { s_pcbs[tcpip_if][ip_protocol].failed_probes = 0; return; } @@ -174,14 +174,14 @@ void mdns_priv_pcb_enable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) void mdns_priv_pcb_set_duplicate(mdns_if_t tcpip_if) { uint8_t i; - mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); + mdns_if_t other_if = mdns_priv_netif_get_other_interface(tcpip_if); if (other_if == MDNS_MAX_INTERFACES) { return; // no other interface found } for (i = 0; i < MDNS_IP_PROTOCOL_MAX; i++) { - if (mdns_is_netif_ready(other_if, i)) { + if (mdns_priv_if_ready(other_if, i)) { //stop this interface and mark as dup - if (mdns_is_netif_ready(tcpip_if, i)) { + if (mdns_priv_if_ready(tcpip_if, i)) { _mdns_clear_pcb_tx_queue_head(tcpip_if, i); mdns_pcb_deinit_local(tcpip_if, i); } @@ -299,7 +299,7 @@ void mdns_priv_pcb_deinit(void) bool mdsn_priv_pcb_is_inited(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { - return mdns_is_netif_ready(tcpip_if, ip_protocol) && s_pcbs[tcpip_if][ip_protocol].state > PCB_INIT; + return mdns_priv_if_ready(tcpip_if, ip_protocol) && s_pcbs[tcpip_if][ip_protocol].state > PCB_INIT; } bool mdns_priv_pcb_is_duplicate(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) @@ -426,7 +426,7 @@ void mdns_priv_pcb_send_bye_service(mdns_srv_item_t **services, size_t len, bool for (i = 0; i < MDNS_MAX_INTERFACES; i++) { for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - if (mdns_is_netif_ready(i, j) && s_pcbs[i][j].state == PCB_RUNNING) { + if (mdns_priv_if_ready(i, j) && s_pcbs[i][j].state == PCB_RUNNING) { mdns_send_bye_pcb((mdns_if_t) i, (mdns_ip_protocol_t) j, services, len, include_ip); } } @@ -438,7 +438,7 @@ void mdns_priv_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe uint8_t i, j; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - if (mdns_is_netif_ready(i, j)) { + if (mdns_priv_if_ready(i, j)) { mdns_pcb_t *_pcb = &s_pcbs[i][j]; if (clear_old_probe) { mdns_mem_free(_pcb->probe_services); diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index 023f9de3ae..c2cc3eb8aa 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -217,7 +217,7 @@ mdns_search_once_t *mdns_priv_query_find_from(mdns_search_once_t *s, mdns_name_t } r = s->result; while (r) { - if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { + if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { return s; } r = r->next; @@ -293,7 +293,7 @@ static mdns_tx_packet_t *_mdns_create_search_packet(mdns_search_once_t *search, r = search->result; while (r) { //full record on the same interface is available - if (r->esp_netif != mdns_netif_get_esp_netif(tcpip_if) || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { + if (r->esp_netif != mdns_priv_get_esp_netif(tcpip_if) || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { r = r->next; continue; } @@ -646,7 +646,7 @@ void mdns_priv_query_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t { mdns_result_t *r = search->result; while (r) { - if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { + if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { if (r->txt) { goto free_txt; } @@ -669,7 +669,7 @@ void mdns_priv_query_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t r->txt = txt; r->txt_value_len = txt_value_len; r->txt_count = txt_count; - r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); + r->esp_netif = mdns_priv_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = search->result; @@ -730,7 +730,7 @@ void mdns_priv_query_result_add_ip(mdns_search_once_t *search, const char *hostn || search->type == MDNS_TYPE_ANY) { r = search->result; while (r) { - if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { + if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { _mdns_result_add_ip(r, ip); mdns_priv_query_update_result_ttl(r, ttl); return; @@ -754,7 +754,7 @@ void mdns_priv_query_result_add_ip(mdns_search_once_t *search, const char *hostn a->next = r->addr; r->hostname = mdns_mem_strdup(hostname); r->addr = a; - r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); + r->esp_netif = mdns_priv_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->next = search->result; r->ttl = ttl; @@ -764,7 +764,7 @@ void mdns_priv_query_result_add_ip(mdns_search_once_t *search, const char *hostn } else if (search->type == MDNS_TYPE_PTR || search->type == MDNS_TYPE_SRV) { r = search->result; while (r) { - if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { _mdns_result_add_ip(r, ip); mdns_priv_query_update_result_ttl(r, ttl); break; @@ -782,7 +782,7 @@ void mdns_priv_query_result_add_srv(mdns_search_once_t *search, const char *host { mdns_result_t *r = search->result; while (r) { - if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { mdns_priv_query_update_result_ttl(r, ttl); return; } @@ -807,7 +807,7 @@ void mdns_priv_query_result_add_srv(mdns_search_once_t *search, const char *host r->service_type = mdns_mem_strdup(search->service); r->proto = mdns_mem_strdup(search->proto); r->port = port; - r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); + r->esp_netif = mdns_priv_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = search->result; @@ -825,7 +825,7 @@ mdns_result_t *mdns_priv_query_result_add_ptr(mdns_search_once_t *search, const { mdns_result_t *r = search->result; while (r) { - if (r->esp_netif == mdns_netif_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { + if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { mdns_priv_query_update_result_ttl(r, ttl); return r; } @@ -847,7 +847,7 @@ mdns_result_t *mdns_priv_query_result_add_ptr(mdns_search_once_t *search, const return NULL; } - r->esp_netif = mdns_netif_get_esp_netif(tcpip_if); + r->esp_netif = mdns_priv_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = search->result; diff --git a/components/mdns/mdns_receive.c b/components/mdns/mdns_receive.c index b7bc84e182..2b2c06bfe4 100644 --- a/components/mdns/mdns_receive.c +++ b/components/mdns/mdns_receive.c @@ -347,7 +347,7 @@ static int _mdns_check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) if (!ip->addr) { return 1;//denial! they win } - if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(tcpip_if), &if_ip_info)) { + if (esp_netif_get_ip_info(mdns_priv_get_esp_netif(tcpip_if), &if_ip_info)) { return 1;//they win } int ret = memcmp((uint8_t *)&if_ip_info.ip.addr, (uint8_t *)&ip->addr, sizeof(esp_ip4_addr_t)); @@ -355,11 +355,11 @@ static int _mdns_check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) return -1;//we win } else if (ret < 0) { //is it the other interface? - mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); + mdns_if_t other_if = mdns_priv_netif_get_other_interface(tcpip_if); if (other_if == MDNS_MAX_INTERFACES) { return 1;//AP interface! They win } - if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(other_if), &other_ip_info)) { + if (esp_netif_get_ip_info(mdns_priv_get_esp_netif(other_if), &other_ip_info)) { return 1;//IPv4 not active! They win } if (ip->addr != other_ip_info.ip.addr) { @@ -383,7 +383,7 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) if (mdns_utils_ipv6_address_is_zero(*ip)) { return 1;//denial! they win } - if (esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(tcpip_if), &if_ip6)) { + if (esp_netif_get_ip6_linklocal(mdns_priv_get_esp_netif(tcpip_if), &if_ip6)) { return 1;//they win } int ret = memcmp((uint8_t *)&if_ip6.addr, (uint8_t *)ip->addr, MDNS_UTILS_SIZEOF_IP6_ADDR); @@ -391,11 +391,11 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) return -1;//we win } else if (ret < 0) { //is it the other interface? - mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); + mdns_if_t other_if = mdns_priv_netif_get_other_interface(tcpip_if); if (other_if == MDNS_MAX_INTERFACES) { return 1;//AP interface! They win } - if (esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(other_if), &other_ip6)) { + if (esp_netif_get_ip6_linklocal(mdns_priv_get_esp_netif(other_if), &other_ip6)) { return 1;//IPv6 not active! They win } if (memcmp((uint8_t *)&other_ip6.addr, (uint8_t *)ip->addr, MDNS_UTILS_SIZEOF_IP6_ADDR)) { @@ -609,8 +609,8 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) { static mdns_name_t n; mdns_header_t header; - const uint8_t *data = _mdns_get_packet_data(packet); - size_t len = _mdns_get_packet_len(packet); + const uint8_t *data = mdns_priv_get_packet_data(packet); + size_t len = mdns_priv_get_packet_len(packet); const uint8_t *content = data + MDNS_HEAD_LEN; bool do_not_reply = false; mdns_search_once_t *search_result = NULL; @@ -627,7 +627,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) #ifdef CONFIG_LWIP_IPV4 if (packet->ip_protocol == MDNS_IP_PROTOCOL_V4) { esp_netif_ip_info_t if_ip_info; - if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(packet->tcpip_if), &if_ip_info) == ESP_OK && + if (esp_netif_get_ip_info(mdns_priv_get_esp_netif(packet->tcpip_if), &if_ip_info) == ESP_OK && memcmp(&if_ip_info.ip.addr, &packet->src.u_addr.ip4.addr, sizeof(esp_ip4_addr_t)) == 0) { return; } @@ -636,7 +636,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) #ifdef CONFIG_LWIP_IPV6 if (packet->ip_protocol == MDNS_IP_PROTOCOL_V6) { struct esp_ip6_addr if_ip6; - if (esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(packet->tcpip_if), &if_ip6) == ESP_OK && + if (esp_netif_get_ip6_linklocal(mdns_priv_get_esp_netif(packet->tcpip_if), &if_ip6) == ESP_OK && memcmp(&if_ip6, &packet->src.u_addr.ip6, sizeof(esp_ip6_addr_t)) == 0) { return; } @@ -823,10 +823,10 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) continue; } search_result = mdns_priv_query_find(name, type, packet->tcpip_if, packet->ip_protocol); - browse_result = _mdns_browse_find(name, type, packet->tcpip_if, packet->ip_protocol); + browse_result = mdns_priv_browse_find(name, type, packet->tcpip_if, packet->ip_protocol); if (browse_result) { if (!out_sync_browse) { - // will be freed in function `_mdns_browse_sync` + // will be freed in function `browse_sync` out_sync_browse = (mdns_browse_sync_t *)mdns_mem_malloc(sizeof(mdns_browse_sync_t)); if (!out_sync_browse) { HOOK_MALLOC_FAILED; @@ -932,7 +932,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (search_result && search_result->type == MDNS_TYPE_PTR) { result = search_result->result; while (result) { - if (mdns_netif_get_esp_netif(packet->tcpip_if) == result->esp_netif + if (mdns_priv_get_esp_netif(packet->tcpip_if) == result->esp_netif && packet->ip_protocol == result->ip_protocol && result->instance_name && !strcmp(name->host, result->instance_name)) { break; @@ -959,9 +959,11 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) uint16_t port = mdns_utils_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); if (browse_result) { - mdns_browse_result_add_srv(browse_result, name->host, browse_result_instance, browse_result_service, - browse_result_proto, port, packet->tcpip_if, packet->ip_protocol, ttl, - out_sync_browse); + mdns_priv_browse_result_add_srv(browse_result, name->host, browse_result_instance, + browse_result_service, + browse_result_proto, port, packet->tcpip_if, packet->ip_protocol, + ttl, + out_sync_browse); } if (search_result) { if (search_result->type == MDNS_TYPE_PTR) { @@ -1036,16 +1038,17 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) mdns_result_t *result = NULL; if (browse_result) { _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); - mdns_browse_result_add_txt(browse_result, browse_result_instance, browse_result_service, - browse_result_proto, - txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, - ttl, out_sync_browse); + mdns_priv_browse_result_add_txt(browse_result, browse_result_instance, browse_result_service, + browse_result_proto, + txt, txt_value_len, txt_count, packet->tcpip_if, + packet->ip_protocol, + ttl, out_sync_browse); } if (search_result) { if (search_result->type == MDNS_TYPE_PTR) { result = search_result->result; while (result) { - if (mdns_netif_get_esp_netif(packet->tcpip_if) == result->esp_netif + if (mdns_priv_get_esp_netif(packet->tcpip_if) == result->esp_netif && packet->ip_protocol == result->ip_protocol && result->instance_name && !strcmp(name->host, result->instance_name)) { break; @@ -1108,8 +1111,9 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) ip6.type = ESP_IPADDR_TYPE_V6; memcpy(ip6.u_addr.ip6.addr, data_ptr, MDNS_ANSWER_AAAA_SIZE); if (browse_result) { - mdns_browse_result_add_ip(browse_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, - ttl, out_sync_browse); + mdns_priv_browse_result_add_ip(browse_result, name->host, &ip6, packet->tcpip_if, + packet->ip_protocol, + ttl, out_sync_browse); } if (search_result) { //check for more applicable searches (PTR & A/AAAA at the same time) @@ -1167,8 +1171,9 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) ip.type = ESP_IPADDR_TYPE_V4; memcpy(&(ip.u_addr.ip4.addr), data_ptr, 4); if (browse_result) { - mdns_browse_result_add_ip(browse_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, - ttl, out_sync_browse); + mdns_priv_browse_result_add_ip(browse_result, name->host, &ip, packet->tcpip_if, + packet->ip_protocol, + ttl, out_sync_browse); } if (search_result) { //check for more applicable searches (PTR & A/AAAA at the same time) @@ -1290,8 +1295,8 @@ void mdns_priv_receive_action(mdns_action_t *action, mdns_action_subtype_t type) } if (type == ACTION_RUN) { mdns_parse_packet(action->data.rx_handle.packet); - _mdns_packet_free(action->data.rx_handle.packet); + mdns_priv_packet_free(action->data.rx_handle.packet); } else if (type == ACTION_CLEANUP) { - _mdns_packet_free(action->data.rx_handle.packet); + mdns_priv_packet_free(action->data.rx_handle.packet); } } diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index f99033d2be..cbdfdd7024 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -1259,11 +1259,11 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an else if (answer->type == MDNS_TYPE_A) { if (answer->host == priv_get_self_host()) { esp_netif_ip_info_t if_ip_info; - if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && !mdns_priv_pcb_is_duplicate(tcpip_if, - MDNS_IP_PROTOCOL_V4)) { + if (!mdns_priv_if_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && !mdns_priv_pcb_is_duplicate(tcpip_if, + MDNS_IP_PROTOCOL_V4)) { return 0; } - if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(tcpip_if), &if_ip_info)) { + if (esp_netif_get_ip_info(mdns_priv_get_esp_netif(tcpip_if), &if_ip_info)) { return 0; } if (_mdns_append_a_record(packet, index, mdns_priv_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { @@ -1272,8 +1272,8 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an if (!mdns_priv_pcb_check_for_duplicates(tcpip_if)) { return 1; } - mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); - if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(other_if), &if_ip_info)) { + mdns_if_t other_if = mdns_priv_netif_get_other_interface(tcpip_if); + if (esp_netif_get_ip_info(mdns_priv_get_esp_netif(other_if), &if_ip_info)) { return 1; } if (_mdns_append_a_record(packet, index, mdns_priv_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { @@ -1290,11 +1290,11 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an if (answer->host == priv_get_self_host()) { struct esp_ip6_addr if_ip6s[NETIF_IPV6_MAX_NUMS]; uint8_t count = 0; - if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && !mdns_priv_pcb_is_duplicate(tcpip_if, - MDNS_IP_PROTOCOL_V6)) { + if (!mdns_priv_if_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && !mdns_priv_pcb_is_duplicate(tcpip_if, + MDNS_IP_PROTOCOL_V6)) { return 0; } - count = esp_netif_get_all_ip6(mdns_netif_get_esp_netif(tcpip_if), if_ip6s); + count = esp_netif_get_all_ip6(mdns_priv_get_esp_netif(tcpip_if), if_ip6s); assert(count <= NETIF_IPV6_MAX_NUMS); for (int i = 0; i < count; i++) { if (mdns_utils_ipv6_address_is_zero(if_ip6s[i])) { @@ -1309,9 +1309,9 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an return count; } - mdns_if_t other_if = mdns_netif_get_other_interface(tcpip_if); + mdns_if_t other_if = mdns_priv_netif_get_other_interface(tcpip_if); struct esp_ip6_addr other_ip6; - if (esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(other_if), &other_ip6)) { + if (esp_netif_get_ip6_linklocal(mdns_priv_get_esp_netif(other_if), &other_ip6)) { return count; } if (_mdns_append_aaaa_record(packet, index, mdns_priv_get_global_hostname(), (uint8_t *)other_ip6.addr, @@ -1381,7 +1381,7 @@ void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p) DBG_TX_PACKET(p, packet, index); - _mdns_udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); + mdns_priv_if_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); } @@ -1541,7 +1541,7 @@ void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, uint8_t i, j; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - if (mdns_is_netif_ready(i, j)) { + if (mdns_priv_if_ready(i, j)) { mdns_tx_packet_t *packet = _mdns_alloc_packet_default((mdns_if_t)i, (mdns_ip_protocol_t)j); if (packet == NULL) { return; @@ -1575,7 +1575,7 @@ void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, } _mdns_set_u16(pkt, MDNS_HEAD_ANSWERS_OFFSET, count); - _mdns_udp_pcb_write(packet->tcpip_if, packet->ip_protocol, &packet->dst, packet->port, pkt, index); + mdns_priv_if_write(packet->tcpip_if, packet->ip_protocol, &packet->dst, packet->port, pkt, index); _mdns_free_tx_packet(packet); } @@ -1788,7 +1788,7 @@ void _mdns_remove_scheduled_service_packets(mdns_service_t *service) _mdns_dealloc_scheduled_service_answers(&(q->additional), service); _mdns_dealloc_scheduled_service_answers(&(q->servers), service); - if (mdns_is_netif_ready(q->tcpip_if, q->ip_protocol)) { + if (mdns_priv_if_ready(q->tcpip_if, q->ip_protocol)) { bool should_remove_questions = false; mdns_priv_pcb_check_probing_services(q->tcpip_if, q->ip_protocol, service, had_answers && q->answers == NULL, &should_remove_questions); diff --git a/components/mdns/mdns_service.c b/components/mdns/mdns_service.c index 66471573ab..bd2b8773d5 100644 --- a/components/mdns/mdns_service.c +++ b/components/mdns/mdns_service.c @@ -72,7 +72,7 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) #ifdef CONFIG_LWIP_IPV4 if (action & MDNS_EVENT_IP4_REVERSE_LOOKUP) { esp_netif_ip_info_t if_ip_info; - if (esp_netif_get_ip_info(mdns_netif_get_esp_netif(mdns_if), &if_ip_info) == ESP_OK) { + if (esp_netif_get_ip_info(mdns_priv_get_esp_netif(mdns_if), &if_ip_info) == ESP_OK) { esp_ip4_addr_t *ip = &if_ip_info.ip; char *reverse_query_name = NULL; if (asprintf(&reverse_query_name, "%d.%d.%d.%d.in-addr", @@ -87,7 +87,7 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) #ifdef CONFIG_LWIP_IPV6 if (action & MDNS_EVENT_IP6_REVERSE_LOOKUP) { esp_ip6_addr_t addr6; - if (!esp_netif_get_ip6_linklocal(mdns_netif_get_esp_netif(mdns_if), &addr6) && !mdns_utils_ipv6_address_is_zero(addr6)) { + if (!esp_netif_get_ip6_linklocal(mdns_priv_get_esp_netif(mdns_if), &addr6) && !mdns_utils_ipv6_address_is_zero(addr6)) { uint8_t *paddr = (uint8_t *)&addr6.addr; const char sub[] = "ip6"; const size_t query_name_size = 4 * sizeof(addr6.addr) /* (2 nibbles + 2 dots)/per byte of IP address */ + sizeof(sub); @@ -128,7 +128,7 @@ static void _mdns_free_action(mdns_action_t *action) case ACTION_BROWSE_ADD: case ACTION_BROWSE_END: case ACTION_BROWSE_SYNC: - mdns_browse_action(action, ACTION_CLEANUP); + mdns_priv_browse_action(action, ACTION_CLEANUP); break; case ACTION_TX_HANDLE: mdns_send_action(action, ACTION_CLEANUP); @@ -166,7 +166,7 @@ static void _mdns_execute_action(mdns_action_t *action) case ACTION_BROWSE_ADD: case ACTION_BROWSE_SYNC: case ACTION_BROWSE_END: - mdns_browse_action(action, ACTION_RUN); + mdns_priv_browse_action(action, ACTION_RUN); break; case ACTION_TX_HANDLE: @@ -358,7 +358,7 @@ esp_err_t mdns_init(void) goto free_responder; } - if (mdns_netif_init() != ESP_OK) { + if (mdns_priv_netif_init() != ESP_OK) { err = ESP_FAIL; goto free_queue; } @@ -372,7 +372,7 @@ esp_err_t mdns_init(void) return ESP_OK; free_all_and_disable_pcbs: - mdns_netif_deinit(); + mdns_priv_netif_deinit(); free_queue: vQueueDelete(s_action_queue); free_responder: @@ -387,7 +387,7 @@ void mdns_free(void) } // Unregister handlers before destroying the mdns internals to avoid receiving async events while deinit - mdns_netif_unregister_predefined_handlers(); + mdns_priv_netif_unregister_predefined_handlers(); mdns_service_remove_all(); mdns_priv_free_delegated_hostnames(); @@ -404,7 +404,7 @@ void mdns_free(void) } _mdns_clear_tx_queue_head(); mdns_priv_query_free(); - mdns_browse_free(); + mdns_priv_browse_free(); mdns_priv_responder_free(); } diff --git a/components/mdns/private_include/mdns_browser.h b/components/mdns/private_include/mdns_browser.h index d76ab4e409..3bf5ef2313 100644 --- a/components/mdns/private_include/mdns_browser.h +++ b/components/mdns/private_include/mdns_browser.h @@ -17,7 +17,7 @@ extern "C" { * * @note Called from mdns_free() */ -void mdns_browse_free(void); +void mdns_priv_browse_free(void); /** * @brief Looks for the name/type in active browse items @@ -26,46 +26,45 @@ void mdns_browse_free(void); * * @return browse results */ -mdns_browse_t *_mdns_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +mdns_browse_t *mdns_priv_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); /** * @brief Send out all browse queries * * @note Called from the network events (mdns_netif.c) - * @note Calls (indirectly) _mdns_search_send_pcb() from mdns_querier.c, which sends out the query + * @note Calls (indirectly) search-send from mdns_querier.c, which sends out the query */ -void mdns_browse_send_all(mdns_if_t mdns_if); +void mdns_priv_browse_send_all(mdns_if_t mdns_if); /** * @brief Perform action from mdns service queue * * @note Called from the _mdns_service_task() in mdns.c */ -void mdns_browse_action(mdns_action_t *action, mdns_action_subtype_t type); - +void mdns_priv_browse_action(mdns_action_t *action, mdns_action_subtype_t type); /** * @brief Add a TXT record to the browse result * * @note Called from the packet parser (mdns_receive.c) */ -void mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, - mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, - uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +void mdns_priv_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, + mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl, mdns_browse_sync_t *out_sync_browse); /** * @brief Add an IP record to the browse result * * @note Called from the packet parser (mdns_receive.c) */ -void mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, - mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +void mdns_priv_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); /** * @brief Add a SRV record to the browse result * * @note Called from the packet parser (mdns_receive.c) */ -void mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, - uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +void mdns_priv_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, + uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_netif.h b/components/mdns/private_include/mdns_netif.h index 990a2b591c..42aa5f1ff0 100644 --- a/components/mdns/private_include/mdns_netif.h +++ b/components/mdns/private_include/mdns_netif.h @@ -17,14 +17,14 @@ extern "C" { * * @note Called from mdns_init() in mdns.c */ -esp_err_t mdns_netif_init(void); +esp_err_t mdns_priv_netif_init(void); /** * @brief Deinitialize the mDNS network interfaces * * @note Called from mdns_init() in mdns.c */ -esp_err_t mdns_netif_deinit(void); +esp_err_t mdns_priv_netif_deinit(void); /** * @brief Unregister predefined (default) network interfaces @@ -32,21 +32,21 @@ esp_err_t mdns_netif_deinit(void); * @note Called from mdns_free() in mdns.c * */ -void mdns_netif_unregister_predefined_handlers(void); +void mdns_priv_netif_unregister_predefined_handlers(void); /** * @brief Clean the internal netif for the particular interface * * @note Called from mdns_responder on disabling pcbs */ -void mdns_netif_disable(mdns_if_t tcpip_if); +void mdns_priv_netif_disable(mdns_if_t tcpip_if); /** * @brief Returns potentially duplicated interface * * @note Called from multiple places where Rx and Tx packets are processed */ -mdns_if_t mdns_netif_get_other_interface(mdns_if_t tcpip_if); +mdns_if_t mdns_priv_netif_get_other_interface(mdns_if_t tcpip_if); /** * @brief Gets the actual esp_netif pointer from the internal network interface list @@ -60,7 +60,8 @@ mdns_if_t mdns_netif_get_other_interface(mdns_if_t tcpip_if); * @param tcpip_if Ordinal number of the interface * @return Pointer ot the esp_netif object if the interface is available, NULL otherwise */ -esp_netif_t *mdns_netif_get_esp_netif(mdns_if_t tcpip_if); +esp_netif_t *mdns_priv_get_esp_netif(mdns_if_t tcpip_if); + #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h index a00266ef5c..9b5e396bc0 100644 --- a/components/mdns/private_include/mdns_networking.h +++ b/components/mdns/private_include/mdns_networking.h @@ -3,8 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ESP_MDNS_NETWORKING_H_ -#define ESP_MDNS_NETWORKING_H_ +#pragma once /* * MDNS Server Networking -- private include @@ -13,20 +12,24 @@ #include "mdns.h" #include "mdns_private.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * @brief Check if the netif on the selected interfacce and protocol is ready */ -bool mdns_is_netif_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +bool mdns_priv_if_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); /** * @brief Start PCB */ -esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +esp_err_t mdns_priv_if_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); /** * @brief Stop PCB */ -esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +esp_err_t mdns_priv_if_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); /** * @brief send packet over UDP @@ -37,21 +40,23 @@ esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); * * @return length of sent packet or 0 on error */ -size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len); +size_t mdns_priv_if_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len); /** * @brief Gets data pointer to the mDNS packet */ -void *_mdns_get_packet_data(mdns_rx_packet_t *packet); +void *mdns_priv_get_packet_data(mdns_rx_packet_t *packet); /** * @brief Gets data length of c */ -size_t _mdns_get_packet_len(mdns_rx_packet_t *packet); +size_t mdns_priv_get_packet_len(mdns_rx_packet_t *packet); /** * @brief Free the mDNS packet */ -void _mdns_packet_free(mdns_rx_packet_t *packet); +void mdns_priv_packet_free(mdns_rx_packet_t *packet); -#endif /* ESP_MDNS_NETWORKING_H_ */ +#ifdef __cplusplus +} +#endif diff --git a/components/mdns/tests/host_unit_test/stubs/mdns_engine.c b/components/mdns/tests/host_unit_test/stubs/mdns_engine.c index 74251281d7..996c89356c 100644 --- a/components/mdns/tests/host_unit_test/stubs/mdns_engine.c +++ b/components/mdns/tests/host_unit_test/stubs/mdns_engine.c @@ -25,7 +25,7 @@ static void execute_action(mdns_action_t *action) case ACTION_BROWSE_ADD: case ACTION_BROWSE_SYNC: case ACTION_BROWSE_END: - mdns_browse_action(action, ACTION_RUN); + mdns_priv_browse_action(action, ACTION_RUN); break; case ACTION_TX_HANDLE: diff --git a/components/mdns/tests/host_unit_test/stubs/mdns_networking.c b/components/mdns/tests/host_unit_test/stubs/mdns_networking.c index 2258aa9507..9bd385d494 100644 --- a/components/mdns/tests/host_unit_test/stubs/mdns_networking.c +++ b/components/mdns/tests/host_unit_test/stubs/mdns_networking.c @@ -11,37 +11,37 @@ struct pbuf { size_t len; }; -bool mdns_is_netif_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +bool mdns_priv_if_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { return true; // Default to ready for testing } -esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +esp_err_t mdns_priv_if_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { return ESP_OK; } -esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +esp_err_t mdns_priv_if_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { return ESP_OK; } -size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len) +size_t mdns_priv_if_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len) { return len; // Return the input length as if all data was sent successfully } -void *_mdns_get_packet_data(mdns_rx_packet_t *packet) +void *mdns_priv_get_packet_data(mdns_rx_packet_t *packet) { return packet->pb->payload; } -size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +size_t mdns_priv_get_packet_len(mdns_rx_packet_t *packet) { return packet->pb->len; } -void _mdns_packet_free(mdns_rx_packet_t *packet) +void mdns_priv_packet_free(mdns_rx_packet_t *packet) { mdns_mem_free(packet->pb->payload); mdns_mem_free(packet->pb); diff --git a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h index 70a2037ffa..a4a5b0be39 100644 --- a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h @@ -58,8 +58,8 @@ #define vTaskDelete(a) free(NULL) #define xSemaphoreGive(s) #define xQueueCreateMutex(s) -#define _mdns_pcb_init(a,b) true -#define _mdns_pcb_deinit(a,b) true +#define mdns_priv_if_init(a,b) true +#define mdns_priv_if_deinit(a,b) true #define xSemaphoreCreateMutex() malloc(1) #define xSemaphoreCreateBinary() malloc(1) #define vSemaphoreDelete(s) free(s) @@ -72,7 +72,7 @@ #define ESP_TASK_PRIO_MAX 25 #define ESP_TASKD_EVENT_PRIO 5 -#define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len +#define mdns_priv_if_write(tcpip_if, ip_protocol, ip, port, data, len) len #define TaskHandle_t TaskHandle_t diff --git a/components/mdns/tests/test_afl_fuzz_host/mdns_mock.h b/components/mdns/tests/test_afl_fuzz_host/mdns_mock.h index d37da92968..20351f4f0b 100644 --- a/components/mdns/tests/test_afl_fuzz_host/mdns_mock.h +++ b/components/mdns/tests/test_afl_fuzz_host/mdns_mock.h @@ -9,23 +9,23 @@ #include "mdns_private.h" -static inline void *_mdns_get_packet_data(mdns_rx_packet_t *packet) +static inline void *mdns_priv_get_packet_data(mdns_rx_packet_t *packet) { return packet->pb->payload; } -static inline size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +static inline size_t mdns_priv_get_packet_len(mdns_rx_packet_t *packet) { return packet->pb->len; } -static inline void _mdns_packet_free(mdns_rx_packet_t *packet) +static inline void mdns_priv_packet_free(mdns_rx_packet_t *packet) { free(packet->pb); free(packet); } -static inline bool mdns_is_netif_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static inline bool mdns_priv_if_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { return true; } From 7330f780d06d254e2eb67bb7c3f4941a2cbd7423 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 1 Apr 2025 16:40:25 +0200 Subject: [PATCH 19/27] fix(mdns): Cleanup querier and pcb --- components/mdns/mdns_browser.c | 2 +- components/mdns/mdns_networking_lwip.c | 86 ++-- components/mdns/mdns_pcb.c | 69 +-- components/mdns/mdns_querier.c | 466 +++++++++--------- components/mdns/private_include/mdns_pcb.h | 1 - .../mdns/private_include/mdns_private.h | 13 +- .../mdns/private_include/mdns_querier.h | 2 +- 7 files changed, 313 insertions(+), 326 deletions(-) diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index ca3c0c1421..e432b225be 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -90,7 +90,7 @@ static void browse_send(mdns_browse_t *browse, mdns_if_t interface) search.next = NULL; for (uint8_t protocol_idx = 0; protocol_idx < MDNS_IP_PROTOCOL_MAX; protocol_idx++) { - _mdns_search_send_pcb(&search, interface, (mdns_ip_protocol_t)protocol_idx); + mdns_priv_query_send(&search, interface, (mdns_ip_protocol_t) protocol_idx); } } diff --git a/components/mdns/mdns_networking_lwip.c b/components/mdns/mdns_networking_lwip.c index e320b7c037..a3a0bf34ef 100644 --- a/components/mdns/mdns_networking_lwip.c +++ b/components/mdns/mdns_networking_lwip.c @@ -38,13 +38,13 @@ typedef struct interfaces { static interfaces_t s_interfaces[MDNS_MAX_INTERFACES]; -static struct udp_pcb *_pcb_main = NULL; +static struct udp_pcb *s_pcb_main = NULL; static const char *TAG = "mdns_networking"; -static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport); +static void receive(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport); -static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) +static esp_err_t send_rx_action(mdns_rx_packet_t *packet) { mdns_action_t *action = NULL; @@ -66,44 +66,44 @@ static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) /** * @brief Low level UDP PCB Initialize */ -static esp_err_t _udp_pcb_main_init(void) +static esp_err_t pcb_init(void) { - if (_pcb_main) { + if (s_pcb_main) { return ESP_OK; } - _pcb_main = udp_new(); - if (!_pcb_main) { + s_pcb_main = udp_new(); + if (!s_pcb_main) { return ESP_ERR_NO_MEM; } - if (udp_bind(_pcb_main, IP_ANY_TYPE, MDNS_SERVICE_PORT) != 0) { - udp_remove(_pcb_main); - _pcb_main = NULL; + if (udp_bind(s_pcb_main, IP_ANY_TYPE, MDNS_SERVICE_PORT) != 0) { + udp_remove(s_pcb_main); + s_pcb_main = NULL; return ESP_ERR_INVALID_STATE; } - _pcb_main->mcast_ttl = 255; - _pcb_main->remote_port = MDNS_SERVICE_PORT; - ip_addr_copy(_pcb_main->remote_ip, *(IP_ANY_TYPE)); - udp_recv(_pcb_main, &_udp_recv, NULL); + s_pcb_main->mcast_ttl = 255; + s_pcb_main->remote_port = MDNS_SERVICE_PORT; + ip_addr_copy(s_pcb_main->remote_ip, *(IP_ANY_TYPE)); + udp_recv(s_pcb_main, receive, NULL); return ESP_OK; } /** * @brief Low level UDP PCB Free */ -static void _udp_pcb_main_deinit(void) +static void pcb_deinit(void) { - if (_pcb_main) { - udp_recv(_pcb_main, NULL, NULL); - udp_disconnect(_pcb_main); - udp_remove(_pcb_main); - _pcb_main = NULL; + if (s_pcb_main) { + udp_recv(s_pcb_main, NULL, NULL); + udp_disconnect(s_pcb_main); + udp_remove(s_pcb_main); + s_pcb_main = NULL; } } /** * @brief Low level UDP Multicast membership control */ -static esp_err_t _udp_join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protocol, bool join) +static esp_err_t join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protocol, bool join) { struct netif *netif = NULL; esp_netif_t *tcpip_if = mdns_priv_get_esp_netif(if_inx); @@ -154,7 +154,7 @@ static esp_err_t _udp_join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protoco * @brief the receive callback of the raw udp api. Packets are received here * */ -static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport) +static void receive(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport) { uint8_t i; @@ -223,7 +223,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip } } - if (!found || _mdns_send_rx_action(packet) != ESP_OK) { + if (!found || send_rx_action(packet) != ESP_OK) { pbuf_free(this_pb); mdns_mem_free(packet); } @@ -240,7 +240,7 @@ bool mdns_priv_if_ready(mdns_if_t netif, mdns_ip_protocol_t ip_proto) /** * @brief Check if any of the interfaces is up */ -static bool _udp_pcb_is_in_use(void) +static bool is_any_pcb_in_use(void) { int i, p; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { @@ -256,14 +256,14 @@ static bool _udp_pcb_is_in_use(void) /** * @brief Stop PCB Main code */ -static void _udp_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void pcb_if_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { s_interfaces[tcpip_if].proto &= ~(ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6); if (s_interfaces[tcpip_if].proto == 0) { s_interfaces[tcpip_if].ready = false; - _udp_join_group(tcpip_if, ip_protocol, false); - if (!_udp_pcb_is_in_use()) { - _udp_pcb_main_deinit(); + join_group(tcpip_if, ip_protocol, false); + if (!is_any_pcb_in_use()) { + pcb_deinit(); } } } @@ -271,18 +271,18 @@ static void _udp_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) /** * @brief Start PCB Main code */ -static esp_err_t _udp_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static esp_err_t pcb_if_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { if (mdns_priv_if_ready(tcpip_if, ip_protocol)) { return ESP_ERR_INVALID_STATE; } - esp_err_t err = _udp_join_group(tcpip_if, ip_protocol, true); + esp_err_t err = join_group(tcpip_if, ip_protocol, true); if (err) { return err; } - err = _udp_pcb_main_init(); + err = pcb_init(); if (err) { return err; } @@ -305,20 +305,20 @@ typedef struct { /** * @brief Start PCB from LwIP thread */ -static err_t mdns_priv_if_init_api(struct tcpip_api_call_data *api_call_msg) +static err_t pcb_if_init_lwip(struct tcpip_api_call_data *api_call_msg) { mdns_api_call_t *msg = (mdns_api_call_t *)api_call_msg; - msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol) == ESP_OK ? ERR_OK : ERR_IF; - return msg->err; + msg->err = pcb_if_init(msg->tcpip_if, msg->ip_protocol); + return msg->err == ESP_OK ? ERR_OK : ERR_IF; } /** * @brief Stop PCB from LwIP thread */ -static err_t mdns_priv_if_deinit_api(struct tcpip_api_call_data *api_call_msg) +static err_t pcb_if_deinit_lwip(struct tcpip_api_call_data *api_call_msg) { mdns_api_call_t *msg = (mdns_api_call_t *)api_call_msg; - _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol); + pcb_if_deinit(msg->tcpip_if, msg->ip_protocol); msg->err = ESP_OK; return ESP_OK; } @@ -334,7 +334,7 @@ esp_err_t mdns_priv_if_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) .tcpip_if = tcpip_if, .ip_protocol = ip_protocol }; - tcpip_api_call(mdns_priv_if_init_api, &msg.call); + tcpip_api_call(pcb_if_init_lwip, &msg.call); return msg.err; } @@ -344,23 +344,23 @@ esp_err_t mdns_priv_if_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol .tcpip_if = tcpip_if, .ip_protocol = ip_protocol }; - tcpip_api_call(mdns_priv_if_deinit_api, &msg.call); + tcpip_api_call(pcb_if_deinit_lwip, &msg.call); return msg.err; } -static err_t mdns_priv_if_write_api(struct tcpip_api_call_data *api_call_msg) +static err_t write_if_lwip(struct tcpip_api_call_data *api_call_msg) { void *nif = NULL; mdns_api_call_t *msg = (mdns_api_call_t *)api_call_msg; nif = esp_netif_get_netif_impl(mdns_priv_get_esp_netif(msg->tcpip_if)); - if (!nif || !mdns_priv_if_ready(msg->tcpip_if, msg->ip_protocol) || _pcb_main == NULL) { + if (!nif || !mdns_priv_if_ready(msg->tcpip_if, msg->ip_protocol) || s_pcb_main == NULL) { pbuf_free(msg->pbt); msg->err = ERR_IF; return ERR_IF; } - esp_err_t err = udp_sendto_if(_pcb_main, msg->pbt, msg->ip, msg->port, (struct netif *)nif); + err_t err = udp_sendto_if(s_pcb_main, msg->pbt, msg->ip, msg->port, (struct netif *)nif); pbuf_free(msg->pbt); - msg->err = err; + msg->err = err == ERR_OK ? ESP_OK : ESP_FAIL; return err; } @@ -392,7 +392,7 @@ size_t mdns_priv_if_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, co .ip = &ip_add_copy, .port = port }; - tcpip_api_call(mdns_priv_if_write_api, &msg.call); + tcpip_api_call(write_if_lwip, &msg.call); if (msg.err) { return 0; diff --git a/components/mdns/mdns_pcb.c b/components/mdns/mdns_pcb.c index a646b2cdb5..affda39064 100644 --- a/components/mdns/mdns_pcb.c +++ b/components/mdns/mdns_pcb.c @@ -15,7 +15,15 @@ #include "esp_random.h" #include "mdns_responder.h" -static const char *TAG = "mdns_responder"; +#define PCB_STATE_IS_PROBING(s) (s->state > PCB_OFF && s->state < PCB_ANNOUNCE_1) +#define PCB_STATE_IS_ANNOUNCING(s) (s->state > PCB_PROBE_3 && s->state < PCB_RUNNING) + +typedef enum { + PCB_OFF, PCB_DUP, PCB_INIT, + PCB_PROBE_1, PCB_PROBE_2, PCB_PROBE_3, + PCB_ANNOUNCE_1, PCB_ANNOUNCE_2, PCB_ANNOUNCE_3, + PCB_RUNNING +} mdns_pcb_state_t; typedef struct { mdns_pcb_state_t state; @@ -26,6 +34,7 @@ typedef struct { uint16_t failed_probes; } mdns_pcb_t; +static const char *TAG = "mdns_pcb"; static mdns_pcb_t s_pcbs[MDNS_MAX_INTERFACES][MDNS_IP_PROTOCOL_MAX]; /** @@ -92,27 +101,27 @@ bool mdns_priv_pcb_check_for_duplicates(mdns_if_t tcpip_if) return false; } -static esp_err_t mdns_pcb_deinit_local(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_proto) +static esp_err_t deinit_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_proto) { esp_err_t err = mdns_priv_if_deinit(tcpip_if, ip_proto); - mdns_pcb_t *_pcb = &s_pcbs[tcpip_if][ip_proto]; - if (_pcb == NULL || err != ESP_OK) { + mdns_pcb_t *pcb = &s_pcbs[tcpip_if][ip_proto]; + if (pcb == NULL || err != ESP_OK) { return err; } - mdns_mem_free(_pcb->probe_services); - _pcb->state = PCB_OFF; - _pcb->probe_ip = false; - _pcb->probe_services = NULL; - _pcb->probe_services_len = 0; - _pcb->probe_running = false; - _pcb->failed_probes = 0; + mdns_mem_free(pcb->probe_services); + pcb->state = PCB_OFF; + pcb->probe_ip = false; + pcb->probe_services = NULL; + pcb->probe_services_len = 0; + pcb->probe_running = false; + pcb->failed_probes = 0; return ESP_OK; } /** * @brief Restart the responder on particular PCB */ -static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { size_t srv_count = 0; mdns_srv_item_t *a = mdns_priv_get_services(); @@ -144,7 +153,7 @@ void mdns_priv_pcb_disable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) if (mdns_priv_if_ready(tcpip_if, ip_protocol)) { _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); - mdns_pcb_deinit_local(tcpip_if, ip_protocol); + deinit_pcb(tcpip_if, ip_protocol); mdns_if_t other_if = mdns_priv_netif_get_other_interface(tcpip_if); if (other_if != MDNS_MAX_INTERFACES && s_pcbs[other_if][ip_protocol].state == PCB_DUP) { s_pcbs[other_if][ip_protocol].state = PCB_OFF; @@ -165,7 +174,7 @@ void mdns_priv_pcb_enable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) return; } } - _mdns_restart_pcb(tcpip_if, ip_protocol); + restart_pcb(tcpip_if, ip_protocol); } /** @@ -183,10 +192,9 @@ void mdns_priv_pcb_set_duplicate(mdns_if_t tcpip_if) //stop this interface and mark as dup if (mdns_priv_if_ready(tcpip_if, i)) { _mdns_clear_pcb_tx_queue_head(tcpip_if, i); - mdns_pcb_deinit_local(tcpip_if, i); + deinit_pcb(tcpip_if, i); } s_pcbs[tcpip_if][i].state = PCB_DUP; -// _mdns_server->interfaces[tcpip_if].pcbs[i].state = PCB_DUP; mdns_priv_pcb_announce(other_if, i, NULL, 0, true); } } @@ -292,7 +300,7 @@ void mdns_priv_pcb_deinit(void) { for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { for (int j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - mdns_pcb_deinit_local(i, j); + deinit_pcb(i, j); } } } @@ -322,13 +330,10 @@ void mdns_priv_pcb_set_probe_failed(mdns_rx_packet_t *packet) s_pcbs[packet->tcpip_if][packet->ip_protocol].failed_probes++; } - - - /** * @brief Send probe for additional services on particular PCB */ -static void _mdns_init_pcb_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) +static void init_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) { mdns_pcb_t *pcb = &s_pcbs[tcpip_if][ip_protocol]; size_t services_final_len = len; @@ -336,21 +341,21 @@ static void _mdns_init_pcb_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protoco if (PCB_STATE_IS_PROBING(pcb)) { services_final_len += pcb->probe_services_len; } - mdns_srv_item_t **_services = NULL; + mdns_srv_item_t **s = NULL; if (services_final_len) { - _services = (mdns_srv_item_t **)mdns_mem_malloc(sizeof(mdns_srv_item_t *) * services_final_len); - if (!_services) { + s = (mdns_srv_item_t **)mdns_mem_malloc(sizeof(mdns_srv_item_t *) * services_final_len); + if (!s) { HOOK_MALLOC_FAILED; return; } size_t i; for (i = 0; i < len; i++) { - _services[i] = services[i]; + s[i] = services[i]; } if (pcb->probe_services) { for (i = 0; i < pcb->probe_services_len; i++) { - _services[len + i] = pcb->probe_services[i]; + s[len + i] = pcb->probe_services[i]; } mdns_mem_free(pcb->probe_services); } @@ -363,14 +368,14 @@ static void _mdns_init_pcb_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protoco pcb->probe_services_len = 0; pcb->probe_running = false; - mdns_tx_packet_t *packet = _mdns_create_probe_packet(tcpip_if, ip_protocol, _services, services_final_len, true, probe_ip); + mdns_tx_packet_t *packet = _mdns_create_probe_packet(tcpip_if, ip_protocol, s, services_final_len, true, probe_ip); if (!packet) { - mdns_mem_free(_services); + mdns_mem_free(s); return; } pcb->probe_ip = probe_ip; - pcb->probe_services = _services; + pcb->probe_services = s; pcb->probe_services_len = services_final_len; pcb->probe_running = true; mdns_send_schedule_tx_packet(packet, ((pcb->failed_probes > 5) ? 1000 : 120) + (esp_random() & 0x7F)); @@ -406,11 +411,11 @@ void mdns_priv_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol } } // init probing for newly added services - _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, - new_probe_service_len ? new_probe_services : NULL, new_probe_service_len, probe_ip); + init_probe_new_service(tcpip_if, ip_protocol, + new_probe_service_len ? new_probe_services : NULL, new_probe_service_len, probe_ip); } else { // not probing, so init for all services - _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, services, len, probe_ip); + init_probe_new_service(tcpip_if, ip_protocol, services, len, probe_ip); } } diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index c2cc3eb8aa..c6943c3e85 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -15,11 +15,10 @@ #include "mdns_responder.h" static const char *TAG = "mdns_querier"; - static mdns_search_once_t *s_search_once; -static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); -static void _mdns_search_free(mdns_search_once_t *search); +static esp_err_t send_search_action(mdns_action_type_t type, mdns_search_once_t *search); +static void search_free(mdns_search_once_t *search); void mdns_priv_query_results_free(mdns_result_t *results) { @@ -55,7 +54,7 @@ void mdns_priv_query_results_free(mdns_result_t *results) /** * @brief Mark search as finished and remove it from search chain */ -static void _mdns_search_finish(mdns_search_once_t *search) +static void search_finish(mdns_search_once_t *search) { search->state = SEARCH_OFF; queueDetach(mdns_search_once_t, s_search_once, search); @@ -68,7 +67,7 @@ static void _mdns_search_finish(mdns_search_once_t *search) /** * @brief Add new search to the search chain */ -void _mdns_search_add(mdns_search_once_t *search) +void search_add(mdns_search_once_t *search) { search->next = s_search_once; s_search_once = search; @@ -77,7 +76,7 @@ void _mdns_search_add(mdns_search_once_t *search) /** * @brief Send search packet to all available interfaces */ -void _mdns_search_send(mdns_search_once_t *search) +static void search_send(mdns_search_once_t *search) { mdns_search_once_t *queue = s_search_once; bool found = false; @@ -98,7 +97,7 @@ void _mdns_search_send(mdns_search_once_t *search) uint8_t i, j; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { - _mdns_search_send_pcb(search, (mdns_if_t)i, (mdns_ip_protocol_t)j); + mdns_priv_query_send(search, (mdns_if_t) i, (mdns_ip_protocol_t) j); } } } @@ -108,13 +107,13 @@ void mdns_priv_query_action(mdns_action_t *action, mdns_action_subtype_t type) if (type == ACTION_RUN) { switch (action->type) { case ACTION_SEARCH_ADD: - _mdns_search_add(action->data.search_add.search); + search_add(action->data.search_add.search); break; case ACTION_SEARCH_SEND: - _mdns_search_send(action->data.search_add.search); + search_send(action->data.search_add.search); break; case ACTION_SEARCH_END: - _mdns_search_finish(action->data.search_add.search); + search_finish(action->data.search_add.search); break; default: abort(); @@ -122,7 +121,7 @@ void mdns_priv_query_action(mdns_action_t *action, mdns_action_subtype_t type) return; } if (type == ACTION_CLEANUP) { - _mdns_search_free(action->data.search_add.search); + search_free(action->data.search_add.search); } } @@ -142,13 +141,13 @@ void mdns_priv_query_start_stop(void) if (s->state != SEARCH_OFF) { if (now > (s->started_at + s->timeout)) { s->state = SEARCH_OFF; - if (_mdns_send_search_action(ACTION_SEARCH_END, s) != ESP_OK) { + if (send_search_action(ACTION_SEARCH_END, s) != ESP_OK) { s->state = SEARCH_RUNNING; } } else if (s->state == SEARCH_INIT || (now - s->sent_at) > 1000) { s->state = SEARCH_RUNNING; s->sent_at = now; - if (_mdns_send_search_action(ACTION_SEARCH_SEND, s) != ESP_OK) { + if (send_search_action(ACTION_SEARCH_SEND, s) != ESP_OK) { s->sent_at -= 1000; } } @@ -185,7 +184,7 @@ void mdns_priv_query_done(void) s = search; search = search->next; if (s->max_results && s->num_results >= s->max_results) { - _mdns_search_finish(s); + search_finish(s); } } } @@ -265,7 +264,7 @@ mdns_search_once_t *mdns_priv_query_find(mdns_name_t *name, uint16_t type, mdns_ /** * @brief Create search packet for particular interface */ -static mdns_tx_packet_t *_mdns_create_search_packet(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static mdns_tx_packet_t *create_search_packet(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_result_t *r = NULL; mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); @@ -323,11 +322,11 @@ static mdns_tx_packet_t *_mdns_create_search_packet(mdns_search_once_t *search, /** * @brief Send search packet to particular interface */ -void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +void mdns_priv_query_send(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_tx_packet_t *packet = NULL; if (mdsn_priv_pcb_is_inited(tcpip_if, ip_protocol)) { - packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol); + packet = create_search_packet(search, tcpip_if, ip_protocol); if (!packet) { return; } @@ -336,14 +335,10 @@ void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ } } -/* - * MDNS Search - * */ - /** * @brief Free search structure (except the results) */ -static void _mdns_search_free(mdns_search_once_t *search) +static void search_free(mdns_search_once_t *search) { mdns_mem_free(search->instance); mdns_mem_free(search->service); @@ -355,8 +350,8 @@ static void _mdns_search_free(mdns_search_once_t *search) /** * @brief Allocate new search structure */ -static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, - uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier) +static mdns_search_once_t *search_init(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, + uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier) { mdns_search_once_t *search = (mdns_search_once_t *)mdns_mem_malloc(sizeof(mdns_search_once_t)); if (!search) { @@ -374,7 +369,7 @@ static mdns_search_once_t *_mdns_search_init(const char *name, const char *servi if (!mdns_utils_str_null_or_empty(name)) { search->instance = mdns_mem_strndup(name, MDNS_NAME_BUF_LEN - 1); if (!search->instance) { - _mdns_search_free(search); + search_free(search); return NULL; } } @@ -382,7 +377,7 @@ static mdns_search_once_t *_mdns_search_init(const char *name, const char *servi if (!mdns_utils_str_null_or_empty(service)) { search->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); if (!search->service) { - _mdns_search_free(search); + search_free(search); return NULL; } } @@ -390,7 +385,7 @@ static mdns_search_once_t *_mdns_search_init(const char *name, const char *servi if (!mdns_utils_str_null_or_empty(proto)) { search->proto = mdns_mem_strndup(proto, MDNS_NAME_BUF_LEN - 1); if (!search->proto) { - _mdns_search_free(search); + search_free(search); return NULL; } } @@ -410,136 +405,10 @@ static mdns_search_once_t *_mdns_search_init(const char *name, const char *servi return search; } - -/* - * MDNS QUERY - * */ -void mdns_query_results_free(mdns_result_t *results) -{ - mdns_priv_service_lock(); - mdns_priv_query_results_free(results); - mdns_priv_service_unlock(); -} - -esp_err_t mdns_query_async_delete(mdns_search_once_t *search) -{ - if (!search) { - return ESP_ERR_INVALID_ARG; - } - if (search->state != SEARCH_OFF) { - return ESP_ERR_INVALID_STATE; - } - - mdns_priv_service_lock(); - _mdns_search_free(search); - mdns_priv_service_unlock(); - - return ESP_OK; -} - -bool mdns_query_async_get_results(mdns_search_once_t *search, uint32_t timeout, mdns_result_t **results, uint8_t *num_results) -{ - if (xSemaphoreTake(search->done_semaphore, pdMS_TO_TICKS(timeout)) == pdTRUE) { - if (results) { - *results = search->result; - } - if (num_results) { - *num_results = search->num_results; - } - return true; - } - return false; -} - -mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, const char *proto, uint16_t type, - uint32_t timeout, size_t max_results, mdns_query_notify_t notifier) -{ - mdns_search_once_t *search = NULL; - - if (!mdns_priv_is_server_init() || !timeout || mdns_utils_str_null_or_empty(service) != mdns_utils_str_null_or_empty(proto)) { - return NULL; - } - - search = _mdns_search_init(name, service, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, notifier); - if (!search) { - return NULL; - } - - if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { - _mdns_search_free(search); - return NULL; - } - - return search; -} - -esp_err_t mdns_query_generic(const char *name, const char *service, const char *proto, uint16_t type, mdns_query_transmission_type_t transmission_type, uint32_t timeout, size_t max_results, mdns_result_t **results) -{ - mdns_search_once_t *search = NULL; - - *results = NULL; - - if (!mdns_priv_is_server_init()) { - return ESP_ERR_INVALID_STATE; - } - - if (!timeout || mdns_utils_str_null_or_empty(service) != mdns_utils_str_null_or_empty(proto)) { - return ESP_ERR_INVALID_ARG; - } - - search = _mdns_search_init(name, service, proto, type, transmission_type == MDNS_QUERY_UNICAST, timeout, max_results, NULL); - if (!search) { - return ESP_ERR_NO_MEM; - } - - if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { - _mdns_search_free(search); - return ESP_ERR_NO_MEM; - } - xSemaphoreTake(search->done_semaphore, portMAX_DELAY); - - *results = search->result; - _mdns_search_free(search); - - return ESP_OK; -} - -esp_err_t mdns_query(const char *name, const char *service_type, const char *proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t **results) -{ - return mdns_query_generic(name, service_type, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, results); -} - -esp_err_t mdns_query_ptr(const char *service, const char *proto, uint32_t timeout, size_t max_results, mdns_result_t **results) -{ - if (mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { - return ESP_ERR_INVALID_ARG; - } - - return mdns_query(NULL, service, proto, MDNS_TYPE_PTR, timeout, max_results, results); -} - -esp_err_t mdns_query_srv(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) -{ - if (mdns_utils_str_null_or_empty(instance) || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { - return ESP_ERR_INVALID_ARG; - } - - return mdns_query(instance, service, proto, MDNS_TYPE_SRV, timeout, 1, result); -} - -esp_err_t mdns_query_txt(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) -{ - if (mdns_utils_str_null_or_empty(instance) || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { - return ESP_ERR_INVALID_ARG; - } - - return mdns_query(instance, service, proto, MDNS_TYPE_TXT, timeout, 1, result); -} - /** * @brief Queue search action */ -static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search) +static esp_err_t send_search_action(mdns_action_type_t type, mdns_search_once_t *search) { mdns_action_t *action = NULL; @@ -558,85 +427,6 @@ static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_o return ESP_OK; } - -#ifdef CONFIG_LWIP_IPV4 -esp_err_t mdns_query_a(const char *name, uint32_t timeout, esp_ip4_addr_t *addr) -{ - mdns_result_t *result = NULL; - esp_err_t err; - - if (mdns_utils_str_null_or_empty(name)) { - return ESP_ERR_INVALID_ARG; - } - - if (strstr(name, ".local")) { - ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); - } - - err = mdns_query(name, NULL, NULL, MDNS_TYPE_A, timeout, 1, &result); - - if (err) { - return err; - } - - if (!result) { - return ESP_ERR_NOT_FOUND; - } - - mdns_ip_addr_t *a = result->addr; - while (a) { - if (a->addr.type == ESP_IPADDR_TYPE_V4) { - addr->addr = a->addr.u_addr.ip4.addr; - mdns_query_results_free(result); - return ESP_OK; - } - a = a->next; - } - - mdns_query_results_free(result); - return ESP_ERR_NOT_FOUND; -} -#endif /* CONFIG_LWIP_IPV4 */ - -#ifdef CONFIG_LWIP_IPV6 -esp_err_t mdns_query_aaaa(const char *name, uint32_t timeout, esp_ip6_addr_t *addr) -{ - mdns_result_t *result = NULL; - esp_err_t err; - - if (mdns_utils_str_null_or_empty(name)) { - return ESP_ERR_INVALID_ARG; - } - - if (strstr(name, ".local")) { - ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); - } - - err = mdns_query(name, NULL, NULL, MDNS_TYPE_AAAA, timeout, 1, &result); - - if (err) { - return err; - } - - if (!result) { - return ESP_ERR_NOT_FOUND; - } - - mdns_ip_addr_t *a = result->addr; - while (a) { - if (a->addr.type == ESP_IPADDR_TYPE_V6) { - memcpy(addr->addr, a->addr.u_addr.ip6.addr, 16); - mdns_query_results_free(result); - return ESP_OK; - } - a = a->next; - } - - mdns_query_results_free(result); - return ESP_ERR_NOT_FOUND; -} -#endif /* CONFIG_LWIP_IPV6 */ - /** * @brief Called from parser to add TXT data to search result */ @@ -690,7 +480,7 @@ void mdns_priv_query_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t /** * @brief Chain new IP to search result */ -static void _mdns_result_add_ip(mdns_result_t *r, esp_ip_addr_t *ip) +static void result_add_ip(mdns_result_t *r, esp_ip_addr_t *ip) { mdns_ip_addr_t *a = r->addr; while (a) { @@ -731,7 +521,7 @@ void mdns_priv_query_result_add_ip(mdns_search_once_t *search, const char *hostn r = search->result; while (r) { if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { - _mdns_result_add_ip(r, ip); + result_add_ip(r, ip); mdns_priv_query_update_result_ttl(r, ttl); return; } @@ -765,7 +555,7 @@ void mdns_priv_query_result_add_ip(mdns_search_once_t *search, const char *hostn r = search->result; while (r) { if (r->esp_netif == mdns_priv_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !mdns_utils_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { - _mdns_result_add_ip(r, ip); + result_add_ip(r, ip); mdns_priv_query_update_result_ttl(r, ttl); break; } @@ -874,3 +664,207 @@ mdns_ip_addr_t *mdns_priv_result_addr_create_ip(esp_ip_addr_t *ip) } return a; } + +/** + * @brief MDNS_PUBLIC_API + * */ +void mdns_query_results_free(mdns_result_t *results) +{ + mdns_priv_service_lock(); + mdns_priv_query_results_free(results); + mdns_priv_service_unlock(); +} + +esp_err_t mdns_query_async_delete(mdns_search_once_t *search) +{ + if (!search) { + return ESP_ERR_INVALID_ARG; + } + if (search->state != SEARCH_OFF) { + return ESP_ERR_INVALID_STATE; + } + + mdns_priv_service_lock(); + search_free(search); + mdns_priv_service_unlock(); + + return ESP_OK; +} + +bool mdns_query_async_get_results(mdns_search_once_t *search, uint32_t timeout, mdns_result_t **results, uint8_t *num_results) +{ + if (xSemaphoreTake(search->done_semaphore, pdMS_TO_TICKS(timeout)) == pdTRUE) { + if (results) { + *results = search->result; + } + if (num_results) { + *num_results = search->num_results; + } + return true; + } + return false; +} + +mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, size_t max_results, mdns_query_notify_t notifier) +{ + mdns_search_once_t *search = NULL; + + if (!mdns_priv_is_server_init() || !timeout || mdns_utils_str_null_or_empty(service) != mdns_utils_str_null_or_empty(proto)) { + return NULL; + } + + search = search_init(name, service, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, notifier); + if (!search) { + return NULL; + } + + if (send_search_action(ACTION_SEARCH_ADD, search)) { + search_free(search); + return NULL; + } + + return search; +} + +esp_err_t mdns_query_generic(const char *name, const char *service, const char *proto, uint16_t type, mdns_query_transmission_type_t transmission_type, uint32_t timeout, size_t max_results, mdns_result_t **results) +{ + mdns_search_once_t *search = NULL; + + *results = NULL; + + if (!mdns_priv_is_server_init()) { + return ESP_ERR_INVALID_STATE; + } + + if (!timeout || mdns_utils_str_null_or_empty(service) != mdns_utils_str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + search = search_init(name, service, proto, type, transmission_type == MDNS_QUERY_UNICAST, timeout, max_results, + NULL); + if (!search) { + return ESP_ERR_NO_MEM; + } + + if (send_search_action(ACTION_SEARCH_ADD, search)) { + search_free(search); + return ESP_ERR_NO_MEM; + } + xSemaphoreTake(search->done_semaphore, portMAX_DELAY); + + *results = search->result; + search_free(search); + + return ESP_OK; +} + +esp_err_t mdns_query(const char *name, const char *service_type, const char *proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t **results) +{ + return mdns_query_generic(name, service_type, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, results); +} + +esp_err_t mdns_query_ptr(const char *service, const char *proto, uint32_t timeout, size_t max_results, mdns_result_t **results) +{ + if (mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + return mdns_query(NULL, service, proto, MDNS_TYPE_PTR, timeout, max_results, results); +} + +esp_err_t mdns_query_srv(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) +{ + if (mdns_utils_str_null_or_empty(instance) || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + return mdns_query(instance, service, proto, MDNS_TYPE_SRV, timeout, 1, result); +} + +esp_err_t mdns_query_txt(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) +{ + if (mdns_utils_str_null_or_empty(instance) || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + return mdns_query(instance, service, proto, MDNS_TYPE_TXT, timeout, 1, result); +} + +#ifdef CONFIG_LWIP_IPV4 +esp_err_t mdns_query_a(const char *name, uint32_t timeout, esp_ip4_addr_t *addr) +{ + mdns_result_t *result = NULL; + esp_err_t err; + + if (mdns_utils_str_null_or_empty(name)) { + return ESP_ERR_INVALID_ARG; + } + + if (strstr(name, ".local")) { + ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); + } + + err = mdns_query(name, NULL, NULL, MDNS_TYPE_A, timeout, 1, &result); + + if (err) { + return err; + } + + if (!result) { + return ESP_ERR_NOT_FOUND; + } + + mdns_ip_addr_t *a = result->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V4) { + addr->addr = a->addr.u_addr.ip4.addr; + mdns_query_results_free(result); + return ESP_OK; + } + a = a->next; + } + + mdns_query_results_free(result); + return ESP_ERR_NOT_FOUND; +} +#endif /* CONFIG_LWIP_IPV4 */ + +#ifdef CONFIG_LWIP_IPV6 +esp_err_t mdns_query_aaaa(const char *name, uint32_t timeout, esp_ip6_addr_t *addr) +{ + mdns_result_t *result = NULL; + esp_err_t err; + + if (mdns_utils_str_null_or_empty(name)) { + return ESP_ERR_INVALID_ARG; + } + + if (strstr(name, ".local")) { + ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); + } + + err = mdns_query(name, NULL, NULL, MDNS_TYPE_AAAA, timeout, 1, &result); + + if (err) { + return err; + } + + if (!result) { + return ESP_ERR_NOT_FOUND; + } + + mdns_ip_addr_t *a = result->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { + memcpy(addr->addr, a->addr.u_addr.ip6.addr, 16); + mdns_query_results_free(result); + return ESP_OK; + } + a = a->next; + } + + mdns_query_results_free(result); + return ESP_ERR_NOT_FOUND; +} +#endif /* CONFIG_LWIP_IPV6 */ diff --git a/components/mdns/private_include/mdns_pcb.h b/components/mdns/private_include/mdns_pcb.h index f0e260b3b5..723bdca209 100644 --- a/components/mdns/private_include/mdns_pcb.h +++ b/components/mdns/private_include/mdns_pcb.h @@ -116,7 +116,6 @@ void mdns_priv_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe */ void mdns_priv_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip); - #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 4bcec0d1d1..15fba8a23d 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -151,23 +151,12 @@ #define queueFree(type, queue) while (queue) { type * _q = queue; queue = queue->next; free(_q); } -#define PCB_STATE_IS_PROBING(s) (s->state > PCB_OFF && s->state < PCB_ANNOUNCE_1) -#define PCB_STATE_IS_ANNOUNCING(s) (s->state > PCB_PROBE_3 && s->state < PCB_RUNNING) -#define PCB_STATE_IS_RUNNING(s) (s->state == PCB_RUNNING) - #ifndef HOOK_MALLOC_FAILED -#define HOOK_MALLOC_FAILED ESP_LOGE(TAG, "Cannot allocate memory (line: %d, free heap: %" PRIu32 " bytes)", __LINE__, esp_get_free_heap_size()); +#define HOOK_MALLOC_FAILED do { ESP_LOGE(TAG, "Cannot allocate memory (line: %d, free heap: %" PRIu32 " bytes)", __LINE__, esp_get_free_heap_size()); } while(0) #endif typedef size_t mdns_if_t; -typedef enum { - PCB_OFF, PCB_DUP, PCB_INIT, - PCB_PROBE_1, PCB_PROBE_2, PCB_PROBE_3, - PCB_ANNOUNCE_1, PCB_ANNOUNCE_2, PCB_ANNOUNCE_3, - PCB_RUNNING -} mdns_pcb_state_t; - typedef enum { MDNS_ANSWER, MDNS_NS, MDNS_EXTRA } mdns_parsed_record_type_t; diff --git a/components/mdns/private_include/mdns_querier.h b/components/mdns/private_include/mdns_querier.h index 663700335c..50467121fe 100644 --- a/components/mdns/private_include/mdns_querier.h +++ b/components/mdns/private_include/mdns_querier.h @@ -104,7 +104,7 @@ static inline void mdns_priv_query_update_result_ttl(mdns_result_t *r, uint32_t /** * @brief Send a search query packet on the specified interface and protocol */ -void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +void mdns_priv_query_send(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); #ifdef __cplusplus } From c41424eec4d59ab0a24f554df11dbe7877d089fa Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 1 Apr 2025 17:50:04 +0200 Subject: [PATCH 20/27] fix(mdns): Cleanup mdns sender --- components/mdns/mdns_browser.c | 23 +- components/mdns/mdns_pcb.c | 50 +- components/mdns/mdns_querier.c | 10 +- components/mdns/mdns_receive.c | 158 +++--- components/mdns/mdns_responder.c | 274 +++++----- components/mdns/mdns_send.c | 480 +++++++++--------- components/mdns/mdns_service.c | 8 +- components/mdns/mdns_utils.c | 4 +- .../mdns/private_include/mdns_browser.h | 8 + .../mdns/private_include/mdns_responder.h | 2 +- components/mdns/private_include/mdns_send.h | 41 +- components/mdns/private_include/mdns_utils.h | 2 +- 12 files changed, 527 insertions(+), 533 deletions(-) diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index e432b225be..1b57f68bfd 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -585,7 +585,28 @@ void mdns_priv_browse_result_add_srv(mdns_browse_t *browse, const char *hostname r->next = browse->result; browse->result = r; add_browse_result(out_sync_browse, r); - return; +} + +/**4 + * @brief Browse sync result + */ +esp_err_t mdns_priv_browse_sync(mdns_browse_sync_t *browse_sync) +{ + mdns_action_t *action = NULL; + + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + + action->type = ACTION_BROWSE_SYNC; + action->data.browse_sync.browse_sync = browse_sync; + if (!mdns_priv_queue_action(action)) { + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; } /** diff --git a/components/mdns/mdns_pcb.c b/components/mdns/mdns_pcb.c index affda39064..f631277081 100644 --- a/components/mdns/mdns_pcb.c +++ b/components/mdns/mdns_pcb.c @@ -48,20 +48,23 @@ void mdns_priv_pcb_announce(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, if (PCB_STATE_IS_PROBING(_pcb)) { mdns_priv_init_pcb_probe(tcpip_if, ip_protocol, services, len, include_ip); } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { - mdns_tx_packet_t *p = _mdns_get_next_pcb_packet(tcpip_if, ip_protocol); + mdns_tx_packet_t *p = mdns_priv_get_next_packet(tcpip_if, ip_protocol); if (p) { for (i = 0; i < len; i++) { - if (!_mdns_alloc_answer(&p->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) - || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, false) - || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, false) - || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, false)) { + if (!mdns_priv_create_answer(&p->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) + || !mdns_priv_create_answer(&p->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, + false) + || !mdns_priv_create_answer(&p->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, + false) + || !mdns_priv_create_answer(&p->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, + false)) { break; } } if (include_ip) { - _mdns_dealloc_answer(&p->additional, MDNS_TYPE_A, NULL); - _mdns_dealloc_answer(&p->additional, MDNS_TYPE_AAAA, NULL); - _mdns_append_host_list_in_services(&p->answers, services, len, true, false); + mdns_priv_dealloc_answer(&p->additional, MDNS_TYPE_A, NULL); + mdns_priv_dealloc_answer(&p->additional, MDNS_TYPE_AAAA, NULL); + mdns_priv_append_host_list_in_services(&p->answers, services, len, true, false); } _pcb->state = PCB_ANNOUNCE_1; } @@ -72,9 +75,9 @@ void mdns_priv_pcb_announce(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, } _pcb->state = PCB_ANNOUNCE_1; - mdns_tx_packet_t *p = _mdns_create_announce_packet(tcpip_if, ip_protocol, services, len, include_ip); + mdns_tx_packet_t *p = mdns_priv_create_announce_packet(tcpip_if, ip_protocol, services, len, include_ip); if (p) { - mdns_send_schedule_tx_packet(p, 0); + mdns_priv_send_after(p, 0); } } } @@ -152,7 +155,7 @@ void mdns_priv_pcb_disable(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) mdns_priv_netif_disable(tcpip_if); if (mdns_priv_if_ready(tcpip_if, ip_protocol)) { - _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); + mdns_priv_clear_tx_queue_if(tcpip_if, ip_protocol); deinit_pcb(tcpip_if, ip_protocol); mdns_if_t other_if = mdns_priv_netif_get_other_interface(tcpip_if); if (other_if != MDNS_MAX_INTERFACES && s_pcbs[other_if][ip_protocol].state == PCB_DUP) { @@ -191,7 +194,7 @@ void mdns_priv_pcb_set_duplicate(mdns_if_t tcpip_if) if (mdns_priv_if_ready(other_if, i)) { //stop this interface and mark as dup if (mdns_priv_if_ready(tcpip_if, i)) { - _mdns_clear_pcb_tx_queue_head(tcpip_if, i); + mdns_priv_clear_tx_queue_if(tcpip_if, i); deinit_pcb(tcpip_if, i); } s_pcbs[tcpip_if][i].state = PCB_DUP; @@ -220,13 +223,13 @@ void mdns_priv_pcb_schedule_tx_packet(mdns_tx_packet_t *p) } //fallthrough case PCB_PROBE_2: - mdns_send_schedule_tx_packet(p, 250); + mdns_priv_send_after(p, 250); pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); break; case PCB_PROBE_3: - a = _mdns_create_announce_from_probe(p); + a = mdns_priv_create_announce_from_probe(p); if (!a) { - mdns_send_schedule_tx_packet(p, 250); + mdns_priv_send_after(p, 250); break; } pcb->probe_running = false; @@ -235,22 +238,22 @@ void mdns_priv_pcb_schedule_tx_packet(mdns_tx_packet_t *p) pcb->failed_probes = 0; mdns_mem_free(pcb->probe_services); pcb->probe_services = NULL; - _mdns_free_tx_packet(p); + mdns_priv_free_tx_packet(p); p = a; send_after = 250; //fallthrough case PCB_ANNOUNCE_1: //fallthrough case PCB_ANNOUNCE_2: - mdns_send_schedule_tx_packet(p, send_after); + mdns_priv_send_after(p, send_after); pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); break; case PCB_ANNOUNCE_3: pcb->state = PCB_RUNNING; - _mdns_free_tx_packet(p); + mdns_priv_free_tx_packet(p); break; default: - _mdns_free_tx_packet(p); + mdns_priv_free_tx_packet(p); break; } } @@ -368,7 +371,8 @@ static void init_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_pro pcb->probe_services_len = 0; pcb->probe_running = false; - mdns_tx_packet_t *packet = _mdns_create_probe_packet(tcpip_if, ip_protocol, s, services_final_len, true, probe_ip); + mdns_tx_packet_t *packet = mdns_priv_create_probe_packet(tcpip_if, ip_protocol, s, services_final_len, true, + probe_ip); if (!packet) { mdns_mem_free(s); return; @@ -378,7 +382,7 @@ static void init_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_pro pcb->probe_services = s; pcb->probe_services_len = services_final_len; pcb->probe_running = true; - mdns_send_schedule_tx_packet(packet, ((pcb->failed_probes > 5) ? 1000 : 120) + (esp_random() & 0x7F)); + mdns_priv_send_after(packet, ((pcb->failed_probes > 5) ? 1000 : 120) + (esp_random() & 0x7F)); pcb->state = PCB_PROBE_1; } @@ -386,7 +390,7 @@ void mdns_priv_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol { mdns_pcb_t *pcb = &s_pcbs[tcpip_if][ip_protocol]; - _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); + mdns_priv_clear_tx_queue_if(tcpip_if, ip_protocol); if (mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { pcb->state = PCB_RUNNING; @@ -432,7 +436,7 @@ void mdns_priv_pcb_send_bye_service(mdns_srv_item_t **services, size_t len, bool for (i = 0; i < MDNS_MAX_INTERFACES; i++) { for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { if (mdns_priv_if_ready(i, j) && s_pcbs[i][j].state == PCB_RUNNING) { - mdns_send_bye_pcb((mdns_if_t) i, (mdns_ip_protocol_t) j, services, len, include_ip); + mdns_priv_send_bye((mdns_if_t) i, (mdns_ip_protocol_t) j, services, len, include_ip); } } } diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index c6943c3e85..70cfc59ec5 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -267,7 +267,7 @@ mdns_search_once_t *mdns_priv_query_find(mdns_name_t *name, uint16_t type, mdns_ static mdns_tx_packet_t *create_search_packet(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_result_t *r = NULL; - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + mdns_tx_packet_t *packet = mdns_priv_alloc_packet(tcpip_if, ip_protocol); if (!packet) { return NULL; } @@ -275,7 +275,7 @@ static mdns_tx_packet_t *create_search_packet(mdns_search_once_t *search, mdns_i mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); if (!q) { HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); + mdns_priv_free_tx_packet(packet); return NULL; } q->next = NULL; @@ -299,7 +299,7 @@ static mdns_tx_packet_t *create_search_packet(mdns_search_once_t *search, mdns_i mdns_out_answer_t *a = (mdns_out_answer_t *)mdns_mem_malloc(sizeof(mdns_out_answer_t)); if (!a) { HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); + mdns_priv_free_tx_packet(packet); return NULL; } a->type = MDNS_TYPE_PTR; @@ -330,8 +330,8 @@ void mdns_priv_query_send(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_i if (!packet) { return; } - _mdns_dispatch_tx_packet(packet); - _mdns_free_tx_packet(packet); + mdns_priv_dispatch_tx_packet(packet); + mdns_priv_free_tx_packet(packet); } } diff --git a/components/mdns/mdns_receive.c b/components/mdns/mdns_receive.c index 2b2c06bfe4..75a8400897 100644 --- a/components/mdns/mdns_receive.c +++ b/components/mdns/mdns_receive.c @@ -19,34 +19,12 @@ #include "mdns_pcb.h" #include "mdns_responder.h" -static const char *TAG = "mdns_packet"; - -/**4 - * @brief Browse sync result action -> TODO: Move to the browser module - */ -static esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync) -{ - mdns_action_t *action = NULL; - - action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); - if (!action) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; - } - - action->type = type; - action->data.browse_sync.browse_sync = browse_sync; - if (!mdns_priv_queue_action(action)) { - mdns_mem_free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; -} +static const char *TAG = "mdns_receive"; /** * @brief Check if parsed name is discovery */ -static bool _mdns_name_is_discovery(mdns_name_t *name, uint16_t type) +static bool is_discovery(mdns_name_t *name, uint16_t type) { return ( (name->host[0] && !strcasecmp(name->host, "_services")) @@ -57,7 +35,7 @@ static bool _mdns_name_is_discovery(mdns_name_t *name, uint16_t type) ); } -static mdns_srv_item_t *_mdns_get_service_item_subtype(const char *subtype, const char *service, const char *proto) +static mdns_srv_item_t *get_service_item_subtype(const char *subtype, const char *service, const char *proto) { mdns_srv_item_t *s = mdns_priv_get_services(); while (s) { @@ -78,7 +56,7 @@ static mdns_srv_item_t *_mdns_get_service_item_subtype(const char *subtype, cons /** * @brief Check if the parsed name is ours (matches service or host name) */ -static bool _mdns_name_is_ours(mdns_name_t *name) +static bool is_ours(mdns_name_t *name) { //domain have to be "local" if (mdns_utils_str_null_or_empty(name->domain) || (strcasecmp(name->domain, MDNS_UTILS_DEFAULT_DOMAIN) @@ -108,7 +86,7 @@ static bool _mdns_name_is_ours(mdns_name_t *name) //find the service mdns_srv_item_t *service; if (name->sub) { - service = _mdns_get_service_item_subtype(name->host, name->service, name->proto); + service = get_service_item_subtype(name->host, name->service, name->proto); } else if (mdns_utils_str_null_or_empty(name->host)) { service = mdns_utils_get_service_item(name->service, name->proto, NULL); } else { @@ -140,7 +118,7 @@ static bool _mdns_name_is_ours(mdns_name_t *name) /** * @brief Duplicate string or return error */ -static esp_err_t _mdns_strdup_check(char **out, char *in) +static esp_err_t strdup_check(char **out, char *in) { if (in && in[0]) { *out = mdns_mem_strdup(in); @@ -156,7 +134,7 @@ static esp_err_t _mdns_strdup_check(char **out, char *in) /* * @brief Appends/increments a number to name/instance in case of collision * */ -static char *_mdns_mangle_name(char *in) +static char *mangle_name(char *in) { char *p = strrchr(in, '-'); int suffix = 0; @@ -199,7 +177,7 @@ static char *_mdns_mangle_name(char *in) /** * @brief Get number of items in TXT parsed data */ -static int _mdns_txt_items_count_get(const uint8_t *data, size_t len) +static int get_txt_items_count(const uint8_t *data, size_t len) { if (len == 1) { return 0; @@ -226,7 +204,7 @@ static int _mdns_txt_items_count_get(const uint8_t *data, size_t len) /** * @brief Get the length of TXT item's key name */ -static int _mdns_txt_item_name_get_len(const uint8_t *data, size_t len) +static int get_txt_item_len(const uint8_t *data, size_t len) { if (*data == '=') { return -1; @@ -242,14 +220,14 @@ static int _mdns_txt_item_name_get_len(const uint8_t *data, size_t len) /** * @brief Create TXT result array from parsed TXT data */ -static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_item_t **out_txt, uint8_t **out_value_len, - size_t *out_count) +static void result_txt_create(const uint8_t *data, size_t len, mdns_txt_item_t **out_txt, uint8_t **out_value_len, + size_t *out_count) { *out_txt = NULL; *out_count = 0; uint16_t i = 0, y; - size_t partLen = 0; - int num_items = _mdns_txt_items_count_get(data, len); + size_t part_len = 0; + int num_items = get_txt_items_count(data, len); if (num_items < 0 || num_items > SIZE_MAX / sizeof(mdns_txt_item_t)) { // Error: num_items is incorrect (or too large to allocate) return; @@ -275,18 +253,18 @@ static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_it size_t txt_num = 0; while (i < len && txt_num < num_items) { - partLen = data[i++]; - if (!partLen) { + part_len = data[i++]; + if (!part_len) { break; } - if ((i + partLen) > len) { + if ((i + part_len) > len) { goto handle_error;//error } - int name_len = _mdns_txt_item_name_get_len(data + i, partLen); + int name_len = get_txt_item_len(data + i, part_len); if (name_len < 0) { //invalid item (no name) - i += partLen; + i += part_len; continue; } char *key = (char *) mdns_mem_malloc(name_len + 1); @@ -304,7 +282,7 @@ static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_it i += name_len + 1; t->key = key; - int new_value_len = partLen - name_len - 1; + int new_value_len = part_len - name_len - 1; if (new_value_len > 0) { char *value = (char *) mdns_mem_malloc(new_value_len + 1); if (!value) { @@ -340,7 +318,7 @@ handle_error : /** * @brief Detect IPv4 address collision */ -static int _mdns_check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) +static int check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) { esp_netif_ip_info_t if_ip_info; esp_netif_ip_info_t other_ip_info; @@ -376,7 +354,7 @@ static int _mdns_check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) /** * @brief Detect IPv6 address collision */ -static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) +static int check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) { struct esp_ip6_addr if_ip6; struct esp_ip6_addr other_ip6; @@ -411,7 +389,7 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) /** * @brief Detect TXT collision */ -static int _mdns_check_txt_collision(mdns_service_t *service, const uint8_t *data, size_t len) +static int check_txt_collision(mdns_service_t *service, const uint8_t *data, size_t len) { size_t data_len = 0; if (len <= 1 && service->txt) { // len==0 means incorrect packet (and handled by the packet parser) @@ -456,7 +434,7 @@ static int _mdns_check_txt_collision(mdns_service_t *service, const uint8_t *dat /** * @brief Detect SRV collision */ -static int _mdns_check_srv_collision(mdns_service_t *service, uint16_t priority, uint16_t weight, uint16_t port, const char *host, const char *domain) +static int check_srv_collision(mdns_service_t *service, uint16_t priority, uint16_t weight, uint16_t port, const char *host, const char *domain) { if (mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { return 0; @@ -513,7 +491,7 @@ static int _mdns_check_srv_collision(mdns_service_t *service, uint16_t priority, /** * @brief Check if the parsed name is self-hosted, i.e. we should resolve conflicts */ -static bool _mdns_name_is_selfhosted(mdns_name_t *name) +static bool is_name_selfhosted(mdns_name_t *name) { if (mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { // self-hostname needs to be defined return false; @@ -536,7 +514,7 @@ static bool _mdns_name_is_selfhosted(mdns_name_t *name) /** * @brief Called from parser to check if question matches particular service */ -static bool _mdns_question_matches(mdns_parsed_question_t *question, uint16_t type, mdns_srv_item_t *service) +static bool question_matches(mdns_parsed_question_t *question, uint16_t type, mdns_srv_item_t *service) { if (question->type != type) { return false; @@ -571,11 +549,11 @@ static bool _mdns_question_matches(mdns_parsed_question_t *question, uint16_t ty /** * @brief Removes saved question from parsed data */ -static void _mdns_remove_parsed_question(mdns_parsed_packet_t *parsed_packet, uint16_t type, mdns_srv_item_t *service) +static void remove_parsed_question(mdns_parsed_packet_t *parsed_packet, uint16_t type, mdns_srv_item_t *service) { mdns_parsed_question_t *q = parsed_packet->questions; - if (_mdns_question_matches(q, type, service)) { + if (question_matches(q, type, service)) { parsed_packet->questions = q->next; mdns_mem_free(q->host); mdns_mem_free(q->service); @@ -587,7 +565,7 @@ static void _mdns_remove_parsed_question(mdns_parsed_packet_t *parsed_packet, ui while (q->next) { mdns_parsed_question_t *p = q->next; - if (_mdns_question_matches(p, type, service)) { + if (question_matches(p, type, service)) { q->next = p->next; mdns_mem_free(p->host); mdns_mem_free(p->service); @@ -605,7 +583,7 @@ static void _mdns_remove_parsed_question(mdns_parsed_packet_t *parsed_packet, ui * * @param packet the packet */ -void mdns_parse_packet(mdns_rx_packet_t *packet) +static void mdns_parse_packet(mdns_rx_packet_t *packet) { static mdns_name_t n; mdns_header_t header; @@ -712,7 +690,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) continue; } - if (_mdns_name_is_discovery(name, type)) { + if (is_discovery(name, type)) { //service discovery parsed_packet->discovery = true; mdns_srv_item_t *a = mdns_priv_get_services(); @@ -738,7 +716,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } continue; } - if (!_mdns_name_is_ours(name)) { + if (!is_ours(name)) { continue; } @@ -757,10 +735,10 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) question->unicast = unicast; question->type = type; question->sub = name->sub; - if (_mdns_strdup_check(&(question->host), name->host) - || _mdns_strdup_check(&(question->service), name->service) - || _mdns_strdup_check(&(question->proto), name->proto) - || _mdns_strdup_check(&(question->domain), name->domain)) { + if (strdup_check(&(question->host), name->host) + || strdup_check(&(question->service), name->service) + || strdup_check(&(question->proto), name->proto) + || strdup_check(&(question->domain), name->domain)) { goto clear_rx_packet; } } @@ -810,9 +788,9 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) continue; } - if (parsed_packet->discovery && _mdns_name_is_discovery(name, type)) { + if (parsed_packet->discovery && is_discovery(name, type)) { discovery = true; - } else if (!name->sub && _mdns_name_is_ours(name)) { + } else if (!name->sub && is_ours(name)) { ours = true; if (name->service[0] && name->proto[0]) { service = mdns_utils_get_service_item(name->service, name->proto, NULL); @@ -871,20 +849,20 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (search_result) { mdns_priv_query_result_add_ptr(search_result, name->host, name->service, name->proto, packet->tcpip_if, packet->ip_protocol, ttl); - } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { + } else if ((discovery || ours) && !name->sub && is_ours(name)) { if (name->host[0]) { service = mdns_utils_get_service_item_instance(name->host, name->service, name->proto, NULL); } else { service = mdns_utils_get_service_item(name->service, name->proto, NULL); } if (discovery && service) { - _mdns_remove_parsed_question(parsed_packet, MDNS_TYPE_SDPTR, service); + remove_parsed_question(parsed_packet, MDNS_TYPE_SDPTR, service); } else if (service && parsed_packet->questions && !parsed_packet->probe) { - _mdns_remove_parsed_question(parsed_packet, type, service); + remove_parsed_question(parsed_packet, type, service); } else if (service) { //check if TTL is more than half of the full TTL value (4500) if (ttl > (MDNS_ANSWER_PTR_TTL / 2)) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + mdns_priv_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); } } if (service) { @@ -947,7 +925,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } } - bool is_selfhosted = _mdns_name_is_selfhosted(name); + bool is_selfhosted = is_name_selfhosted(name); if (!mdns_utils_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { continue;//error } @@ -977,10 +955,10 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } else if (ours) { if (parsed_packet->questions && !parsed_packet->probe) { - _mdns_remove_parsed_question(parsed_packet, type, service); + remove_parsed_question(parsed_packet, type, service); continue; } else if (parsed_packet->distributed) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + mdns_priv_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); continue; } if (!is_selfhosted) { @@ -993,7 +971,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else if (!mdns_class) { col = -1; } else if (service) { // only detect srv collision if service existed - col = _mdns_check_srv_collision(service->service, priority, weight, port, name->host, name->domain); + col = check_srv_collision(service->service, priority, weight, port, name->host, name->domain); } if (service && col && (parsed_packet->probe || parsed_packet->authoritative)) { if (col > 0 || !port) { @@ -1001,20 +979,20 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (mdns_priv_pcb_is_probing(packet)) { mdns_priv_pcb_set_probe_failed(packet); if (!mdns_utils_str_null_or_empty(service->service->instance)) { - char *new_instance = _mdns_mangle_name((char *)service->service->instance); + char *new_instance = mangle_name((char *) service->service->instance); if (new_instance) { mdns_mem_free((char *)service->service->instance); service->service->instance = new_instance; } mdns_priv_probe_all_pcbs(&service, 1, false, false); } else if (!mdns_utils_str_null_or_empty(mdns_priv_get_instance())) { - char *new_instance = _mdns_mangle_name((char *) mdns_priv_get_instance()); + char *new_instance = mangle_name((char *) mdns_priv_get_instance()); if (new_instance) { mdns_priv_set_instance(new_instance); } mdns_priv_restart_all_pcbs_no_instance(); } else { - char *new_host = _mdns_mangle_name((char *) mdns_priv_get_global_hostname()); + char *new_host = mangle_name((char *) mdns_priv_get_global_hostname()); if (new_host) { mdns_priv_remap_self_service_hostname(mdns_priv_get_global_hostname(), new_host); mdns_priv_set_global_hostname(new_host); @@ -1022,12 +1000,12 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) mdns_priv_restart_all_pcbs(); } } else if (service) { - mdns_send_bye_pcb(packet->tcpip_if, packet->ip_protocol, &service, 1, false); + mdns_priv_send_bye(packet->tcpip_if, packet->ip_protocol, &service, 1, false); mdns_priv_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, false); } } } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + mdns_priv_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); } } } else if (type == MDNS_TYPE_TXT) { @@ -1037,7 +1015,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) mdns_result_t *result = NULL; if (browse_result) { - _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); + result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); mdns_priv_browse_result_add_txt(browse_result, browse_result_instance, browse_result_service, browse_result_proto, txt, txt_value_len, txt_count, packet->tcpip_if, @@ -1064,7 +1042,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } if (!result->txt) { - _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); + result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); if (txt_count) { result->txt = txt; result->txt_count = txt_count; @@ -1072,7 +1050,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } } else { - _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); + result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); if (txt_count) { mdns_priv_query_result_add_txt(search_result, txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, ttl); @@ -1080,10 +1058,10 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } else if (ours) { if (parsed_packet->questions && !parsed_packet->probe && service) { - _mdns_remove_parsed_question(parsed_packet, type, service); + remove_parsed_question(parsed_packet, type, service); continue; } - if (!_mdns_name_is_selfhosted(name)) { + if (!is_name_selfhosted(name)) { continue; } //detect collision (-1=won, 0=none, 1=lost) @@ -1093,14 +1071,14 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else if (!mdns_class) { col = -1; } else if (service) { // only detect txt collision if service existed - col = _mdns_check_txt_collision(service->service, data_ptr, data_len); + col = check_txt_collision(service->service, data_ptr, data_len); } if (col && !mdns_priv_pcb_is_probing(packet) && service) { do_not_reply = true; mdns_priv_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); } else if (ttl > (MDNS_ANSWER_TXT_TTL / 2) && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( packet)) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + mdns_priv_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); } } @@ -1125,10 +1103,10 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } else if (ours) { if (parsed_packet->questions && !parsed_packet->probe) { - _mdns_remove_parsed_question(parsed_packet, type, NULL); + remove_parsed_question(parsed_packet, type, NULL); continue; } - if (!_mdns_name_is_selfhosted(name)) { + if (!is_name_selfhosted(name)) { continue; } //detect collision (-1=won, 0=none, 1=lost) @@ -1138,7 +1116,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else if (!mdns_class) { col = -1; } else { - col = _mdns_check_aaaa_collision(&(ip6.u_addr.ip6), packet->tcpip_if); + col = check_aaaa_collision(&(ip6.u_addr.ip6), packet->tcpip_if); } if (col == 2) { goto clear_rx_packet; @@ -1147,7 +1125,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (mdns_priv_pcb_is_probing(packet)) { if (col && (parsed_packet->probe || parsed_packet->authoritative)) { mdns_priv_pcb_set_probe_failed(packet); - char *new_host = _mdns_mangle_name((char *) mdns_priv_get_global_hostname()); + char *new_host = mangle_name((char *) mdns_priv_get_global_hostname()); if (new_host) { mdns_priv_remap_self_service_hostname(mdns_priv_get_global_hostname(), new_host); mdns_priv_set_global_hostname(new_host); @@ -1159,7 +1137,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( packet)) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); + mdns_priv_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); } } @@ -1185,10 +1163,10 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } else if (ours) { if (parsed_packet->questions && !parsed_packet->probe) { - _mdns_remove_parsed_question(parsed_packet, type, NULL); + remove_parsed_question(parsed_packet, type, NULL); continue; } - if (!_mdns_name_is_selfhosted(name)) { + if (!is_name_selfhosted(name)) { continue; } //detect collision (-1=won, 0=none, 1=lost) @@ -1198,7 +1176,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } else if (!mdns_class) { col = -1; } else { - col = _mdns_check_a_collision(&(ip.u_addr.ip4), packet->tcpip_if); + col = check_a_collision(&(ip.u_addr.ip4), packet->tcpip_if); } if (col == 2) { goto clear_rx_packet; @@ -1207,7 +1185,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (mdns_priv_pcb_is_probing(packet)) { if (col && (parsed_packet->probe || parsed_packet->authoritative)) { mdns_priv_pcb_set_probe_failed(packet); - char *new_host = _mdns_mangle_name((char *) mdns_priv_get_global_hostname()); + char *new_host = mangle_name((char *) mdns_priv_get_global_hostname()); if (new_host) { mdns_priv_remap_self_service_hostname(mdns_priv_get_global_hostname(), new_host); mdns_priv_set_global_hostname(new_host); @@ -1219,7 +1197,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) } } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !mdns_priv_pcb_is_probing( packet)) { - _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); + mdns_priv_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); } } @@ -1241,7 +1219,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet) if (out_sync_browse->sync_result) { DBG_BROWSE_RESULTS_WITH_MSG(out_sync_browse->sync_result->result, "Changed result:"); - _mdns_sync_browse_action(ACTION_BROWSE_SYNC, out_sync_browse); + mdns_priv_browse_sync(out_sync_browse); } else { mdns_mem_free(out_sync_browse); } diff --git a/components/mdns/mdns_responder.c b/components/mdns/mdns_responder.c index 41e0b4d1cc..9e9a280174 100644 --- a/components/mdns/mdns_responder.c +++ b/components/mdns/mdns_responder.c @@ -19,27 +19,26 @@ typedef struct mdns_server_s { const char *hostname; const char *instance; mdns_srv_item_t *services; + mdns_host_item_t *host_list; + mdns_host_item_t self_host; + SemaphoreHandle_t action_sema; } mdns_server_t; -static mdns_server_t *s_mdns_server = NULL; -static mdns_host_item_t *s_mdns_host_list = NULL; -static mdns_host_item_t s_mdns_self_host; -static SemaphoreHandle_t s_action_sema; - static const char *TAG = "mdns_responder"; +static mdns_server_t *s_server = NULL; esp_err_t mdns_priv_responder_init(void) { - s_mdns_server = (mdns_server_t *)mdns_mem_malloc(sizeof(mdns_server_t)); - if (!s_mdns_server) { + s_server = (mdns_server_t *)mdns_mem_malloc(sizeof(mdns_server_t)); + if (!s_server) { HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } - memset((uint8_t *)s_mdns_server, 0, sizeof(mdns_server_t)); + memset((uint8_t *)s_server, 0, sizeof(mdns_server_t)); - s_action_sema = xSemaphoreCreateBinary(); - if (!s_action_sema) { - mdns_mem_free(s_mdns_server); + s_server->action_sema = xSemaphoreCreateBinary(); + if (!s_server->action_sema) { + mdns_mem_free(s_server); return ESP_ERR_NO_MEM; } @@ -48,73 +47,68 @@ esp_err_t mdns_priv_responder_init(void) void mdns_priv_responder_free(void) { - if (s_action_sema != NULL) { - vSemaphoreDelete(s_action_sema); - s_action_sema = NULL; + if (s_server->action_sema != NULL) { + vSemaphoreDelete(s_server->action_sema); + s_server->action_sema = NULL; } - if (s_mdns_server == NULL) { + if (s_server == NULL) { return; } - mdns_mem_free((char *)s_mdns_server->hostname); - mdns_mem_free((char *)s_mdns_server->instance); - mdns_mem_free(s_mdns_server); - s_mdns_server = NULL; + mdns_mem_free((char *)s_server->hostname); + mdns_mem_free((char *)s_server->instance); + mdns_mem_free(s_server); + s_server = NULL; } const char *mdns_priv_get_global_hostname(void) { - return s_mdns_server ? s_mdns_server->hostname : NULL; + return s_server ? s_server->hostname : NULL; } mdns_srv_item_t *mdns_priv_get_services(void) { - return s_mdns_server ? s_mdns_server->services : NULL; + return s_server ? s_server->services : NULL; } mdns_host_item_t *mdns_priv_get_hosts(void) { - return s_mdns_host_list; + return s_server ? s_server->host_list : NULL; } -mdns_host_item_t *priv_get_self_host(void) +mdns_host_item_t *mdns_priv_get_self_host(void) { - return &s_mdns_self_host; + return s_server ? &s_server->self_host : NULL; } void mdns_priv_set_global_hostname(const char *hostname) { - if (s_mdns_server) { - if (s_mdns_server->hostname) { - mdns_mem_free((void *)s_mdns_server->hostname); + if (s_server) { + if (s_server->hostname) { + mdns_mem_free((void *)s_server->hostname); } - s_mdns_server->hostname = hostname; - s_mdns_self_host.hostname = hostname; + s_server->hostname = hostname; + s_server->self_host.hostname = hostname; } } const char *mdns_priv_get_instance(void) { - return s_mdns_server ? s_mdns_server->instance : NULL; + return s_server ? s_server->instance : NULL; } void mdns_priv_set_instance(const char *instance) { - if (s_mdns_server) { - if (s_mdns_server->instance) { - mdns_mem_free((void *)s_mdns_server->instance); + if (s_server) { + if (s_server->instance) { + mdns_mem_free((void *)s_server->instance); } - s_mdns_server->instance = instance; + s_server->instance = instance; } } bool mdns_priv_is_server_init(void) { - return s_mdns_server != NULL; -} - -static inline bool _str_null_or_empty(const char *str) -{ - return (str == NULL || *str == 0); + return s_server != NULL; } static bool can_add_more_services(void) @@ -122,7 +116,7 @@ static bool can_add_more_services(void) #if MDNS_MAX_SERVICES == 0 return false; #else - mdns_srv_item_t *s = s_mdns_server->services; + mdns_srv_item_t *s = s_server->services; uint16_t service_num = 0; while (s) { service_num ++; @@ -155,7 +149,7 @@ static void send_final_bye(bool include_ip) { //collect all services to send bye packet size_t srv_count = 0; - mdns_srv_item_t *a = s_mdns_server->services; + mdns_srv_item_t *a = s_server->services; while (a) { srv_count++; a = a->next; @@ -165,7 +159,7 @@ static void send_final_bye(bool include_ip) } mdns_srv_item_t *services[srv_count]; size_t i = 0; - a = s_mdns_server->services; + a = s_server->services; while (a) { services[i++] = a; a = a->next; @@ -179,7 +173,7 @@ static void send_final_bye(bool include_ip) static void send_bye_all_pcbs_no_instance(bool include_ip) { size_t srv_count = 0; - mdns_srv_item_t *a = s_mdns_server->services; + mdns_srv_item_t *a = s_server->services; while (a) { if (!a->service->instance) { srv_count++; @@ -191,7 +185,7 @@ static void send_bye_all_pcbs_no_instance(bool include_ip) } mdns_srv_item_t *services[srv_count]; size_t i = 0; - a = s_mdns_server->services; + a = s_server->services; while (a) { if (!a->service->instance) { services[i++] = a; @@ -204,7 +198,7 @@ static void send_bye_all_pcbs_no_instance(bool include_ip) void mdns_priv_restart_all_pcbs_no_instance(void) { size_t srv_count = 0; - mdns_srv_item_t *a = s_mdns_server->services; + mdns_srv_item_t *a = s_server->services; while (a) { if (!a->service->instance) { srv_count++; @@ -216,7 +210,7 @@ void mdns_priv_restart_all_pcbs_no_instance(void) } mdns_srv_item_t *services[srv_count]; size_t i = 0; - a = s_mdns_server->services; + a = s_server->services; while (a) { if (!a->service->instance) { services[i++] = a; @@ -228,9 +222,9 @@ void mdns_priv_restart_all_pcbs_no_instance(void) void mdns_priv_restart_all_pcbs(void) { - _mdns_clear_tx_queue_head(); + mdns_priv_clear_tx_queue(); size_t srv_count = 0; - mdns_srv_item_t *a = s_mdns_server->services; + mdns_srv_item_t *a = s_server->services; while (a) { srv_count++; a = a->next; @@ -241,7 +235,7 @@ void mdns_priv_restart_all_pcbs(void) } mdns_srv_item_t *services[srv_count]; size_t l = 0; - a = s_mdns_server->services; + a = s_server->services; while (a) { services[l++] = a; a = a->next; @@ -422,18 +416,18 @@ bool mdns_priv_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *addre } host->address_list = address_list; host->hostname = hostname; - host->next = s_mdns_host_list; - s_mdns_host_list = host; + host->next = s_server->host_list; + s_server->host_list = host; return true; } static bool delegate_hostname_set_address(const char *hostname, mdns_ip_addr_t *address_list) { - if (!_str_null_or_empty(s_mdns_server->hostname) && - strcasecmp(hostname, s_mdns_server->hostname) == 0) { + if (!mdns_utils_str_null_or_empty(s_server->hostname) && + strcasecmp(hostname, s_server->hostname) == 0) { return false; } - mdns_host_item_t *host = s_mdns_host_list; + mdns_host_item_t *host = s_server->host_list; while (host != NULL) { if (strcasecmp(hostname, host->hostname) == 0) { // free previous address list @@ -449,7 +443,7 @@ static bool delegate_hostname_set_address(const char *hostname, mdns_ip_addr_t * void mdns_priv_free_delegated_hostnames(void) { - mdns_host_item_t *host = s_mdns_host_list; + mdns_host_item_t *host = s_server->host_list; while (host != NULL) { mdns_utils_free_address_list(host->address_list); mdns_mem_free((char *)host->hostname); @@ -457,20 +451,20 @@ void mdns_priv_free_delegated_hostnames(void) host = host->next; mdns_mem_free(item); } - s_mdns_host_list = NULL; + s_server->host_list = NULL; } static bool delegate_hostname_remove(const char *hostname) { - mdns_srv_item_t *srv = s_mdns_server->services; + mdns_srv_item_t *srv = s_server->services; mdns_srv_item_t *prev_srv = NULL; while (srv) { if (strcasecmp(srv->service->hostname, hostname) == 0) { mdns_srv_item_t *to_free = srv; mdns_priv_pcb_send_bye_service(&srv, 1, false); - _mdns_remove_scheduled_service_packets(srv->service); + mdns_priv_remove_scheduled_service_packets(srv->service); if (prev_srv == NULL) { - s_mdns_server->services = srv->next; + s_server->services = srv->next; srv = srv->next; } else { prev_srv->next = srv->next; @@ -483,12 +477,12 @@ static bool delegate_hostname_remove(const char *hostname) srv = srv->next; } } - mdns_host_item_t *host = s_mdns_host_list; + mdns_host_item_t *host = s_server->host_list; mdns_host_item_t *prev_host = NULL; while (host != NULL) { if (strcasecmp(hostname, host->hostname) == 0) { if (prev_host == NULL) { - s_mdns_host_list = host->next; + s_server->host_list = host->next; } else { prev_host->next = host->next; } @@ -506,7 +500,7 @@ static bool delegate_hostname_remove(const char *hostname) void mdns_priv_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) { - mdns_srv_item_t *service = s_mdns_server->services; + mdns_srv_item_t *service = s_server->services; while (service) { if (service->service->hostname && @@ -524,17 +518,17 @@ void mdns_priv_responder_action(mdns_action_t *action, mdns_action_subtype_t typ switch (action->type) { case ACTION_HOSTNAME_SET: send_bye_all_pcbs_no_instance(true); - mdns_priv_remap_self_service_hostname(s_mdns_server->hostname, action->data.hostname_set.hostname); - mdns_mem_free((char *)s_mdns_server->hostname); - s_mdns_server->hostname = action->data.hostname_set.hostname; - s_mdns_self_host.hostname = action->data.hostname_set.hostname; + mdns_priv_remap_self_service_hostname(s_server->hostname, action->data.hostname_set.hostname); + mdns_mem_free((char *)s_server->hostname); + s_server->hostname = action->data.hostname_set.hostname; + s_server->self_host.hostname = action->data.hostname_set.hostname; mdns_priv_restart_all_pcbs(); - xSemaphoreGive(s_action_sema); + xSemaphoreGive(s_server->action_sema); break; case ACTION_INSTANCE_SET: send_bye_all_pcbs_no_instance(false); - mdns_mem_free((char *)s_mdns_server->instance); - s_mdns_server->instance = action->data.instance; + mdns_mem_free((char *)s_server->instance); + s_server->instance = action->data.instance; mdns_priv_restart_all_pcbs_no_instance(); break; case ACTION_DELEGATE_HOSTNAME_ADD: @@ -543,7 +537,7 @@ void mdns_priv_responder_action(mdns_action_t *action, mdns_action_subtype_t typ mdns_mem_free((char *)action->data.delegate_hostname.hostname); mdns_utils_free_address_list(action->data.delegate_hostname.address_list); } - xSemaphoreGive(s_action_sema); + xSemaphoreGive(s_server->action_sema); break; case ACTION_DELEGATE_HOSTNAME_SET_ADDR: if (!delegate_hostname_set_address(action->data.delegate_hostname.hostname, @@ -589,10 +583,10 @@ void mdns_priv_responder_action(mdns_action_t *action, mdns_action_subtype_t typ */ esp_err_t mdns_hostname_set(const char *hostname) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_ARG; } - if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + if (mdns_utils_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } char *new_hostname = mdns_mem_strndup(hostname, MDNS_NAME_BUF_LEN - 1); @@ -613,7 +607,7 @@ esp_err_t mdns_hostname_set(const char *hostname) mdns_mem_free(action); return ESP_ERR_NO_MEM; } - xSemaphoreTake(s_action_sema, portMAX_DELAY); + xSemaphoreTake(s_server->action_sema, portMAX_DELAY); return ESP_OK; } @@ -623,13 +617,13 @@ esp_err_t mdns_hostname_get(char *hostname) return ESP_ERR_INVALID_ARG; } - if (!s_mdns_server || !s_mdns_server->hostname) { + if (!s_server || !s_server->hostname) { return ESP_ERR_INVALID_STATE; } mdns_priv_service_lock(); - size_t len = strnlen(s_mdns_server->hostname, MDNS_NAME_BUF_LEN - 1); - strncpy(hostname, s_mdns_server->hostname, len); + size_t len = strnlen(s_server->hostname, MDNS_NAME_BUF_LEN - 1); + strncpy(hostname, s_server->hostname, len); hostname[len] = 0; mdns_priv_service_unlock(); return ESP_OK; @@ -637,10 +631,10 @@ esp_err_t mdns_hostname_get(char *hostname) esp_err_t mdns_delegate_hostname_add(const char *hostname, const mdns_ip_addr_t *address_list) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } - if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + if (mdns_utils_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } char *new_hostname = mdns_mem_strndup(hostname, MDNS_NAME_BUF_LEN - 1); @@ -662,16 +656,16 @@ esp_err_t mdns_delegate_hostname_add(const char *hostname, const mdns_ip_addr_t mdns_mem_free(action); return ESP_ERR_NO_MEM; } - xSemaphoreTake(s_action_sema, portMAX_DELAY); + xSemaphoreTake(s_server->action_sema, portMAX_DELAY); return ESP_OK; } esp_err_t mdns_delegate_hostname_remove(const char *hostname) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } - if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + if (mdns_utils_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } char *new_hostname = mdns_mem_strndup(hostname, MDNS_NAME_BUF_LEN - 1); @@ -697,10 +691,10 @@ esp_err_t mdns_delegate_hostname_remove(const char *hostname) esp_err_t mdns_delegate_hostname_set_address(const char *hostname, const mdns_ip_addr_t *address_list) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } - if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + if (mdns_utils_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } char *new_hostname = mdns_mem_strndup(hostname, MDNS_NAME_BUF_LEN - 1); @@ -736,10 +730,10 @@ bool mdns_hostname_exists(const char *hostname) esp_err_t mdns_instance_name_set(const char *instance) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } - if (_str_null_or_empty(instance) || s_mdns_server->hostname == NULL || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { + if (mdns_utils_str_null_or_empty(instance) || s_server->hostname == NULL || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } char *new_instance = mdns_mem_strndup(instance, MDNS_NAME_BUF_LEN - 1); @@ -766,13 +760,13 @@ esp_err_t mdns_instance_name_set(const char *instance) esp_err_t mdns_service_add_for_host(const char *instance, const char *service, const char *proto, const char *host, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!s_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !s_mdns_server->hostname) { + if (!s_server || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto) || !s_server->hostname) { return ESP_ERR_INVALID_ARG; } mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : s_mdns_server->hostname; + const char *hostname = host ? host : s_server->hostname; mdns_service_t *s = NULL; ESP_GOTO_ON_FALSE(can_add_more_services(), ESP_ERR_NO_MEM, err, TAG, @@ -790,8 +784,8 @@ esp_err_t mdns_service_add_for_host(const char *instance, const char *service, c item->service = s; item->next = NULL; - item->next = s_mdns_server->services; - s_mdns_server->services = item; + item->next = s_server->services; + s_server->services = item; mdns_priv_probe_all_pcbs(&item, 1, false, false); mdns_priv_service_unlock(); return ESP_OK; @@ -808,7 +802,7 @@ esp_err_t mdns_service_add_for_host(const char *instance, const char *service, c esp_err_t mdns_service_add(const char *instance, const char *service, const char *proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_add_for_host(instance, service, proto, NULL, port, txt, num_items); @@ -888,7 +882,7 @@ static mdns_txt_item_t *copy_txt_items(mdns_txt_linked_item_t *items, uint8_t ** static mdns_ip_addr_t *copy_delegated_host_address_list(char *hostname) { - mdns_host_item_t *host = s_mdns_host_list; + mdns_host_item_t *host = s_server->host_list; while (host) { if (strcasecmp(host->hostname, hostname) == 0) { return mdns_utils_copy_address_list(host->address_list); @@ -900,23 +894,23 @@ static mdns_ip_addr_t *copy_delegated_host_address_list(char *hostname) static mdns_result_t *lookup_service(const char *instance, const char *service, const char *proto, size_t max_results, bool selfhost) { - if (_str_null_or_empty(service) || _str_null_or_empty(proto)) { + if (mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { return NULL; } mdns_result_t *results = NULL; size_t num_results = 0; - mdns_srv_item_t *s = s_mdns_server->services; + mdns_srv_item_t *s = s_server->services; while (s) { mdns_service_t *srv = s->service; if (!srv || !srv->hostname) { s = s->next; continue; } - bool is_service_selfhosted = !_str_null_or_empty(s_mdns_server->hostname) && !strcasecmp(s_mdns_server->hostname, srv->hostname); - bool is_service_delegated = _str_null_or_empty(s_mdns_server->hostname) || strcasecmp(s_mdns_server->hostname, srv->hostname); + bool is_service_selfhosted = !mdns_utils_str_null_or_empty(s_server->hostname) && !strcasecmp(s_server->hostname, srv->hostname); + bool is_service_delegated = mdns_utils_str_null_or_empty(s_server->hostname) || strcasecmp(s_server->hostname, srv->hostname); if ((selfhost && is_service_selfhosted) || (!selfhost && is_service_delegated)) { if (!strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && - (_str_null_or_empty(instance) || mdns_utils_instance_name_match(srv->instance, instance))) { + (mdns_utils_str_null_or_empty(instance) || mdns_utils_instance_name_match(srv->instance, instance))) { mdns_result_t *item = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); if (!item) { HOOK_MALLOC_FAILED; @@ -925,7 +919,7 @@ static mdns_result_t *lookup_service(const char *instance, const char *service, item->next = results; results = item; item->esp_netif = NULL; - item->ttl = _str_null_or_empty(instance) ? MDNS_ANSWER_PTR_TTL : MDNS_ANSWER_SRV_TTL; + item->ttl = mdns_utils_str_null_or_empty(instance) ? MDNS_ANSWER_PTR_TTL : MDNS_ANSWER_SRV_TTL; item->ip_protocol = MDNS_IP_PROTOCOL_MAX; if (srv->instance) { item->instance_name = mdns_mem_strndup(srv->instance, MDNS_NAME_BUF_LEN - 1); @@ -982,8 +976,8 @@ esp_err_t mdns_service_port_set_for_host(const char *instance, const char *servi { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : s_mdns_server->hostname; - ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && port, + const char *hostname = host ? host : s_server->hostname; + ESP_GOTO_ON_FALSE(s_server && s_server->services && !mdns_utils_str_null_or_empty(service) && !mdns_utils_str_null_or_empty(proto) && port, ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); @@ -998,7 +992,7 @@ esp_err_t mdns_service_port_set_for_host(const char *instance, const char *servi esp_err_t mdns_service_port_set(const char *service, const char *proto, uint16_t port) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_port_set_for_host(NULL, service, proto, NULL, port); @@ -1009,8 +1003,8 @@ esp_err_t mdns_service_txt_set_for_host(const char *instance, const char *servic { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : s_mdns_server->hostname; - ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !(num_items && txt_items == NULL), + const char *hostname = host ? host : s_server->hostname; + ESP_GOTO_ON_FALSE(s_server && s_server->services && !mdns_utils_str_null_or_empty(service) && !mdns_utils_str_null_or_empty(proto) && !(num_items && txt_items == NULL), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); @@ -1036,7 +1030,7 @@ esp_err_t mdns_service_txt_set_for_host(const char *instance, const char *servic esp_err_t mdns_service_txt_set(const char *service, const char *proto, mdns_txt_item_t txt[], uint8_t num_items) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_txt_set_for_host(NULL, service, proto, NULL, txt, num_items); @@ -1049,8 +1043,8 @@ esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char esp_err_t ret = ESP_OK; char *value = NULL; mdns_txt_linked_item_t *new_txt = NULL; - const char *hostname = host ? host : s_mdns_server->hostname; - ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(key) && + const char *hostname = host ? host : s_server->hostname; + ESP_GOTO_ON_FALSE(s_server && s_server->services && !mdns_utils_str_null_or_empty(service) && !mdns_utils_str_null_or_empty(proto) && !mdns_utils_str_null_or_empty(key) && !((!value_arg && value_len)), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); @@ -1108,7 +1102,7 @@ esp_err_t mdns_service_txt_item_set_for_host(const char *instance, const char *s esp_err_t mdns_service_txt_item_set(const char *service, const char *proto, const char *key, const char *value) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, NULL, key, @@ -1118,7 +1112,7 @@ esp_err_t mdns_service_txt_item_set(const char *service, const char *proto, cons esp_err_t mdns_service_txt_item_set_with_explicit_value_len(const char *service, const char *proto, const char *key, const char *value, uint8_t value_len) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, NULL, key, value, value_len); @@ -1129,8 +1123,8 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : s_mdns_server->hostname; - ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(key), + const char *hostname = host ? host : s_server->hostname; + ESP_GOTO_ON_FALSE(s_server && s_server->services && !mdns_utils_str_null_or_empty(service) && !mdns_utils_str_null_or_empty(proto) && !mdns_utils_str_null_or_empty(key), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); @@ -1173,7 +1167,7 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char esp_err_t mdns_service_txt_item_remove(const char *service, const char *proto, const char *key) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_txt_item_remove_for_host(NULL, service, proto, NULL, key); @@ -1213,8 +1207,8 @@ esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && - !_str_null_or_empty(subtype), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); + ESP_GOTO_ON_FALSE(s_server && s_server->services && !mdns_utils_str_null_or_empty(service) && !mdns_utils_str_null_or_empty(proto) && + !mdns_utils_str_null_or_empty(subtype), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_name, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); @@ -1229,7 +1223,7 @@ esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const ESP_GOTO_ON_FALSE(remove_subtypes->subtype, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); remove_subtypes->next = NULL; - _mdns_send_bye_subtype(s, instance_name, remove_subtypes); + mdns_priv_send_bye_subtype(s, instance_name, remove_subtypes); free_subtype(remove_subtypes); err: mdns_priv_service_unlock(); @@ -1271,7 +1265,7 @@ esp_err_t mdns_service_subtype_add_multiple_items_for_host(const char *instance_ mdns_priv_service_lock(); esp_err_t ret = ESP_OK; int cur_index = 0; - ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && + ESP_GOTO_ON_FALSE(s_server && s_server->services && !mdns_utils_str_null_or_empty(service) && !mdns_utils_str_null_or_empty(proto) && (num_items > 0), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_name, service, proto, hostname); @@ -1366,7 +1360,7 @@ esp_err_t mdns_service_subtype_update_multiple_items_for_host(const char *instan mdns_priv_service_lock(); esp_err_t ret = ESP_OK; int cur_index = 0; - ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service_type) && !_str_null_or_empty(proto), + ESP_GOTO_ON_FALSE(s_server && s_server->services && !mdns_utils_str_null_or_empty(service_type) && !mdns_utils_str_null_or_empty(proto), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_name, service_type, proto, hostname); @@ -1375,7 +1369,7 @@ esp_err_t mdns_service_subtype_update_multiple_items_for_host(const char *instan mdns_subtype_t *goodbye_subtype = service_find_subtype_needed_sendbye(s->service, subtype, num_items); if (goodbye_subtype) { - _mdns_send_bye_subtype(s, instance_name, goodbye_subtype); + mdns_priv_send_bye_subtype(s, instance_name, goodbye_subtype); } free_subtype(goodbye_subtype); @@ -1412,10 +1406,10 @@ esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, cons { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : s_mdns_server->hostname; + const char *hostname = host ? host : s_server->hostname; - ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && - !_str_null_or_empty(instance) && strlen(instance) <= (MDNS_NAME_BUF_LEN - 1), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); + ESP_GOTO_ON_FALSE(s_server && s_server->services && !mdns_utils_str_null_or_empty(service) && !mdns_utils_str_null_or_empty(proto) && + !mdns_utils_str_null_or_empty(instance) && strlen(instance) <= (MDNS_NAME_BUF_LEN - 1), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance_old, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); @@ -1435,7 +1429,7 @@ esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, cons esp_err_t mdns_service_instance_name_set(const char *service, const char *proto, const char *instance) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_instance_name_set_for_host(NULL, service, proto, NULL, instance); @@ -1445,24 +1439,24 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - const char *hostname = host ? host : s_mdns_server->hostname; - ESP_GOTO_ON_FALSE(s_mdns_server && s_mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto), + const char *hostname = host ? host : s_server->hostname; + ESP_GOTO_ON_FALSE(s_server && s_server->services && !mdns_utils_str_null_or_empty(service) && !mdns_utils_str_null_or_empty(proto), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = mdns_utils_get_service_item_instance(instance, service, proto, hostname); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); - mdns_srv_item_t *a = s_mdns_server->services; + mdns_srv_item_t *a = s_server->services; mdns_srv_item_t *b = a; if (instance) { while (a) { if (mdns_utils_service_match_instance(a->service, instance, service, proto, hostname)) { - if (s_mdns_server->services != a) { + if (s_server->services != a) { b->next = a->next; } else { - s_mdns_server->services = a->next; + s_server->services = a->next; } mdns_priv_pcb_send_bye_service(&a, 1, false); - _mdns_remove_scheduled_service_packets(a->service); + mdns_priv_remove_scheduled_service_packets(a->service); free_service(a->service); mdns_mem_free(a); break; @@ -1473,13 +1467,13 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service } else { while (a) { if (mdns_utils_service_match(a->service, service, proto, hostname)) { - if (s_mdns_server->services != a) { + if (s_server->services != a) { b->next = a->next; } else { - s_mdns_server->services = a->next; + s_server->services = a->next; } mdns_priv_pcb_send_bye_service(&a, 1, false); - _mdns_remove_scheduled_service_packets(a->service); + mdns_priv_remove_scheduled_service_packets(a->service); free_service(a->service); mdns_mem_free(a); break; @@ -1496,7 +1490,7 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service esp_err_t mdns_service_remove(const char *service_type, const char *proto) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_remove_for_host(NULL, service_type, proto, NULL); @@ -1506,18 +1500,18 @@ esp_err_t mdns_service_remove_all(void) { mdns_priv_service_lock(); esp_err_t ret = ESP_OK; - ESP_GOTO_ON_FALSE(s_mdns_server, ESP_ERR_INVALID_ARG, done, TAG, "Invalid state"); - if (!s_mdns_server->services) { + ESP_GOTO_ON_FALSE(s_server, ESP_ERR_INVALID_ARG, done, TAG, "Invalid state"); + if (!s_server->services) { goto done; } send_final_bye(false); - mdns_srv_item_t *services = s_mdns_server->services; - s_mdns_server->services = NULL; + mdns_srv_item_t *services = s_server->services; + s_server->services = NULL; while (services) { mdns_srv_item_t *s = services; services = services->next; - _mdns_remove_scheduled_service_packets(s->service); + mdns_priv_remove_scheduled_service_packets(s->service); free_service(s->service); mdns_mem_free(s); } @@ -1530,10 +1524,10 @@ esp_err_t mdns_service_remove_all(void) esp_err_t mdns_lookup_delegated_service(const char *instance, const char *service, const char *proto, size_t max_results, mdns_result_t **result) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } - if (!result || _str_null_or_empty(service) || _str_null_or_empty(proto)) { + if (!result || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } mdns_priv_service_lock(); @@ -1545,10 +1539,10 @@ esp_err_t mdns_lookup_delegated_service(const char *instance, const char *servic esp_err_t mdns_lookup_selfhosted_service(const char *instance, const char *service, const char *proto, size_t max_results, mdns_result_t **result) { - if (!s_mdns_server) { + if (!s_server) { return ESP_ERR_INVALID_STATE; } - if (!result || _str_null_or_empty(service) || _str_null_or_empty(proto)) { + if (!result || mdns_utils_str_null_or_empty(service) || mdns_utils_str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } mdns_priv_service_lock(); diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index cbdfdd7024..fe0fa1fde0 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -34,15 +34,15 @@ static mdns_tx_packet_t *s_tx_queue_head; * * @return length of added data: 0 on error or 4 on success */ -static inline uint8_t _mdns_append_u32(uint8_t *packet, uint16_t *index, uint32_t value) +static inline uint8_t append_u32(uint8_t *packet, uint16_t *index, uint32_t value) { if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { return 0; } - _mdns_append_u8(packet, index, (value >> 24) & 0xFF); - _mdns_append_u8(packet, index, (value >> 16) & 0xFF); - _mdns_append_u8(packet, index, (value >> 8) & 0xFF); - _mdns_append_u8(packet, index, value & 0xFF); + mdns_utils_append_u8(packet, index, (value >> 24) & 0xFF); + mdns_utils_append_u8(packet, index, (value >> 16) & 0xFF); + mdns_utils_append_u8(packet, index, (value >> 8) & 0xFF); + mdns_utils_append_u8(packet, index, value & 0xFF); return 4; } @@ -56,7 +56,7 @@ static inline uint8_t _mdns_append_u32(uint8_t *packet, uint16_t *index, uint32_ * * @return length of added data: 0 on error or 10 on success */ -static inline uint8_t _mdns_append_type(uint8_t *packet, uint16_t *index, uint8_t type, bool flush, uint32_t ttl) +static inline uint8_t append_type(uint8_t *packet, uint16_t *index, uint8_t type, bool flush, uint32_t ttl) { if ((*index + 10) >= MDNS_MAX_PACKET_SIZE) { return 0; @@ -83,22 +83,11 @@ static inline uint8_t _mdns_append_type(uint8_t *packet, uint16_t *index, uint8_ } else { return 0; } - _mdns_append_u32(packet, index, ttl); + append_u32(packet, index, ttl); mdns_utils_append_u16(packet, index, 0); return 10; } -static inline uint8_t _mdns_append_string_with_len(uint8_t *packet, uint16_t *index, const char *string, uint8_t len) -{ - if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { - return 0; - } - _mdns_append_u8(packet, index, len); - memcpy(packet + *index, string, len); - *index += len; - return len + 1; -} - /** * @brief appends single string to a packet, incrementing the index * @@ -108,13 +97,13 @@ static inline uint8_t _mdns_append_string_with_len(uint8_t *packet, uint16_t *in * * @return length of added data: 0 on error or length of the string + 1 on success */ -static inline uint8_t _mdns_append_string(uint8_t *packet, uint16_t *index, const char *string) +static inline uint8_t append_string(uint8_t *packet, uint16_t *index, const char *string) { uint8_t len = strlen(string); if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { return 0; } - _mdns_append_u8(packet, index, len); + mdns_utils_append_u8(packet, index, len); memcpy(packet + *index, string, len); *index += len; return len + 1; @@ -130,7 +119,7 @@ int mdns_priv_append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { return 0; } - _mdns_append_u8(packet, index, len); + mdns_utils_append_u8(packet, index, len); memcpy(packet + *index, txt->key, key_len); if (txt->value) { packet[*index + key_len] = '='; @@ -140,8 +129,7 @@ int mdns_priv_append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns return len + 1; } - -static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char *strings[], uint8_t count, size_t packet_len); +static uint16_t append_fqdn(uint8_t *packet, uint16_t *index, const char *strings[], uint8_t count, size_t packet_len); /** * @brief sets uint16_t value in a packet @@ -150,7 +138,7 @@ static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char * * @param index offset of uint16_t value * @param value the value to set */ -static inline void _mdns_set_u16(uint8_t *packet, uint16_t index, uint16_t value) +static inline void set_u16(uint8_t *packet, uint16_t index, uint16_t value) { if ((index + 1) >= MDNS_MAX_PACKET_SIZE) { return; @@ -162,7 +150,7 @@ static inline void _mdns_set_u16(uint8_t *packet, uint16_t index, uint16_t value /** * @brief Allocate new packet for sending */ -mdns_tx_packet_t *_mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +mdns_tx_packet_t *mdns_priv_alloc_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_tx_packet_t *packet = (mdns_tx_packet_t *)mdns_mem_malloc(sizeof(mdns_tx_packet_t)); if (!packet) { @@ -193,7 +181,7 @@ mdns_tx_packet_t *_mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protoco * * @param packet the packet */ -void _mdns_free_tx_packet(mdns_tx_packet_t *packet) +void mdns_priv_free_tx_packet(mdns_tx_packet_t *packet) { if (!packet) { return; @@ -219,8 +207,8 @@ void _mdns_free_tx_packet(mdns_tx_packet_t *packet) /** * @brief Allocate new answer and add it to answer list (destination) */ -bool _mdns_alloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_service_t *service, - mdns_host_item_t *host, bool flush, bool bye) +bool mdns_priv_create_answer(mdns_out_answer_t **destination, uint16_t type, mdns_service_t *service, + mdns_host_item_t *host, bool flush, bool bye) { mdns_out_answer_t *d = *destination; while (d) { @@ -246,10 +234,10 @@ bool _mdns_alloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_ser return true; } -static mdns_host_item_t *mdns_get_host_item(const char *hostname) +static mdns_host_item_t *get_host_item(const char *hostname) { if (hostname == NULL || strcasecmp(hostname, mdns_priv_get_global_hostname()) == 0) { - return priv_get_self_host(); + return mdns_priv_get_self_host(); } mdns_host_item_t *host = mdns_priv_get_hosts(); while (host != NULL) { @@ -261,52 +249,56 @@ static mdns_host_item_t *mdns_get_host_item(const char *hostname) return NULL; } -static bool _mdns_create_answer_from_service(mdns_tx_packet_t *packet, mdns_service_t *service, +static bool create_answer_from_service(mdns_tx_packet_t *packet, mdns_service_t *service, mdns_parsed_question_t *question, bool shared, bool send_flush) { - mdns_host_item_t *host = mdns_get_host_item(service->hostname); - bool is_delegated = (host != priv_get_self_host()); + mdns_host_item_t *host = get_host_item(service->hostname); + bool is_delegated = (host != mdns_priv_get_self_host()); if (question->type == MDNS_TYPE_PTR || question->type == MDNS_TYPE_ANY) { // According to RFC6763-section12.1, for DNS-SD, SRV, TXT and all address records // should be included in additional records. - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service, NULL, false, false) || - !_mdns_alloc_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || - !_mdns_alloc_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false) || - !_mdns_alloc_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_A, service, host, send_flush, - false) || - !_mdns_alloc_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_AAAA, service, host, - send_flush, false)) { + if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_PTR, service, NULL, false, false) || + !mdns_priv_create_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_SRV, service, + NULL, send_flush, false) || + !mdns_priv_create_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_TXT, service, + NULL, send_flush, false) || + !mdns_priv_create_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_A, + service, host, send_flush, + false) || + !mdns_priv_create_answer((shared || is_delegated) ? &packet->additional : &packet->answers, + MDNS_TYPE_AAAA, service, host, + send_flush, false)) { return false; } } else if (question->type == MDNS_TYPE_SRV) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || - !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_A, service, host, send_flush, false) || - !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_AAAA, service, host, send_flush, false)) { + if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || + !mdns_priv_create_answer(&packet->additional, MDNS_TYPE_A, service, host, send_flush, false) || + !mdns_priv_create_answer(&packet->additional, MDNS_TYPE_AAAA, service, host, send_flush, false)) { return false; } } else if (question->type == MDNS_TYPE_TXT) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false)) { + if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false)) { return false; } } else if (question->type == MDNS_TYPE_SDPTR) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, service, NULL, false, false)) { + if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_SDPTR, service, NULL, false, false)) { return false; } } return true; } -static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t *packet, const char *hostname, bool send_flush) +static bool create_answer_from_hostname(mdns_tx_packet_t *packet, const char *hostname, bool send_flush) { - mdns_host_item_t *host = mdns_get_host_item(hostname); - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host, send_flush, false) || - !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, send_flush, false)) { + mdns_host_item_t *host = get_host_item(hostname); + if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_A, NULL, host, send_flush, false) || + !mdns_priv_create_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, send_flush, false)) { return false; } return true; } -static bool _mdns_service_match_ptr_question(const mdns_service_t *service, const mdns_parsed_question_t *question) +static bool service_match_ptr_question(const mdns_service_t *service, const mdns_parsed_question_t *question) { if (!mdns_utils_service_match(service, question->service, question->proto, NULL)) { return false; @@ -330,48 +322,48 @@ static bool _mdns_service_match_ptr_question(const mdns_service_t *service, cons } return true; } -static bool _mdns_append_host(mdns_out_answer_t **destination, mdns_host_item_t *host, bool flush, bool bye) +static bool append_host(mdns_out_answer_t **destination, mdns_host_item_t *host, bool flush, bool bye) { - if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { + if (!mdns_priv_create_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { return false; } - if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { + if (!mdns_priv_create_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { return false; } return true; } -bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], - size_t services_len, bool flush, bool bye) +bool mdns_priv_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], + size_t services_len, bool flush, bool bye) { if (services == NULL) { - mdns_host_item_t *host = mdns_get_host_item(mdns_priv_get_global_hostname()); + mdns_host_item_t *host = get_host_item(mdns_priv_get_global_hostname()); if (host != NULL) { - return _mdns_append_host(destination, host, flush, bye); + return append_host(destination, host, flush, bye); } return true; } for (size_t i = 0; i < services_len; i++) { - mdns_host_item_t *host = mdns_get_host_item(services[i]->service->hostname); - if (!_mdns_append_host(destination, host, flush, bye)) { + mdns_host_item_t *host = get_host_item(services[i]->service->hostname); + if (!append_host(destination, host, flush, bye)) { return false; } } return true; } -bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye) +static bool append_host_list(mdns_out_answer_t **destination, bool flush, bool bye) { if (!mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname())) { - mdns_host_item_t *self_host = mdns_get_host_item(mdns_priv_get_global_hostname()); - if (!_mdns_append_host(destination, self_host, flush, bye)) { + mdns_host_item_t *self_host = get_host_item(mdns_priv_get_global_hostname()); + if (!append_host(destination, self_host, flush, bye)) { return false; } } mdns_host_item_t *host = mdns_priv_get_hosts(); while (host != NULL) { host = host->next; - if (!_mdns_append_host(destination, host, flush, bye)) { + if (!append_host(destination, host, flush, bye)) { return false; } } @@ -381,7 +373,7 @@ bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool by /** * @brief Check if question is already in the list */ -static bool _mdns_question_exists(mdns_out_question_t *needle, mdns_out_question_t *haystack) +static bool question_exists(mdns_out_question_t *needle, mdns_out_question_t *haystack) { while (haystack) { if (haystack->type == needle->type @@ -395,7 +387,7 @@ static bool _mdns_question_exists(mdns_out_question_t *needle, mdns_out_question return false; } -static bool _mdns_append_host_question(mdns_out_question_t **questions, const char *hostname, bool unicast) +static bool append_host_question(mdns_out_question_t **questions, const char *hostname, bool unicast) { mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); if (!q) { @@ -410,7 +402,7 @@ static bool _mdns_append_host_question(mdns_out_question_t **questions, const ch q->proto = NULL; q->domain = MDNS_UTILS_DEFAULT_DOMAIN; q->own_dynamic_memory = false; - if (_mdns_question_exists(q, *questions)) { + if (question_exists(q, *questions)) { mdns_mem_free(q); } else { queueToEnd(mdns_out_question_t, *questions, q); @@ -418,15 +410,15 @@ static bool _mdns_append_host_question(mdns_out_question_t **questions, const ch return true; } -static bool _mdns_append_host_questions_for_services(mdns_out_question_t **questions, mdns_srv_item_t *services[], +static bool append_host_questions_for_services(mdns_out_question_t **questions, mdns_srv_item_t *services[], size_t len, bool unicast) { if (!mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname()) && - !_mdns_append_host_question(questions, mdns_priv_get_global_hostname(), unicast)) { + !append_host_question(questions, mdns_priv_get_global_hostname(), unicast)) { return false; } for (size_t i = 0; i < len; i++) { - if (!_mdns_append_host_question(questions, services[i]->service->hostname, unicast)) { + if (!append_host_question(questions, services[i]->service->hostname, unicast)) { return false; } } @@ -439,7 +431,7 @@ static inline int append_single_str(uint8_t *packet, uint16_t *index, const char if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { return 0; } - if (!_mdns_append_u8(packet, index, len)) { + if (!mdns_utils_append_u8(packet, index, len)) { return 0; } memcpy(packet + *index, str, len); @@ -449,7 +441,7 @@ static inline int append_single_str(uint8_t *packet, uint16_t *index, const char /** * @brief appends FQDN to a packet from hostname separated by dots. This API works the same way as - * _mdns_append_fqdn(), but refrains from DNS compression (as it's mainly used for IP addresses (many short items), + * append_fqdn(), but refrains from DNS compression (as it's mainly used for IP addresses (many short items), * where we gain very little (or compression even gets counter-productive mainly for IPv6 addresses) * * @param packet MDNS packet @@ -480,7 +472,7 @@ static uint16_t append_fqdn_dots(uint8_t *packet, uint16_t *index, const char *n } //empty string so terminate - if (!_mdns_append_u8(packet, index, 0)) { + if (!mdns_utils_append_u8(packet, index, 0)) { return 0; } return *index; @@ -489,7 +481,7 @@ static uint16_t append_fqdn_dots(uint8_t *packet, uint16_t *index, const char *n /** * @brief Appends reverse lookup PTR record */ -static uint8_t _mdns_append_reverse_ptr_record(uint8_t *packet, uint16_t *index, const char *name) +static uint8_t append_reverse_ptr_record(uint8_t *packet, uint16_t *index, const char *name) { if (strstr(name, "in-addr") == NULL && strstr(name, "ip6") == NULL) { return 0; @@ -506,12 +498,12 @@ static uint8_t _mdns_append_reverse_ptr_record(uint8_t *packet, uint16_t *index, uint16_t data_len_location = *index - 2; /* store the position of size (2=16bis) of this record */ const char *str[2] = {priv_get_self_host()->hostname, MDNS_UTILS_DEFAULT_DOMAIN }; - int part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + int part_length = append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } - _mdns_set_u16(packet, data_len_location, part_length); + set_u16(packet, data_len_location, part_length); return 1; /* appending only 1 record */ } #endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ @@ -524,7 +516,7 @@ void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_pac bool send_flush = parsed_packet->src_port == MDNS_SERVICE_PORT; bool unicast = false; bool shared = false; - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(parsed_packet->tcpip_if, parsed_packet->ip_protocol); + mdns_tx_packet_t *packet = mdns_priv_alloc_packet(parsed_packet->tcpip_if, parsed_packet->ip_protocol); if (!packet) { return; } @@ -542,8 +534,8 @@ void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_pac q = q->next; continue; } - if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { - _mdns_free_tx_packet(packet); + if (!create_answer_from_service(packet, service->service, q, shared, send_flush)) { + mdns_priv_free_tx_packet(packet); return; } else { out_record_nums++; @@ -551,7 +543,7 @@ void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_pac } else if (q->service && q->proto) { mdns_srv_item_t *service = mdns_priv_get_services(); while (service) { - if (_mdns_service_match_ptr_question(service->service, q)) { + if (service_match_ptr_question(service->service, q)) { mdns_parsed_record_t *r = parsed_packet->records; bool is_record_exist = false; while (r) { @@ -569,8 +561,8 @@ void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_pac r = r->next; } if (!is_record_exist) { - if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { - _mdns_free_tx_packet(packet); + if (!create_answer_from_service(packet, service->service, q, shared, send_flush)) { + mdns_priv_free_tx_packet(packet); return; } else { out_record_nums++; @@ -580,31 +572,32 @@ void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_pac service = service->next; } } else if (q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA) { - if (!_mdns_create_answer_from_hostname(packet, q->host, send_flush)) { - _mdns_free_tx_packet(packet); + if (!create_answer_from_hostname(packet, q->host, send_flush)) { + mdns_priv_free_tx_packet(packet); return; } else { out_record_nums++; } } else if (q->type == MDNS_TYPE_ANY) { - if (!_mdns_append_host_list(&packet->answers, send_flush, false)) { - _mdns_free_tx_packet(packet); + if (!append_host_list(&packet->answers, send_flush, false)) { + mdns_priv_free_tx_packet(packet); return; } else { out_record_nums++; } #ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES } else if (q->type == MDNS_TYPE_PTR) { - mdns_host_item_t *host = mdns_get_host_item(q->host); + mdns_host_item_t *host = get_host_item(q->host); +#error if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, NULL, host, send_flush, false)) { - _mdns_free_tx_packet(packet); + mdns_priv_free_tx_packet(packet); return; } else { out_record_nums++; } #endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ - } else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, NULL, send_flush, false)) { - _mdns_free_tx_packet(packet); + } else if (!mdns_priv_create_answer(&packet->answers, q->type, NULL, NULL, send_flush, false)) { + mdns_priv_free_tx_packet(packet); return; } else { out_record_nums++; @@ -619,7 +612,7 @@ void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_pac mdns_out_question_t *out_question = mdns_mem_malloc(sizeof(mdns_out_question_t)); if (out_question == NULL) { HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); + mdns_priv_free_tx_packet(packet); return; } out_question->type = q->type; @@ -642,7 +635,7 @@ void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_pac q = q->next; } if (out_record_nums == 0) { - _mdns_free_tx_packet(packet); + mdns_priv_free_tx_packet(packet); return; } if (unicast || !send_flush) { @@ -652,11 +645,11 @@ void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_pac static uint8_t share_step = 0; if (shared) { - mdns_send_schedule_tx_packet(packet, 25 + (share_step * 25)); + mdns_priv_send_after(packet, 25 + (share_step * 25)); share_step = (share_step + 1) & 0x03; } else { - _mdns_dispatch_tx_packet(packet); - _mdns_free_tx_packet(packet); + mdns_priv_dispatch_tx_packet(packet); + mdns_priv_free_tx_packet(packet); } } @@ -671,11 +664,11 @@ void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_pac * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char *strings[], uint8_t count, size_t packet_len) +static uint16_t append_fqdn(uint8_t *packet, uint16_t *index, const char *strings[], uint8_t count, size_t packet_len) { if (!count) { //empty string so terminate - return _mdns_append_u8(packet, index, 0); + return mdns_utils_append_u8(packet, index, 0); } static char buf[MDNS_NAME_BUF_LEN]; uint8_t len = strlen(strings[0]); @@ -720,12 +713,12 @@ static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char * } //string is not yet in the packet, so let's add it if (!len_location) { - uint8_t written = _mdns_append_string(packet, index, strings[0]); + uint8_t written = append_string(packet, index, strings[0]); if (!written) { return 0; } //run the same for the other strings in the name - return written + _mdns_append_fqdn(packet, index, &strings[1], count - 1, packet_len); + return written + append_fqdn(packet, index, &strings[1], count - 1, packet_len); } //we have found the string so let's insert a pointer to it instead @@ -738,7 +731,7 @@ static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char * /** * @brief Append question to packet */ -static uint16_t _mdns_append_question(uint8_t *packet, uint16_t *index, mdns_out_question_t *q) +static uint16_t append_question(uint8_t *packet, uint16_t *index, mdns_out_question_t *q) { uint8_t part_length; #ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES @@ -764,7 +757,7 @@ static uint16_t _mdns_append_question(uint8_t *packet, uint16_t *index, mdns_out if (q->domain) { str[str_index++] = q->domain; } - part_length = _mdns_append_fqdn(packet, index, str, str_index, MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, str, str_index, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -785,7 +778,7 @@ static uint16_t _mdns_append_question(uint8_t *packet, uint16_t *index, mdns_out * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, const char *service, const char *proto, bool flush, bool bye) +static uint16_t append_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, const char *service, const char *proto, bool flush, bool bye) { const char *str[4]; uint16_t record_length = 0; @@ -800,24 +793,24 @@ static uint16_t _mdns_append_ptr_record(uint8_t *packet, uint16_t *index, const str[2] = proto; str[3] = MDNS_UTILS_DEFAULT_DOMAIN; - part_length = _mdns_append_fqdn(packet, index, str + 1, 3, MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, str + 1, 3, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL); + part_length = append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL); if (!part_length) { return 0; } record_length += part_length; uint16_t data_len_location = *index - 2; - part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } - _mdns_set_u16(packet, data_len_location, part_length); + set_u16(packet, data_len_location, part_length); record_length += part_length; return record_length; } @@ -835,7 +828,7 @@ static uint16_t _mdns_append_ptr_record(uint8_t *packet, uint16_t *index, const * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_subtype_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, +static uint16_t append_subtype_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, const char *subtype, const char *service, const char *proto, bool flush, bool bye) { @@ -848,24 +841,24 @@ static uint16_t _mdns_append_subtype_ptr_record(uint8_t *packet, uint16_t *index return 0; } - part_length = _mdns_append_fqdn(packet, index, subtype_str, ARRAY_SIZE(subtype_str), MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, subtype_str, ARRAY_SIZE(subtype_str), MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL); + part_length = append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL); if (!part_length) { return 0; } record_length += part_length; uint16_t data_len_location = *index - 2; - part_length = _mdns_append_fqdn(packet, index, instance_str, ARRAY_SIZE(instance_str), MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, instance_str, ARRAY_SIZE(instance_str), MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } - _mdns_set_u16(packet, data_len_location, part_length); + set_u16(packet, data_len_location, part_length); record_length += part_length; return record_length; } @@ -874,12 +867,12 @@ static uint16_t _mdns_append_subtype_ptr_record(uint8_t *packet, uint16_t *index * * @return number of answers added to the packet */ -static uint8_t _mdns_append_service_ptr_answers(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, +static uint8_t append_service_ptr_answers(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) { uint8_t appended_answers = 0; - if (_mdns_append_ptr_record(packet, index, mdns_utils_get_service_instance_name(service), service->service, + if (append_ptr_record(packet, index, mdns_utils_get_service_instance_name(service), service->service, service->proto, flush, bye) <= 0) { return appended_answers; } @@ -888,7 +881,7 @@ static uint8_t _mdns_append_service_ptr_answers(uint8_t *packet, uint16_t *index mdns_subtype_t *subtype = service->subtype; while (subtype) { appended_answers += - (_mdns_append_subtype_ptr_record(packet, index, mdns_utils_get_service_instance_name(service), subtype->subtype, + (append_subtype_ptr_record(packet, index, mdns_utils_get_service_instance_name(service), subtype->subtype, service->service, service->proto, flush, bye) > 0); subtype = subtype->next; } @@ -906,7 +899,7 @@ static uint8_t _mdns_append_service_ptr_answers(uint8_t *packet, uint16_t *index * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_srv_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) +static uint16_t append_srv_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) { const char *str[4]; uint16_t record_length = 0; @@ -925,13 +918,13 @@ static uint16_t _mdns_append_srv_record(uint8_t *packet, uint16_t *index, mdns_s return 0; } - part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_SRV, flush, bye ? 0 : MDNS_ANSWER_SRV_TTL); + part_length = append_type(packet, index, MDNS_ANSWER_SRV, flush, bye ? 0 : MDNS_ANSWER_SRV_TTL); if (!part_length) { return 0; } @@ -958,11 +951,11 @@ static uint16_t _mdns_append_srv_record(uint8_t *packet, uint16_t *index, mdns_s return 0; } - part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } - _mdns_set_u16(packet, data_len_location, part_length + 6); + set_u16(packet, data_len_location, part_length + 6); record_length += part_length + 6; return record_length; @@ -978,7 +971,7 @@ static uint16_t _mdns_append_srv_record(uint8_t *packet, uint16_t *index, mdns_s * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_txt_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) +static uint16_t append_txt_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) { const char *str[4]; uint16_t record_length = 0; @@ -997,13 +990,13 @@ static uint16_t _mdns_append_txt_record(uint8_t *packet, uint16_t *index, mdns_s return 0; } - part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_TXT, flush, bye ? 0 : MDNS_ANSWER_TXT_TTL); + part_length = append_type(packet, index, MDNS_ANSWER_TXT, flush, bye ? 0 : MDNS_ANSWER_TXT_TTL); if (!part_length) { return 0; } @@ -1027,7 +1020,7 @@ static uint16_t _mdns_append_txt_record(uint8_t *packet, uint16_t *index, mdns_s packet[*index] = 0; *index = *index + 1; } - _mdns_set_u16(packet, data_len_location, data_len); + set_u16(packet, data_len_location, data_len); record_length += data_len; return record_length; } @@ -1042,7 +1035,7 @@ static uint16_t _mdns_append_txt_record(uint8_t *packet, uint16_t *index, mdns_s * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_sdptr_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) +static uint16_t append_sdptr_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) { const char *str[3]; const char *sd_str[4]; @@ -1062,22 +1055,22 @@ static uint16_t _mdns_append_sdptr_record(uint8_t *packet, uint16_t *index, mdns str[1] = service->proto; str[2] = MDNS_UTILS_DEFAULT_DOMAIN; - part_length = _mdns_append_fqdn(packet, index, sd_str, 4, MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, sd_str, 4, MDNS_MAX_PACKET_SIZE); record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, flush, MDNS_ANSWER_PTR_TTL); + part_length = append_type(packet, index, MDNS_ANSWER_PTR, flush, MDNS_ANSWER_PTR_TTL); if (!part_length) { return 0; } record_length += part_length; uint16_t data_len_location = *index - 2; - part_length = _mdns_append_fqdn(packet, index, str, 3, MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, str, 3, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } - _mdns_set_u16(packet, data_len_location, part_length); + set_u16(packet, data_len_location, part_length); record_length += part_length; return record_length; } @@ -1093,7 +1086,7 @@ static uint16_t _mdns_append_sdptr_record(uint8_t *packet, uint16_t *index, mdns * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_a_record(uint8_t *packet, uint16_t *index, const char *hostname, uint32_t ip, bool flush, bool bye) +static uint16_t append_a_record(uint8_t *packet, uint16_t *index, const char *hostname, uint32_t ip, bool flush, bool bye) { const char *str[2]; uint16_t record_length = 0; @@ -1106,13 +1099,13 @@ static uint16_t _mdns_append_a_record(uint8_t *packet, uint16_t *index, const ch return 0; } - part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_A, flush, bye ? 0 : MDNS_ANSWER_A_TTL); + part_length = append_type(packet, index, MDNS_ANSWER_A, flush, bye ? 0 : MDNS_ANSWER_A_TTL); if (!part_length) { return 0; } @@ -1123,11 +1116,11 @@ static uint16_t _mdns_append_a_record(uint8_t *packet, uint16_t *index, const ch if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { return 0; } - _mdns_append_u8(packet, index, ip & 0xFF); - _mdns_append_u8(packet, index, (ip >> 8) & 0xFF); - _mdns_append_u8(packet, index, (ip >> 16) & 0xFF); - _mdns_append_u8(packet, index, (ip >> 24) & 0xFF); - _mdns_set_u16(packet, data_len_location, 4); + mdns_utils_append_u8(packet, index, ip & 0xFF); + mdns_utils_append_u8(packet, index, (ip >> 8) & 0xFF); + mdns_utils_append_u8(packet, index, (ip >> 16) & 0xFF); + mdns_utils_append_u8(packet, index, (ip >> 24) & 0xFF); + set_u16(packet, data_len_location, 4); record_length += 4; return record_length; @@ -1145,7 +1138,7 @@ static uint16_t _mdns_append_a_record(uint8_t *packet, uint16_t *index, const ch * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_aaaa_record(uint8_t *packet, uint16_t *index, const char *hostname, uint8_t *ipv6, bool flush, bool bye) +static uint16_t append_aaaa_record(uint8_t *packet, uint16_t *index, const char *hostname, uint8_t *ipv6, bool flush, bool bye) { const char *str[2]; uint16_t record_length = 0; @@ -1159,13 +1152,13 @@ static uint16_t _mdns_append_aaaa_record(uint8_t *packet, uint16_t *index, const } - part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + part_length = append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_AAAA, flush, bye ? 0 : MDNS_ANSWER_AAAA_TTL); + part_length = append_type(packet, index, MDNS_ANSWER_AAAA, flush, bye ? 0 : MDNS_ANSWER_AAAA_TTL); if (!part_length) { return 0; } @@ -1180,13 +1173,13 @@ static uint16_t _mdns_append_aaaa_record(uint8_t *packet, uint16_t *index, const part_length = MDNS_ANSWER_AAAA_SIZE; memcpy(packet + *index, ipv6, part_length); *index += part_length; - _mdns_set_u16(packet, data_len_location, part_length); + set_u16(packet, data_len_location, part_length); record_length += part_length; return record_length; } #endif -static uint8_t _mdns_append_host_answer(uint8_t *packet, uint16_t *index, mdns_host_item_t *host, +static uint8_t append_host_answer(uint8_t *packet, uint16_t *index, mdns_host_item_t *host, uint8_t address_type, bool flush, bool bye) { mdns_ip_addr_t *addr = host->address_list; @@ -1196,13 +1189,13 @@ static uint8_t _mdns_append_host_answer(uint8_t *packet, uint16_t *index, mdns_h if (addr->addr.type == address_type) { #ifdef CONFIG_LWIP_IPV4 if (address_type == ESP_IPADDR_TYPE_V4 && - _mdns_append_a_record(packet, index, host->hostname, addr->addr.u_addr.ip4.addr, flush, bye) <= 0) { + append_a_record(packet, index, host->hostname, addr->addr.u_addr.ip4.addr, flush, bye) <= 0) { break; } #endif /* CONFIG_LWIP_IPV4 */ #ifdef CONFIG_LWIP_IPV6 if (address_type == ESP_IPADDR_TYPE_V6 && - _mdns_append_aaaa_record(packet, index, host->hostname, (uint8_t *)addr->addr.u_addr.ip6.addr, flush, + append_aaaa_record(packet, index, host->hostname, (uint8_t *)addr->addr.u_addr.ip6.addr, flush, bye) <= 0) { break; } @@ -1219,10 +1212,10 @@ static uint8_t _mdns_append_host_answer(uint8_t *packet, uint16_t *index, mdns_h * * @return number of answers added to the packet */ -static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_answer_t *answer, mdns_if_t tcpip_if) +static uint8_t append_answer(uint8_t *packet, uint16_t *index, mdns_out_answer_t *answer, mdns_if_t tcpip_if) { if (answer->host) { - bool is_host_valid = (priv_get_self_host() == answer->host); + bool is_host_valid = (mdns_priv_get_self_host() == answer->host); mdns_host_item_t *target_host = mdns_priv_get_hosts(); while (target_host && !is_host_valid) { if (target_host == answer->host) { @@ -1237,27 +1230,27 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an if (answer->type == MDNS_TYPE_PTR) { if (answer->service) { - return _mdns_append_service_ptr_answers(packet, index, answer->service, answer->flush, answer->bye); + return append_service_ptr_answers(packet, index, answer->service, answer->flush, answer->bye); #ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES } else if (answer->host && answer->host->hostname && (strstr(answer->host->hostname, "in-addr") || strstr(answer->host->hostname, "ip6"))) { - return _mdns_append_reverse_ptr_record(packet, index, answer->host->hostname) > 0; + return append_reverse_ptr_record(packet, index, answer->host->hostname) > 0; #endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ } else { - return _mdns_append_ptr_record(packet, index, + return append_ptr_record(packet, index, answer->custom_instance, answer->custom_service, answer->custom_proto, answer->flush, answer->bye) > 0; } } else if (answer->type == MDNS_TYPE_SRV) { - return _mdns_append_srv_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + return append_srv_record(packet, index, answer->service, answer->flush, answer->bye) > 0; } else if (answer->type == MDNS_TYPE_TXT) { - return _mdns_append_txt_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + return append_txt_record(packet, index, answer->service, answer->flush, answer->bye) > 0; } else if (answer->type == MDNS_TYPE_SDPTR) { - return _mdns_append_sdptr_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + return append_sdptr_record(packet, index, answer->service, answer->flush, answer->bye) > 0; } #ifdef CONFIG_LWIP_IPV4 else if (answer->type == MDNS_TYPE_A) { - if (answer->host == priv_get_self_host()) { + if (answer->host == mdns_priv_get_self_host()) { esp_netif_ip_info_t if_ip_info; if (!mdns_priv_if_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && !mdns_priv_pcb_is_duplicate(tcpip_if, MDNS_IP_PROTOCOL_V4)) { @@ -1266,7 +1259,7 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an if (esp_netif_get_ip_info(mdns_priv_get_esp_netif(tcpip_if), &if_ip_info)) { return 0; } - if (_mdns_append_a_record(packet, index, mdns_priv_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { + if (append_a_record(packet, index, mdns_priv_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { return 0; } if (!mdns_priv_pcb_check_for_duplicates(tcpip_if)) { @@ -1276,18 +1269,18 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an if (esp_netif_get_ip_info(mdns_priv_get_esp_netif(other_if), &if_ip_info)) { return 1; } - if (_mdns_append_a_record(packet, index, mdns_priv_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { + if (append_a_record(packet, index, mdns_priv_get_global_hostname(), if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { return 2; } return 1; } else if (answer->host != NULL) { - return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V4, answer->flush, answer->bye); + return append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V4, answer->flush, answer->bye); } } #endif /* CONFIG_LWIP_IPV4 */ #ifdef CONFIG_LWIP_IPV6 else if (answer->type == MDNS_TYPE_AAAA) { - if (answer->host == priv_get_self_host()) { + if (answer->host == mdns_priv_get_self_host()) { struct esp_ip6_addr if_ip6s[NETIF_IPV6_MAX_NUMS]; uint8_t count = 0; if (!mdns_priv_if_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && !mdns_priv_pcb_is_duplicate(tcpip_if, @@ -1300,7 +1293,7 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an if (mdns_utils_ipv6_address_is_zero(if_ip6s[i])) { return 0; } - if (_mdns_append_aaaa_record(packet, index, mdns_priv_get_global_hostname(), (uint8_t *)if_ip6s[i].addr, + if (append_aaaa_record(packet, index, mdns_priv_get_global_hostname(), (uint8_t *)if_ip6s[i].addr, answer->flush, answer->bye) <= 0) { return 0; } @@ -1314,13 +1307,13 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an if (esp_netif_get_ip6_linklocal(mdns_priv_get_esp_netif(other_if), &other_ip6)) { return count; } - if (_mdns_append_aaaa_record(packet, index, mdns_priv_get_global_hostname(), (uint8_t *)other_ip6.addr, + if (append_aaaa_record(packet, index, mdns_priv_get_global_hostname(), (uint8_t *)other_ip6.addr, answer->flush, answer->bye) > 0) { return 1 + count; } return count; } else if (answer->host != NULL) { - return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V6, answer->flush, + return append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V6, answer->flush, answer->bye); } } @@ -1333,7 +1326,7 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an * * @param p the packet */ -void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p) +void mdns_priv_dispatch_tx_packet(mdns_tx_packet_t *p) { static uint8_t packet[MDNS_MAX_PACKET_SIZE]; uint16_t index = MDNS_HEAD_LEN; @@ -1342,58 +1335,54 @@ void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p) mdns_out_answer_t *a; uint8_t count; - _mdns_set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, p->flags); - _mdns_set_u16(packet, MDNS_HEAD_ID_OFFSET, p->id); + set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, p->flags); + set_u16(packet, MDNS_HEAD_ID_OFFSET, p->id); count = 0; q = p->questions; while (q) { - if (_mdns_append_question(packet, &index, q)) { + if (append_question(packet, &index, q)) { count++; } q = q->next; } - _mdns_set_u16(packet, MDNS_HEAD_QUESTIONS_OFFSET, count); + set_u16(packet, MDNS_HEAD_QUESTIONS_OFFSET, count); count = 0; a = p->answers; while (a) { - count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + count += append_answer(packet, &index, a, p->tcpip_if); a = a->next; } - _mdns_set_u16(packet, MDNS_HEAD_ANSWERS_OFFSET, count); + set_u16(packet, MDNS_HEAD_ANSWERS_OFFSET, count); count = 0; a = p->servers; while (a) { - count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + count += append_answer(packet, &index, a, p->tcpip_if); a = a->next; } - _mdns_set_u16(packet, MDNS_HEAD_SERVERS_OFFSET, count); + set_u16(packet, MDNS_HEAD_SERVERS_OFFSET, count); count = 0; a = p->additional; while (a) { - count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + count += append_answer(packet, &index, a, p->tcpip_if); a = a->next; } - _mdns_set_u16(packet, MDNS_HEAD_ADDITIONAL_OFFSET, count); + set_u16(packet, MDNS_HEAD_ADDITIONAL_OFFSET, count); DBG_TX_PACKET(p, packet, index); mdns_priv_if_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); } - - - - /** * @brief Create probe packet for particular services on particular PCB */ -mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool first, bool include_ip) +mdns_tx_packet_t *mdns_priv_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool first, bool include_ip) { - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + mdns_tx_packet_t *packet = mdns_priv_alloc_packet(tcpip_if, ip_protocol); if (!packet) { return NULL; } @@ -1403,7 +1392,7 @@ mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); if (!q) { HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); + mdns_priv_free_tx_packet(packet); return NULL; } q->next = NULL; @@ -1414,27 +1403,28 @@ mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol q->proto = services[i]->service->proto; q->domain = MDNS_UTILS_DEFAULT_DOMAIN; q->own_dynamic_memory = false; - if (!q->host || _mdns_question_exists(q, packet->questions)) { + if (!q->host || question_exists(q, packet->questions)) { mdns_mem_free(q); continue; } else { queueToEnd(mdns_out_question_t, packet->questions, q); } - if (!q->host || !_mdns_alloc_answer(&packet->servers, MDNS_TYPE_SRV, services[i]->service, NULL, false, false)) { - _mdns_free_tx_packet(packet); + if (!q->host || !mdns_priv_create_answer(&packet->servers, MDNS_TYPE_SRV, services[i]->service, NULL, false, + false)) { + mdns_priv_free_tx_packet(packet); return NULL; } } if (include_ip) { - if (!_mdns_append_host_questions_for_services(&packet->questions, services, len, first)) { - _mdns_free_tx_packet(packet); + if (!append_host_questions_for_services(&packet->questions, services, len, first)) { + mdns_priv_free_tx_packet(packet); return NULL; } - if (!_mdns_append_host_list_in_services(&packet->servers, services, len, false, false)) { - _mdns_free_tx_packet(packet); + if (!mdns_priv_append_host_list_in_services(&packet->servers, services, len, false, false)) { + mdns_priv_free_tx_packet(packet); return NULL; } } @@ -1445,9 +1435,9 @@ mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol /** * @brief Create announce packet for particular services on particular PCB */ -mdns_tx_packet_t *_mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool include_ip) +mdns_tx_packet_t *mdns_priv_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool include_ip) { - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + mdns_tx_packet_t *packet = mdns_priv_alloc_packet(tcpip_if, ip_protocol); if (!packet) { return NULL; } @@ -1455,17 +1445,17 @@ mdns_tx_packet_t *_mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_proto uint8_t i; for (i = 0; i < len; i++) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, false)) { - _mdns_free_tx_packet(packet); + if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) + || !mdns_priv_create_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, false) + || !mdns_priv_create_answer(&packet->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, false) + || !mdns_priv_create_answer(&packet->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, false)) { + mdns_priv_free_tx_packet(packet); return NULL; } } if (include_ip) { - if (!_mdns_append_host_list_in_services(&packet->servers, services, len, true, false)) { - _mdns_free_tx_packet(packet); + if (!mdns_priv_append_host_list_in_services(&packet->servers, services, len, true, false)) { + mdns_priv_free_tx_packet(packet); return NULL; } } @@ -1475,9 +1465,9 @@ mdns_tx_packet_t *_mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_proto /** * @brief Convert probe packet to announce */ -mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *probe) +mdns_tx_packet_t *mdns_priv_create_announce_from_probe(mdns_tx_packet_t *probe) { - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(probe->tcpip_if, probe->ip_protocol); + mdns_tx_packet_t *packet = mdns_priv_alloc_packet(probe->tcpip_if, probe->ip_protocol); if (!packet) { return NULL; } @@ -1486,23 +1476,23 @@ mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *probe) mdns_out_answer_t *s = probe->servers; while (s) { if (s->type == MDNS_TYPE_SRV) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, s->service, NULL, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, s->service, NULL, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, s->service, NULL, true, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, s->service, NULL, true, false)) { - _mdns_free_tx_packet(packet); + if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_SDPTR, s->service, NULL, false, false) + || !mdns_priv_create_answer(&packet->answers, MDNS_TYPE_PTR, s->service, NULL, false, false) + || !mdns_priv_create_answer(&packet->answers, MDNS_TYPE_SRV, s->service, NULL, true, false) + || !mdns_priv_create_answer(&packet->answers, MDNS_TYPE_TXT, s->service, NULL, true, false)) { + mdns_priv_free_tx_packet(packet); return NULL; } - mdns_host_item_t *host = mdns_get_host_item(s->service->hostname); - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host, true, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, true, false)) { - _mdns_free_tx_packet(packet); + mdns_host_item_t *host = get_host_item(s->service->hostname); + if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_A, NULL, host, true, false) + || !mdns_priv_create_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, true, false)) { + mdns_priv_free_tx_packet(packet); return NULL; } } else if (s->type == MDNS_TYPE_A || s->type == MDNS_TYPE_AAAA) { - if (!_mdns_alloc_answer(&packet->answers, s->type, NULL, s->host, true, false)) { - _mdns_free_tx_packet(packet); + if (!mdns_priv_create_answer(&packet->answers, s->type, NULL, s->host, true, false)) { + mdns_priv_free_tx_packet(packet); return NULL; } } @@ -1512,43 +1502,43 @@ mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *probe) return packet; } -void mdns_send_bye_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) +void mdns_priv_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) { - mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + mdns_tx_packet_t *packet = mdns_priv_alloc_packet(tcpip_if, ip_protocol); if (!packet) { return; } packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; size_t i; for (i = 0; i < len; i++) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, true, true)) { - _mdns_free_tx_packet(packet); + if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, true, true)) { + mdns_priv_free_tx_packet(packet); return; } } if (include_ip) { - _mdns_append_host_list_in_services(&packet->answers, services, len, true, true); + mdns_priv_append_host_list_in_services(&packet->answers, services, len, true, true); } - _mdns_dispatch_tx_packet(packet); - _mdns_free_tx_packet(packet); + mdns_priv_dispatch_tx_packet(packet); + mdns_priv_free_tx_packet(packet); } /** * @brief Send bye for particular subtypes */ -void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, mdns_subtype_t *remove_subtypes) +void mdns_priv_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, mdns_subtype_t *remove_subtypes) { uint8_t i, j; for (i = 0; i < MDNS_MAX_INTERFACES; i++) { for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { if (mdns_priv_if_ready(i, j)) { - mdns_tx_packet_t *packet = _mdns_alloc_packet_default((mdns_if_t)i, (mdns_ip_protocol_t)j); + mdns_tx_packet_t *packet = mdns_priv_alloc_packet((mdns_if_t) i, (mdns_ip_protocol_t) j); if (packet == NULL) { return; } packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service->service, NULL, true, true)) { - _mdns_free_tx_packet(packet); + if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_PTR, service->service, NULL, true, true)) { + mdns_priv_free_tx_packet(packet); return; } @@ -1558,8 +1548,8 @@ void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, mdns_out_answer_t *a; uint8_t count; - _mdns_set_u16(pkt, MDNS_HEAD_FLAGS_OFFSET, packet->flags); - _mdns_set_u16(pkt, MDNS_HEAD_ID_OFFSET, packet->id); + set_u16(pkt, MDNS_HEAD_FLAGS_OFFSET, packet->flags); + set_u16(pkt, MDNS_HEAD_ID_OFFSET, packet->id); count = 0; a = packet->answers; @@ -1567,17 +1557,17 @@ void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, if (a->type == MDNS_TYPE_PTR && a->service) { const mdns_subtype_t *current_subtype = remove_subtypes; while (current_subtype) { - count += (_mdns_append_subtype_ptr_record(pkt, &index, instance_name, current_subtype->subtype, a->service->service, a->service->proto, a->flush, a->bye) > 0); + count += (append_subtype_ptr_record(pkt, &index, instance_name, current_subtype->subtype, a->service->service, a->service->proto, a->flush, a->bye) > 0); current_subtype = current_subtype->next; } } a = a->next; } - _mdns_set_u16(pkt, MDNS_HEAD_ANSWERS_OFFSET, count); + set_u16(pkt, MDNS_HEAD_ANSWERS_OFFSET, count); mdns_priv_if_write(packet->tcpip_if, packet->ip_protocol, &packet->dst, packet->port, pkt, index); - _mdns_free_tx_packet(packet); + mdns_priv_free_tx_packet(packet); } } } @@ -1586,7 +1576,7 @@ void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, /** * @brief Find, remove and free answer from the scheduled packets */ -void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service) +void mdns_priv_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service) { mdns_srv_item_t s = {NULL, NULL}; if (!service) { @@ -1624,7 +1614,7 @@ void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_pro * @param packet the packet * @param ms_after number of milliseconds after which the packet should be dispatched */ -void mdns_send_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after) +void mdns_priv_send_after(mdns_tx_packet_t *packet, uint32_t ms_after) { if (!packet) { return; @@ -1647,13 +1637,13 @@ void mdns_send_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after) /** * @brief free all packets scheduled for sending */ -void _mdns_clear_tx_queue_head(void) +void mdns_priv_clear_tx_queue(void) { mdns_tx_packet_t *q; while (s_tx_queue_head) { q = s_tx_queue_head; s_tx_queue_head = s_tx_queue_head->next; - _mdns_free_tx_packet(q); + mdns_priv_free_tx_packet(q); } } @@ -1663,13 +1653,13 @@ void _mdns_clear_tx_queue_head(void) * @param tcpip_if the interface * @param ip_protocol pcb type V4/V6 */ -void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +void mdns_priv_clear_tx_queue_if(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_tx_packet_t *q, * p; while (s_tx_queue_head && s_tx_queue_head->tcpip_if == tcpip_if && s_tx_queue_head->ip_protocol == ip_protocol) { q = s_tx_queue_head; s_tx_queue_head = s_tx_queue_head->next; - _mdns_free_tx_packet(q); + mdns_priv_free_tx_packet(q); } if (s_tx_queue_head) { q = s_tx_queue_head; @@ -1677,7 +1667,7 @@ void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_pro if (q->next->tcpip_if == tcpip_if && q->next->ip_protocol == ip_protocol) { p = q->next; q->next = p->next; - _mdns_free_tx_packet(p); + mdns_priv_free_tx_packet(p); } else { q = q->next; } @@ -1691,7 +1681,7 @@ void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_pro * @param tcpip_if the interface * @param ip_protocol pcb type V4/V6 */ -mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +mdns_tx_packet_t *mdns_priv_get_next_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_tx_packet_t *q = s_tx_queue_head; while (q) { @@ -1710,7 +1700,7 @@ mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol * if it is scheduled to be transmitted, then pushes the packet to action queue to be handled. * */ -void mdns_send_packets(void) +void mdns_priv_send_packets(void) { mdns_priv_service_lock(); mdns_tx_packet_t *p = s_tx_queue_head; @@ -1749,7 +1739,7 @@ void mdns_send_packets(void) /** * @brief Remove and free service answer from answer list (destination) */ -static void _mdns_dealloc_scheduled_service_answers(mdns_out_answer_t **destination, mdns_service_t *service) +static void dealloc_scheduled_service_answers(mdns_out_answer_t **destination, mdns_service_t *service) { mdns_out_answer_t *d = *destination; if (!d) { @@ -1774,7 +1764,7 @@ static void _mdns_dealloc_scheduled_service_answers(mdns_out_answer_t **destinat /** * @brief Find, remove and free answers and scheduled packets for service */ -void _mdns_remove_scheduled_service_packets(mdns_service_t *service) +void mdns_priv_remove_scheduled_service_packets(mdns_service_t *service) { if (!service) { return; @@ -1784,9 +1774,9 @@ void _mdns_remove_scheduled_service_packets(mdns_service_t *service) while (q) { bool had_answers = (q->answers != NULL); - _mdns_dealloc_scheduled_service_answers(&(q->answers), service); - _mdns_dealloc_scheduled_service_answers(&(q->additional), service); - _mdns_dealloc_scheduled_service_answers(&(q->servers), service); + dealloc_scheduled_service_answers(&(q->answers), service); + dealloc_scheduled_service_answers(&(q->additional), service); + dealloc_scheduled_service_answers(&(q->servers), service); if (mdns_priv_if_ready(q->tcpip_if, q->ip_protocol)) { bool should_remove_questions = false; @@ -1818,29 +1808,29 @@ void _mdns_remove_scheduled_service_packets(mdns_service_t *service) q = q->next; if (!p->questions && !p->answers && !p->additional && !p->servers) { queueDetach(mdns_tx_packet_t, s_tx_queue_head, p); - _mdns_free_tx_packet(p); + mdns_priv_free_tx_packet(p); } } } -static void _mdns_tx_handle_packet(mdns_tx_packet_t *p) +static void handle_packet(mdns_tx_packet_t *p) { if (mdns_priv_pcb_is_off(p->tcpip_if, p->ip_protocol)) { - _mdns_free_tx_packet(p); + mdns_priv_free_tx_packet(p); return; } - _mdns_dispatch_tx_packet(p); + mdns_priv_dispatch_tx_packet(p); mdns_priv_pcb_schedule_tx_packet(p); } -static void mdns_send_handle_tx_packet(mdns_tx_packet_t *packet) +static void send_packet(mdns_tx_packet_t *packet) { mdns_tx_packet_t *p = s_tx_queue_head; // packet to be handled should be at tx head, but must be consistent with the one pushed to action queue if (p && p == packet && p->queued) { p->queued = false; // clearing, as the packet might be reused (pushed and transmitted again) s_tx_queue_head = p->next; - _mdns_tx_handle_packet(p); + handle_packet(p); } else { ESP_LOGD(TAG, "Skipping transmit of an unexpected packet!"); } @@ -1849,7 +1839,7 @@ static void mdns_send_handle_tx_packet(mdns_tx_packet_t *packet) /** * @brief Remove and free answer from answer list (destination) */ -void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service) +void mdns_priv_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service) { mdns_out_answer_t *d = *destination; if (!d) { @@ -1875,14 +1865,14 @@ void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_s } } -void mdns_send_action(mdns_action_t *action, mdns_action_subtype_t type) +void mdns_priv_send_action(mdns_action_t *action, mdns_action_subtype_t type) { if (action->type != ACTION_TX_HANDLE) { abort(); } if (type == ACTION_RUN) { - mdns_send_handle_tx_packet(action->data.tx_handle.packet); + send_packet(action->data.tx_handle.packet); } else if (type == ACTION_CLEANUP) { - _mdns_free_tx_packet(action->data.tx_handle.packet); + mdns_priv_free_tx_packet(action->data.tx_handle.packet); } } diff --git a/components/mdns/mdns_service.c b/components/mdns/mdns_service.c index bd2b8773d5..0ef939268c 100644 --- a/components/mdns/mdns_service.c +++ b/components/mdns/mdns_service.c @@ -131,7 +131,7 @@ static void _mdns_free_action(mdns_action_t *action) mdns_priv_browse_action(action, ACTION_CLEANUP); break; case ACTION_TX_HANDLE: - mdns_send_action(action, ACTION_CLEANUP); + mdns_priv_send_action(action, ACTION_CLEANUP); break; case ACTION_RX_HANDLE: mdns_priv_receive_action(action, ACTION_CLEANUP); @@ -170,7 +170,7 @@ static void _mdns_execute_action(mdns_action_t *action) break; case ACTION_TX_HANDLE: - mdns_send_action(action, ACTION_RUN); + mdns_priv_send_action(action, ACTION_RUN); break; case ACTION_RX_HANDLE: mdns_priv_receive_action(action, ACTION_RUN); @@ -215,7 +215,7 @@ static void _mdns_service_task(void *pvParameters) static void _mdns_timer_cb(void *arg) { - mdns_send_packets(); + mdns_priv_send_packets(); mdns_priv_query_start_stop(); } @@ -402,7 +402,7 @@ void mdns_free(void) } vQueueDelete(s_action_queue); } - _mdns_clear_tx_queue_head(); + mdns_priv_clear_tx_queue(); mdns_priv_query_free(); mdns_priv_browse_free(); mdns_priv_responder_free(); diff --git a/components/mdns/mdns_utils.c b/components/mdns/mdns_utils.c index 0017a0c7f8..c1f33bf268 100644 --- a/components/mdns/mdns_utils.c +++ b/components/mdns/mdns_utils.c @@ -261,7 +261,7 @@ uint8_t mdns_utils_append_u16(uint8_t *packet, uint16_t *index, uint16_t value) if ((*index + 1) >= MDNS_MAX_PACKET_SIZE) { return 0; } - _mdns_append_u8(packet, index, (value >> 8) & 0xFF); - _mdns_append_u8(packet, index, value & 0xFF); + mdns_utils_append_u8(packet, index, (value >> 8) & 0xFF); + mdns_utils_append_u8(packet, index, value & 0xFF); return 2; } diff --git a/components/mdns/private_include/mdns_browser.h b/components/mdns/private_include/mdns_browser.h index 3bf5ef2313..30b7f7ac28 100644 --- a/components/mdns/private_include/mdns_browser.h +++ b/components/mdns/private_include/mdns_browser.h @@ -36,6 +36,14 @@ mdns_browse_t *mdns_priv_browse_find(mdns_name_t *name, uint16_t type, mdns_if_t */ void mdns_priv_browse_send_all(mdns_if_t mdns_if); +/** + * @brief Sync browse results + * + * @note Called from the packet parser + * @note Calls mdns_priv_queue_action() from mdns_engine + */ +esp_err_t mdns_priv_browse_sync(mdns_browse_sync_t *browse_sync); + /** * @brief Perform action from mdns service queue * diff --git a/components/mdns/private_include/mdns_responder.h b/components/mdns/private_include/mdns_responder.h index 15f142c6ea..d81adb5590 100644 --- a/components/mdns/private_include/mdns_responder.h +++ b/components/mdns/private_include/mdns_responder.h @@ -47,7 +47,7 @@ mdns_host_item_t *mdns_priv_get_hosts(void); /** * @brief get self host */ -mdns_host_item_t *priv_get_self_host(void); +mdns_host_item_t *mdns_priv_get_self_host(void); /** * @brief set global hostname diff --git a/components/mdns/private_include/mdns_send.h b/components/mdns/private_include/mdns_send.h index 47fcee4f64..43fa91687f 100644 --- a/components/mdns/private_include/mdns_send.h +++ b/components/mdns/private_include/mdns_send.h @@ -15,98 +15,98 @@ extern "C" { /** * @brief Free a transmit packet and its associated resources */ -void _mdns_free_tx_packet(mdns_tx_packet_t *packet); +void mdns_priv_free_tx_packet(mdns_tx_packet_t *packet); /** * @brief Create a probe packet for service discovery */ -mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool first, bool include_ip); +mdns_tx_packet_t *mdns_priv_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool first, bool include_ip); /** * @brief Allocate and initialize an answer record for mDNS response */ -bool _mdns_alloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_service_t *service, - mdns_host_item_t *host, bool flush, bool bye); +bool mdns_priv_create_answer(mdns_out_answer_t **destination, uint16_t type, mdns_service_t *service, + mdns_host_item_t *host, bool flush, bool bye); /** * @brief Create an announcement packet for service advertisement */ -mdns_tx_packet_t *_mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool include_ip); +mdns_tx_packet_t *mdns_priv_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool include_ip); /** * @brief Create an announcement packet from an existing probe packet */ -mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *probe); +mdns_tx_packet_t *mdns_priv_create_announce_from_probe(mdns_tx_packet_t *probe); /** * @brief Dispatch a transmit packet for sending */ -void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p); +void mdns_priv_dispatch_tx_packet(mdns_tx_packet_t *p); /** * @brief Send a goodbye message for a service subtype */ -void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, mdns_subtype_t *remove_subtypes); +void mdns_priv_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, mdns_subtype_t *remove_subtypes); /** * @brief Append host list information to service records */ -bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], size_t services_len, bool flush, bool bye); +bool mdns_priv_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], size_t services_len, bool flush, bool bye); /** * @brief Clear the transmit queue head for a specific interface and protocol */ -void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +void mdns_priv_clear_tx_queue_if(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); /** * @brief Clear the global transmit queue head */ -void _mdns_clear_tx_queue_head(void); +void mdns_priv_clear_tx_queue(void); /** * @brief Remove scheduled service packets for a given service */ -void _mdns_remove_scheduled_service_packets(mdns_service_t *service); +void mdns_priv_remove_scheduled_service_packets(mdns_service_t *service); /** * @brief Get the next packet from the PCB queue for a specific interface and protocol */ -mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +mdns_tx_packet_t *mdns_priv_get_next_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); /** * @brief Deallocate an answer record */ -void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service); +void mdns_priv_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service); /** * @brief Remove a scheduled answer for a specific interface, protocol, and service */ -void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service); +void mdns_priv_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service); /** * @brief Allocate a new packet with default settings */ -mdns_tx_packet_t *_mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +mdns_tx_packet_t *mdns_priv_alloc_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); /** * @brief Send all pending mDNS packets */ -void mdns_send_packets(void); +void mdns_priv_send_packets(void); /** * @brief Execute an mDNS action with specified type */ -void mdns_send_action(mdns_action_t *action, mdns_action_subtype_t type); +void mdns_priv_send_action(mdns_action_t *action, mdns_action_subtype_t type); /** * @brief Schedule a transmit packet for sending after a specified delay */ -void mdns_send_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after); +void mdns_priv_send_after(mdns_tx_packet_t *packet, uint32_t ms_after); /** * @brief Send by for particular services on particular PCB */ -void mdns_send_bye_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); +void mdns_priv_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip); /** * @brief Create answer packet to questions from parsed packet @@ -126,7 +126,6 @@ void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_pac */ int mdns_priv_append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt); - #ifdef __cplusplus } #endif diff --git a/components/mdns/private_include/mdns_utils.h b/components/mdns/private_include/mdns_utils.h index d574a07257..470bb153b0 100644 --- a/components/mdns/private_include/mdns_utils.h +++ b/components/mdns/private_include/mdns_utils.h @@ -144,7 +144,7 @@ uint8_t mdns_utils_append_u16(uint8_t *packet, uint16_t *index, uint16_t value); * * @return length of added data: 0 on error or 1 on success */ -static inline uint8_t _mdns_append_u8(uint8_t *packet, uint16_t *index, uint8_t value) +static inline uint8_t mdns_utils_append_u8(uint8_t *packet, uint16_t *index, uint8_t value) { if (*index >= MDNS_MAX_PACKET_SIZE) { return 0; From 1738b7073aebacb6c95262045aba0b1fd5a4e643 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 1 Apr 2025 17:50:27 +0200 Subject: [PATCH 21/27] fix(mdns): Cleanup mdns sender --- components/mdns/mdns_browser.c | 2 +- components/mdns/mdns_receive.c | 6 +-- components/mdns/mdns_responder.c | 33 ++++++------ components/mdns/mdns_send.c | 53 +++++++++---------- components/mdns/mdns_service.c | 1 - .../mdns/private_include/mdns_responder.h | 5 -- .../tests/host_unit_test/stubs/mdns_engine.c | 2 +- .../unity/test_receiver/test_receiver.c | 4 +- .../unity/test_sender/test_sender.c | 6 +-- 9 files changed, 51 insertions(+), 61 deletions(-) diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index 1b57f68bfd..1e50271617 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -587,7 +587,7 @@ void mdns_priv_browse_result_add_srv(mdns_browse_t *browse, const char *hostname add_browse_result(out_sync_browse, r); } -/**4 +/** * @brief Browse sync result */ esp_err_t mdns_priv_browse_sync(mdns_browse_sync_t *browse_sync) diff --git a/components/mdns/mdns_receive.c b/components/mdns/mdns_receive.c index 75a8400897..4d105c99d9 100644 --- a/components/mdns/mdns_receive.c +++ b/components/mdns/mdns_receive.c @@ -736,9 +736,9 @@ static void mdns_parse_packet(mdns_rx_packet_t *packet) question->type = type; question->sub = name->sub; if (strdup_check(&(question->host), name->host) - || strdup_check(&(question->service), name->service) - || strdup_check(&(question->proto), name->proto) - || strdup_check(&(question->domain), name->domain)) { + || strdup_check(&(question->service), name->service) + || strdup_check(&(question->proto), name->proto) + || strdup_check(&(question->domain), name->domain)) { goto clear_rx_packet; } } diff --git a/components/mdns/mdns_responder.c b/components/mdns/mdns_responder.c index 9e9a280174..43591fab8c 100644 --- a/components/mdns/mdns_responder.c +++ b/components/mdns/mdns_responder.c @@ -45,6 +45,19 @@ esp_err_t mdns_priv_responder_init(void) return ESP_OK; } +static void free_delegated_hostnames(void) +{ + mdns_host_item_t *host = s_server->host_list; + while (host != NULL) { + mdns_utils_free_address_list(host->address_list); + mdns_mem_free((char *)host->hostname); + mdns_host_item_t *item = host; + host = host->next; + mdns_mem_free(item); + } + s_server->host_list = NULL; +} + void mdns_priv_responder_free(void) { if (s_server->action_sema != NULL) { @@ -56,6 +69,7 @@ void mdns_priv_responder_free(void) } mdns_mem_free((char *)s_server->hostname); mdns_mem_free((char *)s_server->instance); + free_delegated_hostnames(); mdns_mem_free(s_server); s_server = NULL; } @@ -424,7 +438,7 @@ bool mdns_priv_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *addre static bool delegate_hostname_set_address(const char *hostname, mdns_ip_addr_t *address_list) { if (!mdns_utils_str_null_or_empty(s_server->hostname) && - strcasecmp(hostname, s_server->hostname) == 0) { + strcasecmp(hostname, s_server->hostname) == 0) { return false; } mdns_host_item_t *host = s_server->host_list; @@ -441,19 +455,6 @@ static bool delegate_hostname_set_address(const char *hostname, mdns_ip_addr_t * return false; } -void mdns_priv_free_delegated_hostnames(void) -{ - mdns_host_item_t *host = s_server->host_list; - while (host != NULL) { - mdns_utils_free_address_list(host->address_list); - mdns_mem_free((char *)host->hostname); - mdns_host_item_t *item = host; - host = host->next; - mdns_mem_free(item); - } - s_server->host_list = NULL; -} - static bool delegate_hostname_remove(const char *hostname) { mdns_srv_item_t *srv = s_server->services; @@ -520,7 +521,7 @@ void mdns_priv_responder_action(mdns_action_t *action, mdns_action_subtype_t typ send_bye_all_pcbs_no_instance(true); mdns_priv_remap_self_service_hostname(s_server->hostname, action->data.hostname_set.hostname); mdns_mem_free((char *)s_server->hostname); - s_server->hostname = action->data.hostname_set.hostname; + s_server->hostname = action->data.hostname_set.hostname; s_server->self_host.hostname = action->data.hostname_set.hostname; mdns_priv_restart_all_pcbs(); xSemaphoreGive(s_server->action_sema); @@ -528,7 +529,7 @@ void mdns_priv_responder_action(mdns_action_t *action, mdns_action_subtype_t typ case ACTION_INSTANCE_SET: send_bye_all_pcbs_no_instance(false); mdns_mem_free((char *)s_server->instance); - s_server->instance = action->data.instance; + s_server->instance = action->data.instance; mdns_priv_restart_all_pcbs_no_instance(); break; case ACTION_DELEGATE_HOSTNAME_ADD: diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index fe0fa1fde0..e3a9ab616c 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -250,7 +250,7 @@ static mdns_host_item_t *get_host_item(const char *hostname) } static bool create_answer_from_service(mdns_tx_packet_t *packet, mdns_service_t *service, - mdns_parsed_question_t *question, bool shared, bool send_flush) + mdns_parsed_question_t *question, bool shared, bool send_flush) { mdns_host_item_t *host = get_host_item(service->hostname); bool is_delegated = (host != mdns_priv_get_self_host()); @@ -258,22 +258,22 @@ static bool create_answer_from_service(mdns_tx_packet_t *packet, mdns_service_t // According to RFC6763-section12.1, for DNS-SD, SRV, TXT and all address records // should be included in additional records. if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_PTR, service, NULL, false, false) || - !mdns_priv_create_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_SRV, service, - NULL, send_flush, false) || - !mdns_priv_create_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_TXT, service, - NULL, send_flush, false) || - !mdns_priv_create_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_A, + !mdns_priv_create_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_SRV, service, + NULL, send_flush, false) || + !mdns_priv_create_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_TXT, service, + NULL, send_flush, false) || + !mdns_priv_create_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_A, service, host, send_flush, false) || - !mdns_priv_create_answer((shared || is_delegated) ? &packet->additional : &packet->answers, + !mdns_priv_create_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_AAAA, service, host, send_flush, false)) { return false; } } else if (question->type == MDNS_TYPE_SRV) { if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || - !mdns_priv_create_answer(&packet->additional, MDNS_TYPE_A, service, host, send_flush, false) || - !mdns_priv_create_answer(&packet->additional, MDNS_TYPE_AAAA, service, host, send_flush, false)) { + !mdns_priv_create_answer(&packet->additional, MDNS_TYPE_A, service, host, send_flush, false) || + !mdns_priv_create_answer(&packet->additional, MDNS_TYPE_AAAA, service, host, send_flush, false)) { return false; } } else if (question->type == MDNS_TYPE_TXT) { @@ -292,7 +292,7 @@ static bool create_answer_from_hostname(mdns_tx_packet_t *packet, const char *ho { mdns_host_item_t *host = get_host_item(hostname); if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_A, NULL, host, send_flush, false) || - !mdns_priv_create_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, send_flush, false)) { + !mdns_priv_create_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, send_flush, false)) { return false; } return true; @@ -411,7 +411,7 @@ static bool append_host_question(mdns_out_question_t **questions, const char *ho } static bool append_host_questions_for_services(mdns_out_question_t **questions, mdns_srv_item_t *services[], - size_t len, bool unicast) + size_t len, bool unicast) { if (!mdns_utils_str_null_or_empty(mdns_priv_get_global_hostname()) && !append_host_question(questions, mdns_priv_get_global_hostname(), unicast)) { @@ -491,12 +491,12 @@ static uint8_t append_reverse_ptr_record(uint8_t *packet, uint16_t *index, const return 0; } - if (!_mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, 10 /* TTL set to 10s*/)) { + if (!append_type(packet, index, MDNS_ANSWER_PTR, false, 10 /* TTL set to 10s*/)) { return 0; } uint16_t data_len_location = *index - 2; /* store the position of size (2=16bis) of this record */ - const char *str[2] = {priv_get_self_host()->hostname, MDNS_UTILS_DEFAULT_DOMAIN }; + const char *str[2] = {mdns_priv_get_self_host()->hostname, MDNS_UTILS_DEFAULT_DOMAIN }; int part_length = append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); if (!part_length) { @@ -588,8 +588,7 @@ void mdns_priv_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_pac #ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES } else if (q->type == MDNS_TYPE_PTR) { mdns_host_item_t *host = get_host_item(q->host); -#error - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, NULL, host, send_flush, false)) { + if (!mdns_priv_create_answer(&packet->answers, MDNS_TYPE_PTR, NULL, host, send_flush, false)) { mdns_priv_free_tx_packet(packet); return; } else { @@ -829,8 +828,8 @@ static uint16_t append_ptr_record(uint8_t *packet, uint16_t *index, const char * * @return length of added data: 0 on error or length on success */ static uint16_t append_subtype_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, - const char *subtype, const char *service, const char *proto, bool flush, - bool bye) + const char *subtype, const char *service, const char *proto, bool flush, + bool bye) { const char *subtype_str[5] = {subtype, MDNS_SUB_STR, service, proto, MDNS_UTILS_DEFAULT_DOMAIN}; const char *instance_str[4] = {instance, service, proto, MDNS_UTILS_DEFAULT_DOMAIN}; @@ -868,12 +867,12 @@ static uint16_t append_subtype_ptr_record(uint8_t *packet, uint16_t *index, cons * @return number of answers added to the packet */ static uint8_t append_service_ptr_answers(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, - bool bye) + bool bye) { uint8_t appended_answers = 0; if (append_ptr_record(packet, index, mdns_utils_get_service_instance_name(service), service->service, - service->proto, flush, bye) <= 0) { + service->proto, flush, bye) <= 0) { return appended_answers; } appended_answers++; @@ -882,7 +881,7 @@ static uint8_t append_service_ptr_answers(uint8_t *packet, uint16_t *index, mdns while (subtype) { appended_answers += (append_subtype_ptr_record(packet, index, mdns_utils_get_service_instance_name(service), subtype->subtype, - service->service, service->proto, flush, bye) > 0); + service->service, service->proto, flush, bye) > 0); subtype = subtype->next; } @@ -1180,7 +1179,7 @@ static uint16_t append_aaaa_record(uint8_t *packet, uint16_t *index, const char #endif static uint8_t append_host_answer(uint8_t *packet, uint16_t *index, mdns_host_item_t *host, - uint8_t address_type, bool flush, bool bye) + uint8_t address_type, bool flush, bool bye) { mdns_ip_addr_t *addr = host->address_list; uint8_t num_records = 0; @@ -1196,7 +1195,7 @@ static uint8_t append_host_answer(uint8_t *packet, uint16_t *index, mdns_host_it #ifdef CONFIG_LWIP_IPV6 if (address_type == ESP_IPADDR_TYPE_V6 && append_aaaa_record(packet, index, host->hostname, (uint8_t *)addr->addr.u_addr.ip6.addr, flush, - bye) <= 0) { + bye) <= 0) { break; } #endif /* CONFIG_LWIP_IPV6 */ @@ -1238,8 +1237,8 @@ static uint8_t append_answer(uint8_t *packet, uint16_t *index, mdns_out_answer_t #endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ } else { return append_ptr_record(packet, index, - answer->custom_instance, answer->custom_service, answer->custom_proto, - answer->flush, answer->bye) > 0; + answer->custom_instance, answer->custom_service, answer->custom_proto, + answer->flush, answer->bye) > 0; } } else if (answer->type == MDNS_TYPE_SRV) { return append_srv_record(packet, index, answer->service, answer->flush, answer->bye) > 0; @@ -1294,7 +1293,7 @@ static uint8_t append_answer(uint8_t *packet, uint16_t *index, mdns_out_answer_t return 0; } if (append_aaaa_record(packet, index, mdns_priv_get_global_hostname(), (uint8_t *)if_ip6s[i].addr, - answer->flush, answer->bye) <= 0) { + answer->flush, answer->bye) <= 0) { return 0; } } @@ -1308,13 +1307,13 @@ static uint8_t append_answer(uint8_t *packet, uint16_t *index, mdns_out_answer_t return count; } if (append_aaaa_record(packet, index, mdns_priv_get_global_hostname(), (uint8_t *)other_ip6.addr, - answer->flush, answer->bye) > 0) { + answer->flush, answer->bye) > 0) { return 1 + count; } return count; } else if (answer->host != NULL) { return append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V6, answer->flush, - answer->bye); + answer->bye); } } #endif /* CONFIG_LWIP_IPV6 */ diff --git a/components/mdns/mdns_service.c b/components/mdns/mdns_service.c index 0ef939268c..cc523a2aec 100644 --- a/components/mdns/mdns_service.c +++ b/components/mdns/mdns_service.c @@ -390,7 +390,6 @@ void mdns_free(void) mdns_priv_netif_unregister_predefined_handlers(); mdns_service_remove_all(); - mdns_priv_free_delegated_hostnames(); _mdns_service_task_stop(); // at this point, the service task is deleted, so we can destroy the stack size mdns_mem_task_free(_mdns_stack_buffer); diff --git a/components/mdns/private_include/mdns_responder.h b/components/mdns/private_include/mdns_responder.h index d81adb5590..fc0fbedb92 100644 --- a/components/mdns/private_include/mdns_responder.h +++ b/components/mdns/private_include/mdns_responder.h @@ -88,11 +88,6 @@ void mdns_priv_restart_all_pcbs(void); */ bool mdns_priv_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *address_list); -/** - * Fee delegated hostnames - */ -void mdns_priv_free_delegated_hostnames(void); - /** * @brief Remaps hostname of self service */ diff --git a/components/mdns/tests/host_unit_test/stubs/mdns_engine.c b/components/mdns/tests/host_unit_test/stubs/mdns_engine.c index 996c89356c..63ba5e48f0 100644 --- a/components/mdns/tests/host_unit_test/stubs/mdns_engine.c +++ b/components/mdns/tests/host_unit_test/stubs/mdns_engine.c @@ -29,7 +29,7 @@ static void execute_action(mdns_action_t *action) break; case ACTION_TX_HANDLE: - mdns_send_action(action, ACTION_RUN); + mdns_priv_send_action(action, ACTION_RUN); break; case ACTION_RX_HANDLE: mdns_priv_receive_action(action, ACTION_RUN); diff --git a/components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c b/components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c index b872ba997f..698c850362 100644 --- a/components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c +++ b/components/mdns/tests/host_unit_test/unity/test_receiver/test_receiver.c @@ -74,8 +74,8 @@ void setup_cmock(void) mdns_priv_pcb_check_probing_services_CMockIgnore(); mdns_priv_pcb_is_after_probing_IgnoreAndReturn(true); - _mdns_clear_tx_queue_head_CMockIgnore(); - _mdns_remove_scheduled_service_packets_CMockIgnore(); + mdns_priv_clear_tx_queue_CMockIgnore(); + mdns_priv_remove_scheduled_service_packets_CMockIgnore(); mdns_priv_create_answer_from_parsed_packet_Stub(mdns_priv_create_answer_from_parsed_packet_Callback); } diff --git a/components/mdns/tests/host_unit_test/unity/test_sender/test_sender.c b/components/mdns/tests/host_unit_test/unity/test_sender/test_sender.c index 8fb326cec4..0d444c28ce 100644 --- a/components/mdns/tests/host_unit_test/unity/test_sender/test_sender.c +++ b/components/mdns/tests/host_unit_test/unity/test_sender/test_sender.c @@ -18,16 +18,12 @@ void setup_cmock(void) mdns_priv_pcb_is_after_probing_IgnoreAndReturn(true); } - - -// Example of a more complex test with answers and additional records static void test_dispatch_tx_packet(void) { mdns_tx_packet_t p = {}; - _mdns_dispatch_tx_packet(&p); + mdns_priv_dispatch_tx_packet(&p); } - void run_unity_tests(void) { UNITY_BEGIN(); From 48fef6ffbedde8f019b3aca0af57cac91e65560c Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 2 Apr 2025 11:10:41 +0200 Subject: [PATCH 22/27] fix(mdns): Add documentation about the refactor, remove old fuzz --- components/mdns/refactor_2025.md | 56 +++ .../tests/test_afl_fuzz_host/CMakeLists.txt | 6 - .../mdns/tests/test_afl_fuzz_host/Makefile | 103 ----- .../mdns/tests/test_afl_fuzz_host/README.md | 80 ---- .../tests/test_afl_fuzz_host/esp32_mock.c | 162 ------- .../tests/test_afl_fuzz_host/esp32_mock.h | 145 ------ .../mdns/tests/test_afl_fuzz_host/esp_attr.h | 14 - .../tests/test_afl_fuzz_host/esp_netif_mock.c | 55 --- .../tests/test_afl_fuzz_host/in/file2.bin | Bin 33 -> 0 bytes .../test_afl_fuzz_host/in/minif_4a_txt.bin | Bin 39 -> 0 bytes .../test_afl_fuzz_host/in/minif_aaaa.bin | Bin 33 -> 0 bytes .../tests/test_afl_fuzz_host/in/minif_any.bin | Bin 109 -> 0 bytes .../test_afl_fuzz_host/in/minif_disc.bin | Bin 65 -> 0 bytes .../tests/test_afl_fuzz_host/in/minif_ptr.bin | Bin 36 -> 0 bytes .../test_afl_fuzz_host/in/minif_query.bin | Bin 77 -> 0 bytes .../test_afl_fuzz_host/in/minif_query2.bin | Bin 64 -> 0 bytes .../test_afl_fuzz_host/in/sub_fritz_m.bin | Bin 72 -> 0 bytes .../test_afl_fuzz_host/in/telnet_ptr.bin | Bin 72 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-14.bin | Bin 568 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-15.bin | Bin 524 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-16.bin | Bin 254 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-28.bin | Bin 62 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-29.bin | Bin 39 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-31.bin | Bin 91 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-53.bin | Bin 140 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-56.bin | Bin 262 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-63.bin | Bin 147 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-83.bin | Bin 105 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-88.bin | Bin 48 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-89.bin | Bin 459 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-95.bin | Bin 286 -> 0 bytes .../tests/test_afl_fuzz_host/in/test-96.bin | Bin 319 -> 0 bytes .../test_afl_fuzz_host/input_packets.txt | 166 ------- .../mdns/tests/test_afl_fuzz_host/mdns_di.h | 28 -- .../mdns/tests/test_afl_fuzz_host/mdns_mock.h | 31 -- .../test_afl_fuzz_host/mdns_querier_di.h | 47 -- .../mdns/tests/test_afl_fuzz_host/sdkconfig.h | 424 ------------------ .../mdns/tests/test_afl_fuzz_host/test.c | 267 ----------- 38 files changed, 56 insertions(+), 1528 deletions(-) create mode 100644 components/mdns/refactor_2025.md delete mode 100644 components/mdns/tests/test_afl_fuzz_host/CMakeLists.txt delete mode 100644 components/mdns/tests/test_afl_fuzz_host/Makefile delete mode 100644 components/mdns/tests/test_afl_fuzz_host/README.md delete mode 100644 components/mdns/tests/test_afl_fuzz_host/esp32_mock.c delete mode 100644 components/mdns/tests/test_afl_fuzz_host/esp32_mock.h delete mode 100644 components/mdns/tests/test_afl_fuzz_host/esp_attr.h delete mode 100644 components/mdns/tests/test_afl_fuzz_host/esp_netif_mock.c delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/file2.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/minif_4a_txt.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/minif_aaaa.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/minif_any.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/minif_disc.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/minif_ptr.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/minif_query.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/minif_query2.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/sub_fritz_m.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/telnet_ptr.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-14.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-15.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-16.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-28.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-29.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-31.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-53.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-56.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-63.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-83.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-88.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-89.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-95.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/in/test-96.bin delete mode 100644 components/mdns/tests/test_afl_fuzz_host/input_packets.txt delete mode 100644 components/mdns/tests/test_afl_fuzz_host/mdns_di.h delete mode 100644 components/mdns/tests/test_afl_fuzz_host/mdns_mock.h delete mode 100644 components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h delete mode 100644 components/mdns/tests/test_afl_fuzz_host/sdkconfig.h delete mode 100644 components/mdns/tests/test_afl_fuzz_host/test.c diff --git a/components/mdns/refactor_2025.md b/components/mdns/refactor_2025.md new file mode 100644 index 0000000000..53b6fd7f1d --- /dev/null +++ b/components/mdns/refactor_2025.md @@ -0,0 +1,56 @@ +# MDNS Component Refactor + +## Introduction + +The MDNS component has been refactored from a single monolithic file `mdns.c` into a set of focused modules with clear responsibilities. This restructuring maintains the same functionality while improving code organization, maintainability, and testability. + +The refactor has been performed in thee major stages, to ensure smooth transition to production while avoiding major changes in untested paths. These stages are: +[x] Restructuring into several modules while keeping the actual code changes to minimum +[ ] Cover functionality of each module by specifically focused unit tests. +[ ] Optimizations on module levels (string and queue operations, esp_timer dependency, socket task improvements, error checking) + +## Module Structure + +### mdns_service.c +The central service module that orchestrates the MDNS component operation. It manages the service task, timer, action queue, and system event handling. This module provides the entry points for the public API and coordinates actions between different modules. It's responsible for the general lifecycle of the MDNS service. + +### mdns_responder.c +Implements the responder functionality that answers incoming MDNS queries. It manages hostname and service registration, and generates appropriate response packets based on the queried information. The responder tracks all registered services and their associated metadata, handling hostname conflicts and service announcement. + +### mdns_browser.c +Handles browse/query functionality, managing browse requests for MDNS services on the network. It provides the infrastructure for adding, tracking, and removing browse requests, and processes incoming service discovery responses. The module manages browsing state and notifies applications when services appear or disappear. + +### mdns_querier.c +Handles outgoing query functionality, maintaining state for ongoing queries and processing query responses. It supports one-shot and continuous queries, manages query timeouts, and organizes results. The module provides the infrastructure for applications to discover services and resolve hostnames. + +### mdns_send.c +Manages packet generation and transmission. It constructs properly formatted MDNS packets, with correct headers and resource records, and handles the transmission scheduling and queueing of outgoing messages. This module encapsulates knowledge about the MDNS protocol packet structure. + +### mdns_receive.c +Processes incoming MDNS packets, parsing and validating their structure. It extracts queries and responses from received packets and dispatches them to the appropriate handling modules. This module focuses on packet parsing and initial classification. + +### mdns_pcb.c +Manages protocol control blocks (PCBs) that handle the state machine for MDNS interface operation. It coordinates the probing, announcing, and running states for each network interface and protocol combination. This module is responsible for service conflict detection, duplicate interface handling, and ensuring proper service announcements. + +### mdns_networking_lwip.c and mdns_networking_socket.c +These modules provide networking abstraction for different underlying network stacks. They handle multicast group management, packet reception, and transmission over the network interfaces. This abstraction allows the MDNS implementation to work with different networking stacks. + +### mdns_netif.c +Manages network interface registration and monitoring. It tracks network interface state changes and notifies the MDNS service when interfaces become available or unavailable, enabling dynamic adaptation to network configuration changes. + +### mdns_utils.c +Contains common utility functions used across multiple modules, such as string handling, data structure operations, and debug helpers. This module centralizes shared functionality to avoid code duplication. + +### mdns_mem_caps.c +Provides memory allocation functions with capability-based allocation support. It encapsulates memory management operations, making it easier to track and debug memory usage across the MDNS component. + +### mdns_debug.c +Contains debugging and logging utilities specific to the MDNS component. It provides structured logging and debug information for troubleshooting complex MDNS operations. + +## Testability Improvements + +The refactored module structure significantly enhances testability by clearly separating different functional areas. Each module can now be tested in isolation with proper mocking of its dependencies. The separation of networking, packet handling, and business logic makes it possible to create focused unit tests without the complexity of managing the entire MDNS stack. Module-specific state is now contained within individual modules rather than distributed throughout a monolithic codebase, making test case setup and verification more straightforward. The refactoring also improves the ability to simulate various network conditions and edge cases by intercepting inter-module communication at well-defined boundaries. + +## Conclusion + +The MDNS component refactoring provides a more maintainable and testable architecture while preserving the existing public API. By breaking down the monolithic implementation into focused modules with clear responsibilities, the codebase becomes easier to understand, extend, and maintain. The refactored structure makes it simpler to identify and fix bugs, implement new features, and adapt to future requirements. This architectural improvement supports long-term evolution of the component while maintaining backward compatibility for existing applications. diff --git a/components/mdns/tests/test_afl_fuzz_host/CMakeLists.txt b/components/mdns/tests/test_afl_fuzz_host/CMakeLists.txt deleted file mode 100644 index f4933a3cb8..0000000000 --- a/components/mdns/tests/test_afl_fuzz_host/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) -set(EXTRA_COMPONENT_DIRS ../../) -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(fuzz_test_update) diff --git a/components/mdns/tests/test_afl_fuzz_host/Makefile b/components/mdns/tests/test_afl_fuzz_host/Makefile deleted file mode 100644 index aa30b09f5c..0000000000 --- a/components/mdns/tests/test_afl_fuzz_host/Makefile +++ /dev/null @@ -1,103 +0,0 @@ -TEST_NAME=test -FUZZ=afl-fuzz -COMPONENTS_DIR=$(IDF_PATH)/components -# Use ESP32 toolchain include path if available, otherwise fall back to system includes for host-based compilation -COMPILER_INCLUDE_DIR=$(shell if command -v xtensa-esp32-elf-gcc >/dev/null 2>&1; then echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf; else echo /usr; fi) - -CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversion -Wno-macro-redefined -Wno-int-to-void-pointer-cast -DHOOK_MALLOC_FAILED -DESP_EVENT_H_ -D__ESP_LOG_H__ \ - -I. -I../.. -I../../include -I../../private_include -I ./build/config \ - -I$(COMPONENTS_DIR) \ - -I$(COMPONENTS_DIR)/driver/include \ - -I$(COMPONENTS_DIR)/esp_common/include \ - -I$(COMPONENTS_DIR)/esp_event/include \ - -I$(COMPONENTS_DIR)/esp_eth/include \ - -I$(COMPONENTS_DIR)/esp_hw_support/include \ - -I$(COMPONENTS_DIR)/esp_netif/include \ - -I$(COMPONENTS_DIR)/esp_netif/private_include \ - -I$(COMPONENTS_DIR)/esp_netif/lwip \ - -I$(COMPONENTS_DIR)/esp_rom/include \ - -I$(COMPONENTS_DIR)/esp_system/include \ - -I$(COMPONENTS_DIR)/esp_timer/include \ - -I$(COMPONENTS_DIR)/esp_wifi/include \ - -I$(COMPONENTS_DIR)/freertos/FreeRTOS-Kernel \ - -I$(COMPONENTS_DIR)/freertos/FreeRTOS-Kernel/include \ - -I$(COMPONENTS_DIR)/freertos/esp_additions/include/freertos \ - -I$(COMPONENTS_DIR)/hal/include \ - -I$(COMPONENTS_DIR)/hal/esp32/include \ - -I$(COMPONENTS_DIR)/heap/include \ - -I$(COMPONENTS_DIR)/log/include \ - -I$(COMPONENTS_DIR)/lwip/lwip/src/include \ - -I$(COMPONENTS_DIR)/linux/include \ - -I$(COMPONENTS_DIR)/lwip/port/esp32/include \ - -I$(COMPONENTS_DIR)/lwip/lwip/src/include/lwip/apps \ - -I$(COMPONENTS_DIR)/soc/include \ - -I$(COMPONENTS_DIR)/soc/esp32/include \ - -I$(COMPONENTS_DIR)/soc/src/esp32/include \ - -I$(COMPONENTS_DIR)/xtensa/include \ - -I$(COMPONENTS_DIR)/xtensa/esp32/include \ - -I$(COMPILER_INCLUDE_DIR)/include - - -MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h -ifeq ($(MDNS_NO_SERVICES),on) - CFLAGS+=-DMDNS_NO_SERVICES -endif - -ifeq ($(INSTR),off) - CC=gcc - CFLAGS+=-DINSTR_IS_OFF - TEST_NAME=test_sim -else - CC=afl-clang-fast -endif -CPP=$(CC) -LD=$(CC) -OBJECTS=esp32_mock.o mdns.o test.o esp_netif_mock.o mdns_utils.o mdns_receive.o mdns_browser.o mdns_querier.o mdns_send.o mdns_responder.o mdns_netif.o - -OS := $(shell uname) -ifeq ($(OS),Darwin) - LDLIBS= -else - LDLIBS=-lbsd - CFLAGS+=-DUSE_BSD_STRING -endif - -all: $(TEST_NAME) - -%.o: %.c - @echo "[CC] $<" - @$(CC) $(CFLAGS) -c $< -o $@ - -mdns.o: ../../mdns.c - @echo "[CC] $<" - @$(CC) $(CFLAGS) -include mdns_mock.h $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@ - -mdns_querier.o: ../../mdns_querier.c - @echo "[CC] $<" - @$(CC) $(CFLAGS) -include mdns_mock.h -include mdns_querier_di.h -c $< -o $@ - - -%.o: ../../%.c - @echo "[CC] $<" - @$(CC) $(CFLAGS) -include mdns_mock.h -c $< -o $@ - -$(TEST_NAME): $(OBJECTS) - @echo "[LD] $@" - @$(LD) $(OBJECTS) -o $@ $(LDLIBS) - -fuzz: $(TEST_NAME) - # timeout returns 124 if time limit is reached, original return code otherwise - # pass only if: fuzzing was running smoothly until timeout AND no crash found - @timeout 10m $(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) || \ - if [ $$? -eq 124 ]; then \ - if [ -n "$$(find out/default/crashes -type f 2>/dev/null)" ]; then \ - echo "Crashes found!"; \ - tar -czf out/default/crashes.tar.gz -C out/default crashes; \ - exit 1; \ - fi \ - else \ - exit 1; \ - fi - -clean: - @rm -rf *.o *.SYM $(TEST_NAME) out diff --git a/components/mdns/tests/test_afl_fuzz_host/README.md b/components/mdns/tests/test_afl_fuzz_host/README.md deleted file mode 100644 index e22a89606f..0000000000 --- a/components/mdns/tests/test_afl_fuzz_host/README.md +++ /dev/null @@ -1,80 +0,0 @@ -## Introduction -This test uses [american fuzzy lop](http://lcamtuf.coredump.cx/afl/) to mangle real mdns packets and look for exceptions caused by the parser. - -A few actual packets are collected and exported as bins in the `in` folder, which is then passed as input to AFL when testing. The setup procedure for the test includes all possible services and scenarios that could be used with the given input packets.The output of the parser before fuzzing can be found in [input_packets.txt](input_packets.txt) - -## Building and running the tests using AFL -To build and run the tests using AFL(afl-clang-fast) instrumentation - -```bash -cd $IDF_PATH/components/mdns/test_afl_host -make fuzz -``` - -(Please note you have to install AFL instrumentation first, check `Installing AFL` section) - -## Building the tests using GCC INSTR(off) - -To build the tests without AFL instrumentations and instead of that use GCC compiler(In this case it will only check for compilation issues and will not run AFL tests). - -```bash -cd $IDF_PATH/components/mdns/test_afl_host -make INSTR=off -``` - -Note, that this setup is useful if we want to reproduce issues reported by fuzzer tests executed in the CI, or to simulate how the packet parser treats the input packets on the host machine. - -## Installing AFL -To run the test yourself, you need to download the [latest afl archive](http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz) and extract it to a folder on your computer. - -The rest of the document will refer to that folder as ```PATH_TO_AFL```. - -### Preparation -- On Mac, you will need to install the latest Xcode and llvm support from [Homebrew](https://brew.sh) - - ```bash - /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" - brew install --with-clang --with-lld --HEAD llvm - export PATH="/usr/local/opt/llvm/bin:$PATH" - ``` - -- On Ubuntu you need the following packages: - - ```bash - sudo apt-get install make clang-4.0(or <=4.0) llvm-4.0(or <=4.0) libbsd-dev - ``` - -Please note that if specified package version can't be installed(due to system is the latest), you can download, build and install it manually. - -### Compile AFL -Compiling AFL is as easy as running make: - -```bash -cd [PATH_TO_AFL] -make -cd llvm_mode/ -make -``` - -After successful compilation, you can export the following variables to your shell (you can also add them to your profile if you want to use AFL in other projects). - -```bash -export AFL_PATH=[PATH_TO_AFL] -export PATH="$AFL_PATH:$PATH" -``` - -Please note LLVM must be <=4.0.0, otherwise afl does not compile, as there are some limitations with building AFL on MacOS/Linux with the latest LLVM. Also, Windows build on cygwin is not fully supported. - -## Additional info -Apple has a crash reporting service that could interfere with AFLs normal operation. To turn that off, run the following command: - -```bash -launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist -sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist -``` - -Ubuntu has a similar service. To turn that off, run as root: - -```bash -echo core >/proc/sys/kernel/core_pattern -``` diff --git a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.c b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.c deleted file mode 100644 index 7f14dc6baa..0000000000 --- a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#include -#include -#include -#include -#include -#include "esp32_mock.h" -#include "esp_log.h" - -void *g_queue; -int g_queue_send_shall_fail = 0; -int g_size = 0; - -const char *WIFI_EVENT = "wifi_event"; -const char *ETH_EVENT = "eth_event"; - -esp_err_t esp_event_handler_register(const char *event_base, - int32_t event_id, - void *event_handler, - void *event_handler_arg) -{ - return ESP_OK; -} - -esp_err_t esp_event_handler_unregister(const char *event_base, int32_t event_id, void *event_handler) -{ - return ESP_OK; -} - -esp_err_t esp_timer_delete(esp_timer_handle_t timer) -{ - return ESP_OK; -} - -esp_err_t esp_timer_stop(esp_timer_handle_t timer) -{ - return ESP_OK; -} - -esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) -{ - return ESP_OK; -} - -esp_err_t esp_timer_create(const esp_timer_create_args_t *create_args, - esp_timer_handle_t *out_handle) -{ - return ESP_OK; -} - -uint32_t xTaskGetTickCount(void) -{ - static uint32_t tick = 0; - return tick++; -} - -/// Queue mock -QueueHandle_t xQueueCreate(uint32_t uxQueueLength, uint32_t uxItemSize) -{ - g_size = uxItemSize; - g_queue = malloc((uxQueueLength) * (uxItemSize)); - return g_queue; -} - - -void vQueueDelete(QueueHandle_t xQueue) -{ - free(xQueue); -} - -uint32_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait) -{ - if (g_queue_send_shall_fail) { - return pdFALSE; - } else { - memcpy(xQueue, pvItemToQueue, g_size); - return pdPASS; - } -} - - -uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait) -{ - return pdFALSE; -} - -void GetLastItem(void *pvBuffer) -{ - memcpy(pvBuffer, g_queue, g_size); -} - -void ForceTaskDelete(void) -{ - g_queue_send_shall_fail = 1; -} - -TaskHandle_t xTaskGetCurrentTaskHandle(void) -{ - return NULL; -} - -void xTaskNotifyGive(TaskHandle_t task) -{ - return; -} - -BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time) -{ - return pdTRUE; -} - -void esp_log_write(esp_log_level_t level, const char *tag, const char *format, ...) -{ -} - -void esp_log(esp_log_config_t config, const char *tag, const char *format, ...) -{ -} - -uint32_t esp_log_timestamp(void) -{ - return 0; -} - -void *mdns_mem_malloc(size_t size) -{ - return malloc(size); -} - -void *mdns_mem_calloc(size_t num, size_t size) -{ - return calloc(num, size); -} - -void mdns_mem_free(void *ptr) -{ - free(ptr); -} - -char *mdns_mem_strdup(const char *s) -{ - return strdup(s); -} - -char *mdns_mem_strndup(const char *s, size_t n) -{ - return strndup(s, n); -} - -void *mdns_mem_task_malloc(size_t size) -{ - return malloc(size); -} - -void mdns_mem_task_free(void *ptr) -{ - free(ptr); -} diff --git a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h deleted file mode 100644 index a4a5b0be39..0000000000 --- a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef _ESP32_COMPAT_H_ -#define _ESP32_COMPAT_H_ - -// Skip these include files -#define ESP_MDNS_NETWORKING_H_ -#define INC_FREERTOS_H -#define QUEUE_H -#define SEMAPHORE_H -#define _ESP_TASK_H_ - -#ifdef USE_BSD_STRING -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include "esp_timer.h" - -#define ESP_FAIL -1 - -#define ESP_ERR_NO_MEM 0x101 -#define ESP_ERR_INVALID_ARG 0x102 -#define ESP_ERR_INVALID_STATE 0x103 -#define ESP_ERR_INVALID_SIZE 0x104 -#define ESP_ERR_NOT_FOUND 0x105 -#define ESP_ERR_NOT_SUPPORTED 0x106 -#define ESP_ERR_TIMEOUT 0x107 -#define ESP_ERR_INVALID_RESPONSE 0x108 -#define ESP_ERR_INVALID_CRC 0x109 - -#define MDNS_TASK_MEMORY_LOG "internal RAM" -#define MALLOC_CAP_8BIT (1<<2) -#define MALLOC_CAP_INTERNAL (1<<11) - -#define pdTRUE true -#define pdFALSE false -#define pdPASS ( pdTRUE ) -#define pdFAIL ( pdFALSE ) - -#define portMAX_DELAY 0xFFFFFFFF -#define portTICK_PERIOD_MS 1 -#define LWIP_HDR_PBUF_H -#define __ESP_RANDOM_H__ -#define INC_TASK_H - -#define pdMS_TO_TICKS(a) a -#define xSemaphoreTake(s,d) true -#define vTaskDelete(a) free(NULL) -#define xSemaphoreGive(s) -#define xQueueCreateMutex(s) -#define mdns_priv_if_init(a,b) true -#define mdns_priv_if_deinit(a,b) true -#define xSemaphoreCreateMutex() malloc(1) -#define xSemaphoreCreateBinary() malloc(1) -#define vSemaphoreDelete(s) free(s) -#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U -#define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1) -#define xTaskCreateStaticPinnedToCore(a,b,c,d,e,f,g,h) ((void*)1) -#define vTaskDelay(m) usleep((m)*0) -#define esp_random() (rand()%UINT32_MAX) - - -#define ESP_TASK_PRIO_MAX 25 -#define ESP_TASKD_EVENT_PRIO 5 -#define mdns_priv_if_write(tcpip_if, ip_protocol, ip, port, data, len) len -#define TaskHandle_t TaskHandle_t - - -typedef int32_t esp_err_t; - -typedef void *SemaphoreHandle_t; -typedef void *QueueHandle_t; -typedef void *TaskHandle_t; -typedef int BaseType_t; -typedef uint32_t TickType_t; -typedef void *StackType_t; -typedef void *StaticTask_t; - -struct udp_pcb { - uint8_t dummy; -}; - -struct ip4_addr { - uint32_t addr; -}; -typedef struct ip4_addr ip4_addr_t; - -struct ip6_addr { - uint32_t addr[4]; -}; -typedef struct ip6_addr ip6_addr_t; - -typedef void *system_event_t; - -struct pbuf { - struct pbuf *next; - void *payload; - uint16_t tot_len; - uint16_t len; - uint8_t /*pbuf_type*/ type; - uint8_t flags; - uint16_t ref; -}; - -uint32_t xTaskGetTickCount(void); -typedef void (*esp_timer_cb_t)(void *arg); - -// Queue mock -QueueHandle_t xQueueCreate(uint32_t uxQueueLength, - uint32_t uxItemSize); - -void vQueueDelete(QueueHandle_t xQueue); - -uint32_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait); - -uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); - -void GetLastItem(void *pvBuffer); - -void ForceTaskDelete(void); - -esp_err_t esp_event_handler_register(const char *event_base, int32_t event_id, void *event_handler, void *event_handler_arg); - -esp_err_t esp_event_handler_unregister(const char *event_base, int32_t event_id, void *event_handler); - - -TaskHandle_t xTaskGetCurrentTaskHandle(void); -void xTaskNotifyGive(TaskHandle_t task); -BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time); - -static inline void xTaskGetStaticBuffers(void *pvTaskBuffer, void *pvStackBuffer, void *pvTaskTCB) -{ -} - -#endif //_ESP32_COMPAT_H_ diff --git a/components/mdns/tests/test_afl_fuzz_host/esp_attr.h b/components/mdns/tests/test_afl_fuzz_host/esp_attr.h deleted file mode 100644 index 75b66786aa..0000000000 --- a/components/mdns/tests/test_afl_fuzz_host/esp_attr.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#pragma once -#define IRAM_ATTR -#define FLAG_ATTR(TYPE) -#define QUEUE_H -#define __ARCH_CC_H__ -#define __XTENSA_API_H__ -#define SSIZE_MAX INT_MAX -#define LWIP_HDR_IP6_ADDR_H -#define LWIP_HDR_IP4_ADDR_H diff --git a/components/mdns/tests/test_afl_fuzz_host/esp_netif_mock.c b/components/mdns/tests/test_afl_fuzz_host/esp_netif_mock.c deleted file mode 100644 index 80629ad63d..0000000000 --- a/components/mdns/tests/test_afl_fuzz_host/esp_netif_mock.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include "esp32_mock.h" - -typedef struct esp_netif_s esp_netif_t; -typedef struct esp_netif_ip_info esp_netif_ip_info_t; -typedef struct esp_netif_dhcp_status esp_netif_dhcp_status_t; - - -const char *IP_EVENT = "IP_EVENT"; - - -esp_err_t esp_netif_add_to_list(esp_netif_t *netif) -{ - return ESP_OK; -} - -esp_err_t esp_netif_remove_from_list(esp_netif_t *netif) -{ - return ESP_ERR_NOT_FOUND; -} - -esp_netif_t *esp_netif_next(esp_netif_t *netif) -{ - return NULL; -} - -esp_netif_t *esp_netif_next_unsafe(esp_netif_t *netif) -{ - return NULL; -} - -esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key) -{ - return NULL; -} - -esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) -{ - return ESP_ERR_NOT_SUPPORTED; -} - -esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) -{ - return ESP_ERR_NOT_SUPPORTED; -} diff --git a/components/mdns/tests/test_afl_fuzz_host/in/file2.bin b/components/mdns/tests/test_afl_fuzz_host/in/file2.bin deleted file mode 100644 index a7ce859cc0fdf7cef7985d51d480e03cef0bde7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33 kcmZQz00Kr3!N9*z=%+RBzQm% hBz1s?L6LzGXixSyIIkUy@wFnv;?$zD)FPJn;?g9x__U(Tk}8(?lH>x`oc!d(90mp+2F3$CAd-PW Ra1sL#XKrR*CRo)0NdPDN5l#RA diff --git a/components/mdns/tests/test_afl_fuzz_host/in/telnet_ptr.bin b/components/mdns/tests/test_afl_fuzz_host/in/telnet_ptr.bin deleted file mode 100644 index 1cd8e85d8021f55039566cdd619235aeb952ffa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72 zcmZQzXkh>XMi9XnUz}Q0mYJMd%pRYTSFBr{!V+JaQox#%pPZP(z`z4iB{+paggw3_ PH775%geATt872z=Qoj-} diff --git a/components/mdns/tests/test_afl_fuzz_host/in/test-14.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-14.bin deleted file mode 100644 index b9d059d8202682602e7232a8505c495a3047e3a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 568 zcmaiwPfNov7{)Vc-GqW7j)|wjsGcf~S~hRiF&W~a2k#+k0~WgWB}sAnMEe#aev*0f zYnYmKpg5L8@;*Gj_g@gw=M=T;r$cDQq2$scG66d;6PhFBpq5SEqy*Ki;|>9y6_W8k z(juaoD$gKwot!QVViQiwP4*$FL_!N=w2csr$^a@cZR*xs(X_FMHk)!f+~gb+NOM1> zk_yQgof*O+&`j$PkuwH9@N&MeNR@)Rs7LhfhXIZT<8b&C;fD#&geg za3+LG&Fd@xs>KLTNcn;-*5pXh{6Hl3Gf@0Bv?l!J7wTd;niT zpQFAGPvJB)ejMCnH#5JT{b&BO0M9^cBj1M?YNV6sL|5fVbt9Ej+lyF*S{proq+$Y_ zy(EZB<0$aQ0F|dTfW0^Pc%S>15?e0gf=P$9ZRU2E6gBl1yUeqg)y}c?t9peygs&#} z7|j&Zdeo=X8zO0VLkn$-((43yUL=X?$Ick}!j;^kSawken}R!yj@dNbnpQ!IPSfSw z6t(+@>poibXblSGtk>cz>tEHauqc}6a-MwrlizE$|MzI+T(JBX1>O+*nyq$)j zQylnX9d7k~Ow=qiw8BP1a9+~%qG`nQ)xD8Uv1!|NXD5mA#_QH@&$~uSCEPYe#h+j? zazWa{-WhziU)BS1Dn2W)3#)mrXUl8}NBQ(&0aZF-|Mg&HNV7tR6XMi3VDD9S7@$yYB{2+7P%Rd7x$C@#%O<%mzrEGoz^Dq)E)NiJZ`$xlwq zVPFtw0BRAO!mwg_d7`hQt+|1&xv{RZldhAAuCt}Cld(<_s<4x;fr+lGIY`(DNi{^+ z0x0a4YnzvpS*%-zV0U=oA+vm)V+|Sr{1T8R{fu1*g~=8yw(a(1*I26Ub&|U}#`) F005APLjnK* diff --git a/components/mdns/tests/test_afl_fuzz_host/in/test-28.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-28.bin deleted file mode 100644 index 537352ae67db92f820ff0d1299dae3534eef1f48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62 zcmZQz00Kr3!N4HuQIuI+lCNH@5R#djs^FYhP+Xdm${nAWR*+woT2zu;z!DE6Sab4| L6LT0C6dM=;y^9dW diff --git a/components/mdns/tests/test_afl_fuzz_host/in/test-29.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-29.bin deleted file mode 100644 index 837737b32e12e3f33ff3f1c3b59f6ff351b05fba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39 qcmZQz00Jfu!N9XCLm_y%+1WpOe@MPsbbB^PfpBXV328G1WHse2>fdR(m)`h7xI6{k-wY= bco-O=ax4c{{1X83^`U$YAe+U3fq?@6q#+cG diff --git a/components/mdns/tests/test_afl_fuzz_host/in/test-53.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-53.bin deleted file mode 100644 index 73181ea8c378d33efed725aa209387113edffdd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 140 zcmZQz00Jf;1Ok@$;@l*b_>$xT)|~w0#2f|&9tKA7;QX}A%0ykyvc$anvczIt-^666 z{QT?#VhoH7j0bo?Y8V)}zcR>5K~yS0RX%E%S*!q4%mY{WjX^@xqbReuBwxK)AtW<5 PRlzy2ptv+A^#Bh5gdisG diff --git a/components/mdns/tests/test_afl_fuzz_host/in/test-56.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-56.bin deleted file mode 100644 index 980b6516a20908c4b681b1cf3717c7ef35f062b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 262 zcmZQzXkh>XCLm@L_9)6MF3Eq?Ftb>}H!)cuH#0AjCq5;$EHgP(H#09SpC!H|xqvk% zKRGdnfkA+Qk%2*Q3WJP5ZhlH?jxA6JNQ0S<5m$b3MOkW5v8|yQOMG!|(g9rt9;jk5 zY<3)oKTyCR&;T)xkpak21aTND7=%D>W8BLLGB~X$v!v>P(SfB5GEiB8e+?jc1_lwm xkpDZ5{N)77F+$~74y^bm05nM-YAh#^&C0;gz~BH>1QrAu&jDn!I5049006}!N5=pF diff --git a/components/mdns/tests/test_afl_fuzz_host/in/test-63.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-63.bin deleted file mode 100644 index 883d444ba269c8938aa87f3ba8da53a1305f9763..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 147 zcmZQz00Jf;1Oo2(#I%C^vecrIAisgkVmtU4x ztm~VY?3ACMeL$9hk%9354@eEr1V;v0DTqo1sLDqTGm8~qig}O}N{D(CWfqs@s~0PT SWag$SI42eqm*%7%-~j;3q9}|2 diff --git a/components/mdns/tests/test_afl_fuzz_host/in/test-83.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-83.bin deleted file mode 100644 index c6cc159a2597bc35b4316a796af18534bfee7dc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 zcmZQzXkh>XMj&Pq56(}^tW4DPEKAJGFH0=e^-WB6%FoYc&B;$r%mFHD04b|rU^%ej opU43o1{o+{;9mn!90-_XHvj*(sc11!P9G}A0c5i{Ffecc09-p6=Kufz diff --git a/components/mdns/tests/test_afl_fuzz_host/in/test-88.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-88.bin deleted file mode 100644 index fcbb384438a28961526215b8b66e32193b6fd0e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48 xcmZQz00Jfu!N9;0UzC=_5?_*Bz?zevoS4JFz{9}E5ucb@RFGd(azGHo1pvO@39SGC diff --git a/components/mdns/tests/test_afl_fuzz_host/in/test-89.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-89.bin deleted file mode 100644 index d60a987cad92fe5e9e86e83ea8d2ee16f7fe93e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 459 zcmZut!AiqG6nsjH6?&*>t%!$uQZQS0laj>4LYts?QG|-ulBSVH(x&XjT5mmg=~3_> ztY`gzT*ZHizSvY0e6Z}id9$-S3-AC~%eYnwZO0eGP(-mV!P{&eAgrX;5v-UP|9p7oBgos1w8f0EOdo2ePiw} zNje}4^KDp~;Po(uTs%uyd;q1i$LGwR@0_zHHz+YQVq3(j6Z?o*nj-$v7NK==Y^1dM zOFgGeq|f_&(D5aSJQ-nY_c&vUuzMxFc@pCZ#o|bZ%N*uF-f3J6VQOGQliZLVkQEZ||>|XE&P_Qhxn0o}&II^Gj0M Z$Nq4kL7Zy<6!6?PhySpOI1ey^#uu&jeZK$z diff --git a/components/mdns/tests/test_afl_fuzz_host/in/test-95.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-95.bin deleted file mode 100644 index 26553090fa6d7cddb5fb7c748fc72d8d20c77364..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 286 zcmZQz00L$PHW0-fpO{vVUzS=_l3c(N4XCLm@O^(e|LF3DFfRtU+=O;vDCEGRC`N#%)8NiEAvPSwrKOUq}8FG((7 z&B;$r%wb>1yv^6)dGB>tzcCvCZv2wPwax&IQObK(dHK;H&FfedS$u_cu z^DV$~ezs8iK?*}{O-<7hlaefwbQ8^tlXOi@Obm4`EzC`H%~Dg6Obtv@lZ*`#fi^3G pY-XrnkOhSV1E&Zi7>ad4{?UaRc)$dxP#@|pb->payload; -} - -static inline size_t mdns_priv_get_packet_len(mdns_rx_packet_t *packet) -{ - return packet->pb->len; -} - -static inline void mdns_priv_packet_free(mdns_rx_packet_t *packet) -{ - free(packet->pb); - free(packet); -} - -static inline bool mdns_priv_if_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - return true; -} diff --git a/components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h b/components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h deleted file mode 100644 index 23908fe40f..0000000000 --- a/components/mdns/tests/test_afl_fuzz_host/mdns_querier_di.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -/* - * MDNS Dependecy injection -- preincluded to inject interface test functions into static variables - * - */ - -#include "mdns.h" -#include "mdns_private.h" - -esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t *search) = NULL; -void (*mdns_test_static_search_free)(mdns_search_once_t *search) = NULL; - -mdns_search_once_t *(*mdns_test_static_search_init)(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, - uint32_t timeout, uint8_t max_results, - mdns_query_notify_t notifier) = NULL; - -static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, - uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier); -static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); -static void _mdns_search_free(mdns_search_once_t *search); - -void mdns_querier_test_init_di(void) -{ - mdns_test_static_search_init = _mdns_search_init; - mdns_test_static_send_search_action = _mdns_send_search_action; - mdns_test_static_search_free = _mdns_search_free; -} - - -mdns_search_once_t *mdns_test_search_init(const char *name, const char *service, const char *proto, uint16_t type, uint32_t timeout, uint8_t max_results) -{ - return mdns_test_static_search_init(name, service, proto, type, timeout, type != MDNS_TYPE_PTR, max_results, NULL); -} - -void mdns_test_search_free(mdns_search_once_t *search) -{ - return mdns_test_static_search_free(search); -} - -esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t *search) -{ - return mdns_test_static_send_search_action(type, search); -} diff --git a/components/mdns/tests/test_afl_fuzz_host/sdkconfig.h b/components/mdns/tests/test_afl_fuzz_host/sdkconfig.h deleted file mode 100644 index da75d14752..0000000000 --- a/components/mdns/tests/test_afl_fuzz_host/sdkconfig.h +++ /dev/null @@ -1,424 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -/* - * This config file commited in order to not run `idf.py reconfigure` each time when running fuzzer test. You can modify it manually or run `idf.py reconfigure` to generate new one if needed. - * Espressif IoT Development Framework (ESP-IDF) Configuration Header - */ -#pragma once -#define CONFIG_IDF_TARGET "esp32" -#define CONFIG_IDF_TARGET_ESP32 1 -#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 -#define CONFIG_SDK_TOOLPREFIX "xtensa-esp32-elf-" -#define CONFIG_APP_BUILD_TYPE_APP_2NDBOOT 1 -#define CONFIG_APP_BUILD_GENERATE_BINARIES 1 -#define CONFIG_APP_BUILD_BOOTLOADER 1 -#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1 -#define CONFIG_APP_COMPILE_TIME_DATE 1 -#define CONFIG_APP_RETRIEVE_LEN_ELF_SHA 16 -#define CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE 1 -#define CONFIG_BOOTLOADER_LOG_LEVEL_INFO 1 -#define CONFIG_BOOTLOADER_LOG_LEVEL 3 -#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 -#define CONFIG_BOOTLOADER_WDT_ENABLE 1 -#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 -#define CONFIG_BOOTLOADER_RESERVE_RTC_SIZE 0x0 -#define CONFIG_ESPTOOLPY_WITH_STUB 1 -#define CONFIG_ESPTOOLPY_FLASHMODE_DIO 1 -#define CONFIG_ESPTOOLPY_FLASHMODE "dio" -#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 -#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" -#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1 -#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB" -#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 -#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 -#define CONFIG_ESPTOOLPY_BEFORE "default_reset" -#define CONFIG_ESPTOOLPY_AFTER_RESET 1 -#define CONFIG_ESPTOOLPY_AFTER "hard_reset" -#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 -#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" -#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" -#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 -#define CONFIG_PARTITION_TABLE_MD5 1 -#define CONFIG_COMPILER_OPTIMIZATION_DEFAULT 1 -#define CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE 1 -#define CONFIG_COMPILER_STACK_CHECK_MODE_NONE 1 -#define CONFIG_APPTRACE_DEST_NONE 1 -#define CONFIG_APPTRACE_LOCK_ENABLE 1 -#define CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF 0 -#define CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF 0 -#define CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF 0 -#define CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF 0 -#define CONFIG_BTDM_CTRL_PINNED_TO_CORE 0 -#define CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF 1 -#define CONFIG_BTDM_RESERVE_DRAM 0x0 -#define CONFIG_COAP_MBEDTLS_PSK 1 -#define CONFIG_COAP_LOG_DEFAULT_LEVEL 0 -#define CONFIG_ADC_DISABLE_DAC 1 -#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 -#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 -#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 -#define CONFIG_EFUSE_MAX_BLK_LEN 192 -#define CONFIG_ESP_TLS_USING_MBEDTLS 1 -#define CONFIG_ESP32_REV_MIN_0 1 -#define CONFIG_ESP32_REV_MIN 0 -#define CONFIG_ESP32_DPORT_WORKAROUND 1 -#define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 1 -#define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 160 -#define CONFIG_ESP32_TRACEMEM_RESERVE_DRAM 0x0 -#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR 1 -#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES 4 -#define CONFIG_ULP_COPROC_RESERVE_MEM 0 -#define CONFIG_ESP_DEBUG_OCDAWARE 1 -#define CONFIG_ESP_BROWNOUT_DET 1 -#define CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0 1 -#define CONFIG_ESP_BROWNOUT_DET_LVL 0 -#define CONFIG_ESP32_REDUCE_PHY_TX_POWER 1 -#define CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT 1 -#define CONFIG_RTC_CLK_SRC_INT_RC 1 -#define CONFIG_RTC_CLK_CAL_CYCLES 1024 -#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 -#define CONFIG_ESP32_XTAL_FREQ_40 1 -#define CONFIG_ESP32_XTAL_FREQ 40 -#define CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL 5 -#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 -#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 -#define CONFIG_ADC_CAL_LUT_ENABLE 1 -#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 -#define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32 -#define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2304 -#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 3584 -#define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024 -#define CONFIG_ESP_IPC_USES_CALLERS_PRIORITY 1 -#define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048 -#define CONFIG_ESP_CONSOLE_UART_DEFAULT 1 -#define CONFIG_ESP_CONSOLE_UART_NUM 0 -#define CONFIG_ESP_CONSOLE_UART_TX_GPIO 1 -#define CONFIG_ESP_CONSOLE_UART_RX_GPIO 3 -#define CONFIG_ESP_CONSOLE_UART_BAUDRATE 115200 -#define CONFIG_ESP_INT_WDT 1 -#define CONFIG_ESP_INT_WDT_TIMEOUT_MS 300 -#define CONFIG_ESP_INT_WDT_CHECK_CPU1 1 -#define CONFIG_ESP_TASK_WDT 1 -#define CONFIG_ESP_TASK_WDT_TIMEOUT_S 5 -#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 -#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 -#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA 1 -#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP 1 -#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT 1 -#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT_OFFSET 2 -#define CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH 1 -#define CONFIG_ETH_ENABLED 1 -#define CONFIG_ETH_USE_ESP32_EMAC 1 -#define CONFIG_ETH_PHY_INTERFACE_RMII 1 -#define CONFIG_ETH_RMII_CLK_INPUT 1 -#define CONFIG_ETH_RMII_CLK_IN_GPIO 0 -#define CONFIG_ETH_DMA_BUFFER_SIZE 512 -#define CONFIG_ETH_DMA_RX_BUFFER_NUM 10 -#define CONFIG_ETH_DMA_TX_BUFFER_NUM 10 -#define CONFIG_ETH_USE_SPI_ETHERNET 1 -#define CONFIG_ESP_EVENT_POST_FROM_ISR 1 -#define CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 1 -#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 -#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 -#define CONFIG_HTTPD_MAX_URI_LEN 512 -#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 -#define CONFIG_HTTPD_PURGE_BUF_LEN 32 -#define CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL 120 -#define CONFIG_ESP_NETIF_TCPIP_LWIP 1 -#define CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT 1 -#define CONFIG_ESP_TIMER_TASK_STACK_SIZE 3584 -#define CONFIG_ESP_TIMER_IMPL_TG0_LAC 1 -#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 -#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 -#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 -#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 -#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 -#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 -#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 -#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 -#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 -#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 -#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1 -#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752 -#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 -#define CONFIG_ESP32_WIFI_IRAM_OPT 1 -#define CONFIG_ESP32_WIFI_RX_IRAM_OPT 1 -#define CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE 1 -#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 -#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 -#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 -#define CONFIG_ESP_COREDUMP_ENABLE_TO_NONE 1 -#define CONFIG_FATFS_CODEPAGE_437 1 -#define CONFIG_FATFS_CODEPAGE 437 -#define CONFIG_FATFS_LFN_NONE 1 -#define CONFIG_FATFS_FS_LOCK 0 -#define CONFIG_FATFS_TIMEOUT_MS 10000 -#define CONFIG_FATFS_PER_FILE_CACHE 1 -#define CONFIG_FMB_COMM_MODE_RTU_EN 1 -#define CONFIG_FMB_COMM_MODE_ASCII_EN 1 -#define CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND 150 -#define CONFIG_FMB_MASTER_DELAY_MS_CONVERT 200 -#define CONFIG_FMB_QUEUE_LENGTH 20 -#define CONFIG_FMB_SERIAL_TASK_STACK_SIZE 2048 -#define CONFIG_FMB_SERIAL_BUF_SIZE 256 -#define CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB 8 -#define CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS 1000 -#define CONFIG_FMB_SERIAL_TASK_PRIO 10 -#define CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT 20 -#define CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE 20 -#define CONFIG_FMB_CONTROLLER_STACK_SIZE 4096 -#define CONFIG_FMB_EVENT_QUEUE_TIMEOUT 20 -#define CONFIG_FMB_TIMER_PORT_ENABLED 1 -#define CONFIG_FMB_TIMER_GROUP 0 -#define CONFIG_FMB_TIMER_INDEX 0 -#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF -#define CONFIG_FREERTOS_CORETIMER_0 1 -#define CONFIG_FREERTOS_HZ 100 -#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 -#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 -#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 -#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 -#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 -#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 -#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 -#define CONFIG_FREERTOS_TIMER_TASK_PRIORITY 1 -#define CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH 2048 -#define CONFIG_FREERTOS_TIMER_QUEUE_LENGTH 10 -#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 -#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 -#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 -#define CONFIG_FREERTOS_DEBUG_OCDAWARE 1 -#define CONFIG_HEAP_POISONING_DISABLED 1 -#define CONFIG_HEAP_TRACING_OFF 1 -#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 -#define CONFIG_LOG_DEFAULT_LEVEL 3 -#define CONFIG_LOG_MAXIMUM_LEVEL 3 -#define CONFIG_LOG_COLORS 1 -#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1 -#define CONFIG_LWIP_LOCAL_HOSTNAME "espressif" -#define CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES 1 -#define CONFIG_LWIP_TIMERS_ONDEMAND 1 -#define CONFIG_LWIP_MAX_SOCKETS 10 -#define CONFIG_LWIP_SO_REUSE 1 -#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 -#define CONFIG_LWIP_IP_FRAG 1 -#define CONFIG_LWIP_ESP_GRATUITOUS_ARP 1 -#define CONFIG_LWIP_GARP_TMR_INTERVAL 60 -#define CONFIG_LWIP_TCPIP_RECVMBOX_SIZE 32 -#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 -#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 -#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 -#define CONFIG_LWIP_NETIF_LOOPBACK 1 -#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 -#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 -#define CONFIG_LWIP_MAX_LISTENING_TCP 16 -#define CONFIG_LWIP_TCP_MAXRTX 12 -#define CONFIG_LWIP_TCP_SYNMAXRTX 6 -#define CONFIG_LWIP_TCP_MSS 1440 -#define CONFIG_LWIP_TCP_TMR_INTERVAL 250 -#define CONFIG_LWIP_TCP_MSL 60000 -#define CONFIG_LWIP_TCP_SND_BUF_DEFAULT 5744 -#define CONFIG_LWIP_TCP_WND_DEFAULT 5744 -#define CONFIG_LWIP_TCP_RECVMBOX_SIZE 6 -#define CONFIG_LWIP_TCP_QUEUE_OOSEQ 1 -#define CONFIG_LWIP_TCP_OVERSIZE_MSS 1 -#define CONFIG_LWIP_MAX_UDP_PCBS 16 -#define CONFIG_LWIP_UDP_RECVMBOX_SIZE 6 -#define CONFIG_LWIP_TCPIP_TASK_STACK_SIZE 3072 -#define CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 -#define CONFIG_LWIP_TCPIP_TASK_AFFINITY 0x7FFFFFFF -#define CONFIG_LWIP_MAX_RAW_PCBS 16 -#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 -#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000 -#define CONFIG_LWIP_ESP_LWIP_ASSERT 1 -#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 -#define CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN 1 -#define CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN 16384 -#define CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN 4096 -#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE 1 -#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL 1 -#define CONFIG_MBEDTLS_HARDWARE_AES 1 -#define CONFIG_MBEDTLS_HARDWARE_MPI 1 -#define CONFIG_MBEDTLS_HARDWARE_SHA 1 -#define CONFIG_MBEDTLS_HAVE_TIME 1 -#define CONFIG_MBEDTLS_ECDSA_DETERMINISTIC 1 -#define CONFIG_MBEDTLS_SHA512_C 1 -#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 -#define CONFIG_MBEDTLS_TLS_SERVER 1 -#define CONFIG_MBEDTLS_TLS_CLIENT 1 -#define CONFIG_MBEDTLS_TLS_ENABLED 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 -#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 -#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 -#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 -#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 -#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 -#define CONFIG_MBEDTLS_SSL_ALPN 1 -#define CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS 1 -#define CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS 1 -#define CONFIG_MBEDTLS_AES_C 1 -#define CONFIG_MBEDTLS_RC4_DISABLED 1 -#define CONFIG_MBEDTLS_CCM_C 1 -#define CONFIG_MBEDTLS_GCM_C 1 -#define CONFIG_MBEDTLS_PEM_PARSE_C 1 -#define CONFIG_MBEDTLS_PEM_WRITE_C 1 -#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 -#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 -#define CONFIG_MBEDTLS_ECP_C 1 -#define CONFIG_MBEDTLS_ECDH_C 1 -#define CONFIG_MBEDTLS_ECDSA_C 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 -#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 -#define CONFIG_MDNS_MAX_SERVICES 25 -#define CONFIG_MDNS_MAX_INTERFACES 3 -#define CONFIG_MDNS_TASK_PRIORITY 1 -#define CONFIG_MDNS_ACTION_QUEUE_LEN 16 -#define CONFIG_MDNS_TASK_STACK_SIZE 4096 -#define CONFIG_MDNS_TASK_AFFINITY_CPU0 1 -#define CONFIG_MDNS_TASK_AFFINITY 0x0 -#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 1 -#define CONFIG_MDNS_TIMER_PERIOD_MS 100 -#define CONFIG_MQTT_PROTOCOL_311 1 -#define CONFIG_MQTT_TRANSPORT_SSL 1 -#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 -#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 -#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 -#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 -#define CONFIG_OPENSSL_ASSERT_EXIT 1 -#define CONFIG_PTHREAD_TASK_PRIO_DEFAULT 5 -#define CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 -#define CONFIG_PTHREAD_STACK_MIN 768 -#define CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY 1 -#define CONFIG_PTHREAD_TASK_CORE_DEFAULT -1 -#define CONFIG_PTHREAD_TASK_NAME_DEFAULT "pthread" -#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 -#define CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS 1 -#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 -#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 -#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 -#define CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP 1 -#define CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP 1 -#define CONFIG_SPI_FLASH_SUPPORT_GD_CHIP 1 -#define CONFIG_SPIFFS_MAX_PARTITIONS 3 -#define CONFIG_SPIFFS_CACHE 1 -#define CONFIG_SPIFFS_CACHE_WR 1 -#define CONFIG_SPIFFS_PAGE_CHECK 1 -#define CONFIG_SPIFFS_GC_MAX_RUNS 10 -#define CONFIG_SPIFFS_PAGE_SIZE 256 -#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 -#define CONFIG_SPIFFS_USE_MAGIC 1 -#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 -#define CONFIG_SPIFFS_META_LENGTH 4 -#define CONFIG_SPIFFS_USE_MTIME 1 -#define CONFIG_USB_DESC_CUSTOM_VID 0x1234 -#define CONFIG_USB_DESC_CUSTOM_PID 0x5678 -#define CONFIG_UNITY_ENABLE_FLOAT 1 -#define CONFIG_UNITY_ENABLE_DOUBLE 1 -#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 -#define CONFIG_VFS_SUPPORT_IO 1 -#define CONFIG_VFS_SUPPORT_DIR 1 -#define CONFIG_VFS_SUPPORT_SELECT 1 -#define CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT 1 -#define CONFIG_VFS_SUPPORT_TERMIOS 1 -#define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1 -#define CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN 128 -#define CONFIG_WL_SECTOR_SIZE_4096 1 -#define CONFIG_WL_SECTOR_SIZE 4096 -#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 -#define CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT 30 -#define CONFIG_WPA_MBEDTLS_CRYPTO 1 - -/* List of deprecated options */ -#define CONFIG_ADC2_DISABLE_DAC CONFIG_ADC_DISABLE_DAC -#define CONFIG_BROWNOUT_DET CONFIG_ESP_BROWNOUT_DET -#define CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0 -#define CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT -#define CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE -#define CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT -#define CONFIG_CONSOLE_UART_RX_GPIO CONFIG_ESP_CONSOLE_UART_RX_GPIO -#define CONFIG_CONSOLE_UART_TX_GPIO CONFIG_ESP_CONSOLE_UART_TX_GPIO -#define CONFIG_ESP32S2_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT -#define CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE -#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY -#define CONFIG_ESP32_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT -#define CONFIG_ESP32_PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN -#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT CONFIG_PTHREAD_TASK_NAME_DEFAULT -#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT CONFIG_PTHREAD_TASK_PRIO_DEFAULT -#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT -#define CONFIG_ESP_GRATUITOUS_ARP CONFIG_LWIP_ESP_GRATUITOUS_ARP -#define CONFIG_FLASHMODE_DIO CONFIG_ESPTOOLPY_FLASHMODE_DIO -#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR -#define CONFIG_GARP_TMR_INTERVAL CONFIG_LWIP_GARP_TMR_INTERVAL -#define CONFIG_INT_WDT CONFIG_ESP_INT_WDT -#define CONFIG_INT_WDT_CHECK_CPU1 CONFIG_ESP_INT_WDT_CHECK_CPU1 -#define CONFIG_INT_WDT_TIMEOUT_MS CONFIG_ESP_INT_WDT_TIMEOUT_MS -#define CONFIG_IPC_TASK_STACK_SIZE CONFIG_ESP_IPC_TASK_STACK_SIZE -#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO CONFIG_BOOTLOADER_LOG_LEVEL_INFO -#define CONFIG_MAIN_TASK_STACK_SIZE CONFIG_ESP_MAIN_TASK_STACK_SIZE -#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE -#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT -#define CONFIG_MB_CONTROLLER_STACK_SIZE CONFIG_FMB_CONTROLLER_STACK_SIZE -#define CONFIG_MB_EVENT_QUEUE_TIMEOUT CONFIG_FMB_EVENT_QUEUE_TIMEOUT -#define CONFIG_MB_MASTER_DELAY_MS_CONVERT CONFIG_FMB_MASTER_DELAY_MS_CONVERT -#define CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND -#define CONFIG_MB_QUEUE_LENGTH CONFIG_FMB_QUEUE_LENGTH -#define CONFIG_MB_SERIAL_BUF_SIZE CONFIG_FMB_SERIAL_BUF_SIZE -#define CONFIG_MB_SERIAL_TASK_PRIO CONFIG_FMB_SERIAL_TASK_PRIO -#define CONFIG_MB_SERIAL_TASK_STACK_SIZE CONFIG_FMB_SERIAL_TASK_STACK_SIZE -#define CONFIG_MB_TIMER_GROUP CONFIG_FMB_TIMER_GROUP -#define CONFIG_MB_TIMER_INDEX CONFIG_FMB_TIMER_INDEX -#define CONFIG_MB_TIMER_PORT_ENABLED CONFIG_FMB_TIMER_PORT_ENABLED -#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE -#define CONFIG_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT -#define CONFIG_POST_EVENTS_FROM_IRAM_ISR CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR -#define CONFIG_POST_EVENTS_FROM_ISR CONFIG_ESP_EVENT_POST_FROM_ISR -#define CONFIG_REDUCE_PHY_TX_POWER CONFIG_ESP32_REDUCE_PHY_TX_POWER -#define CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN -#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS -#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS -#define CONFIG_STACK_CHECK_NONE CONFIG_COMPILER_STACK_CHECK_MODE_NONE -#define CONFIG_SUPPORT_TERMIOS CONFIG_VFS_SUPPORT_TERMIOS -#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT -#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE -#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE -#define CONFIG_TASK_WDT CONFIG_ESP_TASK_WDT -#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 -#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 -#define CONFIG_TASK_WDT_TIMEOUT_S CONFIG_ESP_TASK_WDT_TIMEOUT_S -#define CONFIG_TCPIP_RECVMBOX_SIZE CONFIG_LWIP_TCPIP_RECVMBOX_SIZE -#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY -#define CONFIG_TCPIP_TASK_STACK_SIZE CONFIG_LWIP_TCPIP_TASK_STACK_SIZE -#define CONFIG_TCP_MAXRTX CONFIG_LWIP_TCP_MAXRTX -#define CONFIG_TCP_MSL CONFIG_LWIP_TCP_MSL -#define CONFIG_TCP_MSS CONFIG_LWIP_TCP_MSS -#define CONFIG_TCP_OVERSIZE_MSS CONFIG_LWIP_TCP_OVERSIZE_MSS -#define CONFIG_TCP_QUEUE_OOSEQ CONFIG_LWIP_TCP_QUEUE_OOSEQ -#define CONFIG_TCP_RECVMBOX_SIZE CONFIG_LWIP_TCP_RECVMBOX_SIZE -#define CONFIG_TCP_SND_BUF_DEFAULT CONFIG_LWIP_TCP_SND_BUF_DEFAULT -#define CONFIG_TCP_SYNMAXRTX CONFIG_LWIP_TCP_SYNMAXRTX -#define CONFIG_TCP_WND_DEFAULT CONFIG_LWIP_TCP_WND_DEFAULT -#define CONFIG_TIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH -#define CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY -#define CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH -#define CONFIG_TIMER_TASK_STACK_SIZE CONFIG_ESP_TIMER_TASK_STACK_SIZE -#define CONFIG_TOOLPREFIX CONFIG_SDK_TOOLPREFIX -#define CONFIG_UDP_RECVMBOX_SIZE CONFIG_LWIP_UDP_RECVMBOX_SIZE diff --git a/components/mdns/tests/test_afl_fuzz_host/test.c b/components/mdns/tests/test_afl_fuzz_host/test.c deleted file mode 100644 index 50c78de83a..0000000000 --- a/components/mdns/tests/test_afl_fuzz_host/test.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include - -#include "esp32_mock.h" -#include "mdns.h" -#include "mdns_private.h" -#include "mdns_utils.h" -#include "mdns_querier.h" - -// -// Global stuctures containing packet payload, search -mdns_rx_packet_t g_packet; -struct pbuf mypbuf; -mdns_search_once_t *search = NULL; - -// -// Dependency injected test functions -void mdns_test_execute_action(void *action); -mdns_search_once_t *mdns_test_search_init(const char *name, const char *service, const char *proto, uint16_t type, uint32_t timeout, uint8_t max_results); -esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); -void mdns_test_search_free(mdns_search_once_t *search); - -void mdns_test_init_di(void); -void mdns_querier_test_init_di(void); -extern mdns_server_t *_mdns_server; - -// -// mdns function wrappers for mdns setup in test mode -static int mdns_test_hostname_set(const char *mdns_hostname) -{ - for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { - // _mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V4].state = PCB_RUNNING; // mark the PCB running to exercise mdns in fully operational mode - // _mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V6].state = PCB_RUNNING; - } - int ret = mdns_hostname_set(mdns_hostname); - mdns_action_t *a = NULL; - GetLastItem(&a); - mdns_test_execute_action(a); - return ret; -} - -static int mdns_test_add_delegated_host(const char *mdns_hostname) -{ - mdns_ip_addr_t addr = { .addr = { .u_addr = ESP_IPADDR_TYPE_V4 } }; - addr.addr.u_addr.ip4.addr = 0x11111111; - int ret = mdns_delegate_hostname_add(mdns_hostname, &addr); - mdns_action_t *a = NULL; - GetLastItem(&a); - mdns_test_execute_action(a); - return ret; -} - - -static int mdns_test_service_instance_name_set(const char *service, const char *proto, const char *instance) -{ - int ret = mdns_service_instance_name_set(service, proto, instance); - mdns_action_t *a = NULL; - GetLastItem(&a); - mdns_test_execute_action(a); - return ret; -} - -static int mdns_test_service_txt_set(const char *service, const char *proto, uint8_t num_items, mdns_txt_item_t txt[]) -{ - int ret = mdns_service_txt_set(service, proto, txt, num_items); - mdns_action_t *a = NULL; - GetLastItem(&a); - mdns_test_execute_action(a); - return ret; -} - -static int mdns_test_sub_service_add(const char *sub_name, const char *service_name, const char *proto, uint32_t port) -{ - if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { - return ESP_FAIL; - } - - if (_mdns_get_service_item(service_name, proto, NULL) == NULL) { - return ESP_FAIL; - } - return mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name); -} - -static int mdns_test_service_add(const char *service_name, const char *proto, uint32_t port) -{ - if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { - return ESP_FAIL; - } - - if (_mdns_get_service_item(service_name, proto, NULL) == NULL) { - return ESP_FAIL; - } - return ESP_OK; -} - -static mdns_result_t *mdns_test_query(const char *name, const char *service, const char *proto, uint16_t type) -{ - search = mdns_test_search_init(name, service, proto, type, 3000, 20); - if (!search) { - abort(); - } - - if (mdns_test_send_search_action(ACTION_SEARCH_ADD, search)) { - mdns_test_search_free(search); - abort(); - } - - mdns_action_t *a = NULL; - GetLastItem(&a); - mdns_test_execute_action(a); - return NULL; -} - -static void mdns_test_query_free(void) -{ - mdns_test_search_free(search); -} - -// -// function "under test" where afl-mangled packets passed -// -void mdns_parse_packet(mdns_rx_packet_t *packet); - -// -// Test starts here -// -int main(int argc, char **argv) -{ - int i; - const char *mdns_hostname = "minifritz"; - const char *mdns_instance = "Hristo's Time Capsule"; - mdns_txt_item_t arduTxtData[4] = { - {"board", "esp32"}, - {"tcp_check", "no"}, - {"ssh_upload", "no"}, - {"auth_upload", "no"} - }; - - const uint8_t mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x32}; - - uint8_t buf[1460]; - char winstance[21 + strlen(mdns_hostname)]; - - sprintf(winstance, "%s [%02x:%02x:%02x:%02x:%02x:%02x]", mdns_hostname, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - - // Init depencency injected methods - mdns_test_init_di(); - mdns_querier_test_init_di(); - - if (mdns_init()) { - abort(); - } - - if (mdns_test_hostname_set(mdns_hostname)) { - abort(); - } - - if (mdns_test_add_delegated_host(mdns_hostname) || mdns_test_add_delegated_host("megafritz")) { - abort(); - } - -#ifndef MDNS_NO_SERVICES - - if (mdns_test_sub_service_add("_server", "_fritz", "_tcp", 22)) { - abort(); - } - - if (mdns_test_service_add("_telnet", "_tcp", 22)) { - abort(); - } - - if (mdns_test_service_add("_workstation", "_tcp", 9)) { - abort(); - } - if (mdns_test_service_instance_name_set("_workstation", "_tcp", winstance)) { - abort(); - } - - if (mdns_test_service_add("_arduino", "_tcp", 3232)) { - abort(); - } - - if (mdns_test_service_txt_set("_arduino", "_tcp", 4, arduTxtData)) { - abort(); - } - - if (mdns_test_service_add("_http", "_tcp", 80)) { - abort(); - } - - if (mdns_test_service_instance_name_set("_http", "_tcp", "ESP WebServer")) { - abort(); - } - - if ( - mdns_test_service_add("_afpovertcp", "_tcp", 548) - || mdns_test_service_add("_rfb", "_tcp", 885) - || mdns_test_service_add("_smb", "_tcp", 885) - || mdns_test_service_add("_adisk", "_tcp", 885) - || mdns_test_service_add("_airport", "_tcp", 885) - || mdns_test_service_add("_printer", "_tcp", 885) - || mdns_test_service_add("_airplay", "_tcp", 885) - || mdns_test_service_add("_raop", "_tcp", 885) - || mdns_test_service_add("_uscan", "_tcp", 885) - || mdns_test_service_add("_uscans", "_tcp", 885) - || mdns_test_service_add("_ippusb", "_tcp", 885) - || mdns_test_service_add("_scanner", "_tcp", 885) - || mdns_test_service_add("_ipp", "_tcp", 885) - || mdns_test_service_add("_ipps", "_tcp", 885) - || mdns_test_service_add("_pdl-datastream", "_tcp", 885) - || mdns_test_service_add("_ptp", "_tcp", 885) - || mdns_test_service_add("_sleep-proxy", "_udp", 885)) { - abort(); - } -#endif - mdns_result_t *results = NULL; - FILE *file; - size_t nread; - -#ifdef INSTR_IS_OFF - size_t len = 1460; - memset(buf, 0, 1460); - - if (argc != 2) { - printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n"); - return 1; - } else { - // - // Note: parameter1 is a file (mangled packet) which caused the crash - file = fopen(argv[1], "r"); - assert(file >= 0); - len = fread(buf, 1, 1460, file); - fclose(file); - } - - for (i = 0; i < 1; i++) { -#else - while (__AFL_LOOP(1000)) { - memset(buf, 0, 1460); - size_t len = read(0, buf, 1460); -#endif - mypbuf.payload = malloc(len); - memcpy(mypbuf.payload, buf, len); - mypbuf.len = len; - g_packet.pb = &mypbuf; - mdns_test_query("minifritz", "_fritz", "_tcp", MDNS_TYPE_ANY); - mdns_test_query(NULL, "_fritz", "_tcp", MDNS_TYPE_PTR); - mdns_test_query(NULL, "_afpovertcp", "_tcp", MDNS_TYPE_PTR); - mdns_parse_packet(&g_packet); - free(mypbuf.payload); - } -#ifndef MDNS_NO_SERVICES - mdns_service_remove_all(); -#endif - ForceTaskDelete(); - mdns_free(); - return 0; -} From 582d2e4cc3f87d75e548a1ebe913a125c9126534 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 2 Apr 2025 21:06:46 +0200 Subject: [PATCH 23/27] fix(mdns): Add refactoring details to help review changes --- components/mdns/refactoring_details.md | 279 +++++++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 components/mdns/refactoring_details.md diff --git a/components/mdns/refactoring_details.md b/components/mdns/refactoring_details.md new file mode 100644 index 0000000000..edb33ccafe --- /dev/null +++ b/components/mdns/refactoring_details.md @@ -0,0 +1,279 @@ +| Original Function | Refactored Function | Concerns | +|------------------|--------------------|---------| +| [_udp_pcb_main_init](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L50) | [pcb_init](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L69) | | +| [_udp_pcb_main_deinit](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L74) | [pcb_deinit](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L93) | | +| [_udp_join_group](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L87) | [join_group](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L106) | | +| [_udp_recv](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L138) | [receive](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L157) | | +| [mdns_is_netif_ready](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L215) | [mdns_priv_if_ready](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L96) | | +| [_udp_pcb_is_in_use](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L224) | [is_any_pcb_in_use](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L243) | The function name changed from _udp_pcb_is_in_use to is_any_pcb_in_use, and the internal check changed from mdns_is_netif_ready to mdns_priv_if_ready. While this appears to be a straightforward rename and internal function call change, we should verify that mdns_priv_if_ready maintains the same semantic meaning as the original mdns_is_netif_ready function. | +| [_udp_pcb_deinit](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L240) | [pcb_if_deinit](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L259) | | +| [_udp_pcb_init](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L255) | [pcb_if_init](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L274) | | +| [_mdns_pcb_init_api](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L289) | [pcb_if_init_lwip](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L308) | | +| [_mdns_pcb_deinit_api](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L299) | [pcb_if_deinit_lwip](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L318) | | +| [_mdns_pcb_deinit_api](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L299) | [mdns_priv_if_deinit](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L341) | | +| [_mdns_pcb_init](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L312) | [mdns_priv_if_init](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L394) | | +| [_mdns_pcb_deinit](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L322) | [mdns_priv_if_deinit](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L341) | | +| [_mdns_udp_pcb_write_api](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L332) | [write_if_lwip](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L351) | The error code conversion from err_t to esp_err_t (msg->err = err == ERR_OK ? ESP_OK : ESP_FAIL) might change the error handling behavior compared to the original function which passed through the raw err_t value. | +| [_mdns_udp_pcb_write](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L348) | [mdns_priv_if_write](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking.c#L29) | | +| [_mdns_get_packet_data](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L384) | [mdns_priv_get_packet_data](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L403) | | +| [_mdns_get_packet_len](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L389) | [mdns_priv_get_packet_len](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L408) | | +| [_mdns_packet_free](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_lwip.c#L394) | [mdns_priv_packet_free](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L111) | | +| [ctor_networking_socket](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L61) | [ctor_networking_socket](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L83) | | +| [delete_socket](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L69) | [delete_socket](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L91) | | +| [mdns_is_netif_ready](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L74) | [mdns_priv_if_ready](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L96) | The refactored function name changed from mdns_is_netif_ready to mdns_priv_if_ready, which might affect existing code that calls this function. Also, the mock implementation (Result 1) returns a hardcoded true value which could mask real interface readiness checks. | +| [_mdns_get_packet_data](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L79) | [mdns_priv_get_packet_data](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L403) | | +| [_mdns_get_packet_len](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L84) | [mdns_priv_get_packet_len](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L408) | | +| [_mdns_packet_free](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L89) | [mdns_priv_packet_free](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L413) | | +| [_mdns_pcb_deinit](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L96) | [mdns_priv_if_deinit](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L118) | | +| [inet6_ntoa_r](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L121) | [inet6_ntoa_r](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L143) | | +| [inet_ntoa_r](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L127) | [inet_ntoa_r](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L149) | | +| [get_string_address](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L137) | [get_string_address](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L159) | | +| [espaddr_to_inet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L159) | [espaddr_to_inet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L181) | | +| [_mdns_udp_pcb_write](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L195) | [mdns_priv_if_write](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking.c#L29) | The refactored function appears to have multiple implementations (socket, lwip, and dummy versions) with the same name but different behaviors. This could lead to unexpected behavior depending on which implementation gets linked. The original function had distinct implementations for socket vs lwip cases with different names (_mdns_udp_pcb_write in both files but with different implementations). | +| [inet_to_espaddr](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L218) | [inet_to_espaddr](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L240) | | +| [sock_recv_task](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L250) | [sock_recv_task](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L272) | | +| [mdns_networking_init](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L341) | [networking_init](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L363) | | +| [create_pcb](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L349) | [create_pcb](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L371) | | +| [_mdns_pcb_init](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L372) | [mdns_priv_if_init](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L331) | | +| [create_socket](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L383) | [create_socket](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L405) | | +| [socket_add_ipv6_multicast_group](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L437) | [socket_add_ipv6_multicast_group](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L459) | | +| [socket_add_ipv4_multicast_group](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L460) | [socket_add_ipv4_multicast_group](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L482) | | +| [join_mdns_multicast_group](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns_networking_socket.c#L486) | [join_mdns_multicast_group](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_socket.c#L508) | | +| [mdns_if_from_preset_if](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L136) | [mdns_if_from_preset](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L87) | | +| [esp_netif_from_preset_if](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L151) | [netif_from_preset](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L102) | | +| [_mdns_get_esp_netif](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L179) | [mdns_priv_get_esp_netif](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L118) | | +| [_mdns_clean_netif_ptr](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L196) | [mdns_priv_netif_disable](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L134) | | +| [_mdns_get_if_from_esp_netif](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L207) | [get_if_from_netif](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L144) | | +| [_str_null_or_empty](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L224) | [mdns_utils_str_null_or_empty](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.h#L38) | | +| [_mdns_mangle_name](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L232) | [mangle_name](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L137) | | +| [_mdns_service_match](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L272) | [mdns_utils_service_match](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L119) | | +| [_mdns_get_service_item](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L291) | [mdns_utils_get_service_item](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L129) | | +| [_mdns_get_service_item_subtype](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L303) | [get_service_item_subtype](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L38) | | +| [mdns_get_host_item](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L321) | [get_host_item](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L237) | | +| [_mdns_can_add_more_services](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L336) | [can_add_more_services](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L128) | | +| [_mdns_send_rx_action](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L354) | [send_rx_action](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_networking_lwip.c#L47) | | +| [_mdns_get_default_instance_name](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L373) | [get_default_instance_name](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L173) | | +| [_mdns_get_service_instance_name](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L389) | [mdns_utils_get_service_instance_name](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L190) | | +| [_mdns_instance_name_match](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L398) | [mdns_utils_instance_name_match](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L200) | | +| [_mdns_service_match_instance](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L409) | [mdns_utils_service_match_instance](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L160) | | +| [_mdns_get_service_item_instance](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L422) | [mdns_utils_get_service_item_instance](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L141) | | +| [_mdns_read_fqdn](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L452) | [mdns_utils_read_fqdn](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L16) | | +| [_mdns_set_u16](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L512) | [set_u16](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L141) | | +| [_mdns_append_u8](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L530) | [mdns_utils_append_u8](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.h#L147) | | +| [_mdns_append_u16](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L549) | [mdns_utils_append_u16](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L259) | | +| [_mdns_append_u32](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L568) | [append_u32](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L37) | | +| [_mdns_append_type](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L590) | [append_type](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L59) | The function append_type uses append_u32 for TTL but mdns_utils_append_u16 for other fields, which might be inconsistent. Also, the original used _mdns_append_u32 consistently. | +| [_mdns_append_string_with_len](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L622) | [append_string](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L100) | The refactored function 'append_string' now calculates the string length internally using strlen() instead of taking it as a parameter, which changes the function's interface and behavior. The original function allowed passing pre-calculated lengths. | +| [_mdns_append_string](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L642) | [append_string](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L100) | The function mdns_utils_append_u8 is now used instead of _mdns_append_u8, which has slightly different error handling (returns 0/1 instead of void). However, since the original _mdns_append_string didn't check the return value of _mdns_append_u8, this change shouldn't affect functionality. | +| [append_one_txt_record_entry](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L665) | [mdns_priv_append_one_txt_record_entry](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mock_mdns_send.c#L3399) | | +| [append_single_str](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L686) | [append_single_str](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L429) | The function was renamed _mdns_append_u8 to mdns_utils_append_u8, which appears to be a utility function extraction. The functionality remains equivalent but relies on the new utility function's implementation being correct. | +| [append_fqdn_dots](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L711) | [append_fqdn_dots](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L454) | The refactored function replaces _mdns_append_u8 with mdns_utils_append_u8, which appears to be a renamed utility function. While this is likely safe, we should verify that mdns_utils_append_u8 has the same behavior as the original _mdns_append_u8 function. | +| [_mdns_append_fqdn](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L750) | [append_fqdn](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L666) | | +| [_mdns_append_ptr_record](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L823) | [append_ptr_record](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L780) | | +| [_mdns_append_subtype_ptr_record](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L873) | [append_subtype_ptr_record](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L830) | | +| [_mdns_append_sdptr_record](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L918) | [append_sdptr_record](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1037) | | +| [_mdns_append_txt_record](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L968) | [append_txt_record](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L973) | | +| [_mdns_append_srv_record](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1032) | [append_srv_record](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L901) | | +| [_mdns_append_a_record](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1105) | [append_a_record](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1088) | | +| [_mdns_append_aaaa_record](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1157) | [append_aaaa_record](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1140) | The refactored function uses MDNS_UTILS_DEFAULT_DOMAIN instead of MDNS_DEFAULT_DOMAIN and calls utility functions with different prefixes (mdns_utils_str_null_or_empty vs _str_null_or_empty, set_u16 vs _mdns_set_u16). While functionally equivalent, these changes might affect compatibility if other parts of the codebase expect the original constants/function names. | +| [_mdns_append_question](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1201) | [append_question](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L733) | | +| [_mdns_get_other_if](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1242) | [mdns_priv_netif_get_other_interface](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L73) | | +| [_mdns_if_is_dup](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1253) | [mdns_priv_pcb_check_for_duplicates](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_pcb.c#L89) | | +| [_ipv6_address_is_zero](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1273) | [mdns_utils_ipv6_address_is_zero](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L246) | | +| [_mdns_append_host_answer](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1286) | [append_host_answer](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1181) | | +| [_mdns_append_reverse_ptr_record](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1318) | [append_reverse_ptr_record](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L484) | The refactored function uses mdns_priv_get_self_host()->hostname instead of _mdns_self_host.hostname and MDNS_UTILS_DEFAULT_DOMAIN instead of MDNS_DEFAULT_DOMAIN. While this appears to be a safe structural change (just accessing the hostname through a different interface), we should verify that mdns_priv_get_self_host() returns the same host structure as _mdns_self_host was referencing. | +| [_mdns_append_service_ptr_answers](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1350) | [append_service_ptr_answers](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L869) | | +| [_mdns_append_answer](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1378) | [append_answer](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1214) | | +| [_mdns_dispatch_tx_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1490) | [mdns_priv_dispatch_tx_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1328) | The function name changed from _mdns_dispatch_tx_packet to mdns_priv_dispatch_tx_packet, and some internal helper functions were renamed (e.g., _mdns_set_u16 to set_u16, _mdns_append_question to append_question). The functionality appears equivalent, but we should verify these renamed helper functions maintain the same behavior. | +| [_mdns_free_tx_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1559) | [mdns_priv_free_tx_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L184) | | +| [_mdns_schedule_tx_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1588) | [mdns_priv_send_after](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1616) | The global variable _mdns_server->tx_queue_head was changed to s_tx_queue_head. Need to verify that s_tx_queue_head is properly initialized and accessible in the same way as the original. | +| [_mdns_clear_tx_queue_head](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1611) | [mdns_priv_clear_tx_queue](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1639) | | +| [_mdns_clear_pcb_tx_queue_head](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1627) | [mdns_priv_clear_tx_queue_if](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1655) | The refactored function uses a global variable 's_tx_queue_head' instead of accessing it through '_mdns_server->tx_queue_head'. This could be problematic if the server structure is still being used elsewhere in the code. | +| [_mdns_get_next_pcb_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1655) | [mdns_priv_get_next_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1683) | | +| [_mdns_remove_scheduled_answer](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1670) | [mdns_priv_remove_scheduled_answer](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mock_mdns_send.c#L2558) | | +| [_mdns_dealloc_answer](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1704) | [mdns_priv_dealloc_answer](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mock_mdns_send.c#L2408) | | +| [_mdns_alloc_answer](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1733) | [mdns_priv_create_answer](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L210) | | +| [_mdns_alloc_packet_default](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1763) | [mdns_priv_alloc_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L153) | | +| [_mdns_create_answer_from_service](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1789) | [create_answer_from_service](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L252) | | +| [_mdns_create_answer_from_hostname](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1824) | [create_answer_from_hostname](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L291) | | +| [_mdns_service_match_ptr_question](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1834) | [service_match_ptr_question](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L301) | | +| [_mdns_create_answer_from_parsed_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L1862) | [mdns_priv_create_answer_from_parsed_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mock_mdns_send.c#L3276) | | +| [_mdns_question_exists](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2009) | [question_exists](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L376) | | +| [_mdns_append_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2023) | [append_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L325) | | +| [_mdns_append_host_list_in_services](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2034) | [mdns_priv_append_host_list_in_services](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L336) | | +| [_mdns_append_host_list](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2053) | [append_host_list](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L355) | | +| [_mdns_append_host_question](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2071) | [append_host_question](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L390) | | +| [_mdns_append_host_questions_for_services](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2094) | [append_host_questions_for_services](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L413) | | +| [_mdns_create_probe_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2112) | [mdns_priv_create_probe_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1382) | | +| [_mdns_create_announce_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2166) | [mdns_priv_create_announce_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1437) | | +| [_mdns_create_announce_from_probe](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2196) | [mdns_priv_create_announce_from_probe](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1467) | | +| [_mdns_pcb_send_bye](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2236) | [mdns_priv_send_bye](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1504) | | +| [_mdns_init_pcb_probe_new_service](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2260) | [init_probe_new_service](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_pcb.c#L339) | | +| [_mdns_init_pcb_probe](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2316) | [mdns_priv_init_pcb_probe](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mock_mdns_pcb.c#L2478) | | +| [_mdns_restart_pcb](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2356) | [restart_pcb](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_pcb.c#L127) | | +| [_mdns_send_bye](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2382) | [mdns_priv_pcb_send_bye_service](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_pcb.c#L429) | | +| [_mdns_send_bye_subtype](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2401) | [mdns_priv_send_bye_subtype](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mock_mdns_send.c#L1681) | | +| [_mdns_announce_pcb](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2451) | [mdns_priv_pcb_announce](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mock_mdns_pcb.c#L861) | | +| [_mdns_probe_all_pcbs](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2494) | [mdns_priv_probe_all_pcbs](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mock_mdns_pcb.c#L2342) | | +| [_mdns_announce_all_pcbs](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2516) | [announce_all_pcbs](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L149) | | +| [_mdns_send_final_bye](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2529) | [send_final_bye](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L162) | | +| [_mdns_send_bye_all_pcbs_no_instance](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2554) | [send_bye_all_pcbs_no_instance](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L187) | The refactored function calls mdns_priv_pcb_send_bye_service instead of _mdns_send_bye, which appears to be a renamed function. The behavior should be verified to ensure the new function maintains the same functionality as the original. | +| [_mdns_restart_all_pcbs_no_instance](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2582) | [mdns_priv_restart_all_pcbs_no_instance](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L212) | | +| [_mdns_restart_all_pcbs](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2610) | [mdns_priv_restart_all_pcbs](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L237) | | +| [_mdns_allocate_txt](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2643) | [allocate_txt](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L268) | | +| [_mdns_free_linked_txt](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2677) | [free_linked_txt](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L302) | | +| [_mdns_create_service](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2701) | [create_service](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L326) | | +| [_mdns_dealloc_scheduled_service_answers](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2757) | [dealloc_scheduled_service_answers](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1741) | | +| [_mdns_remove_scheduled_service_packets](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2782) | [mdns_priv_remove_scheduled_service_packets](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mock_mdns_send.c#L2171) | The refactored function extracts the PCB state checking logic into mdns_priv_pcb_check_probing_services, which is good for modularity. However, we should verify that this new function handles all the PCB state transitions (PROBING/ANNOUNCING/RUNNING) correctly, particularly the case where had_answers && q->answers == NULL should transition to PCB_RUNNING state during ANNOUNCING. | +| [_mdns_free_subtype](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2863) | [free_subtype](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L379) | | +| [_mdns_free_service_subtype](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2873) | [free_service_subtype](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L389) | | +| [_mdns_free_service](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2884) | [free_service](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L400) | | +| [_mdns_check_srv_collision](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2912) | [check_srv_collision](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L437) | | +| [_mdns_check_txt_collision](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L2969) | [check_txt_collision](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L392) | | +| [mdns_pcb_deinit_local](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3011) | [deinit_pcb](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_pcb.c#L107) | The refactored function uses a different global variable name (s_pcbs instead of _mdns_server->interfaces) and calls mdns_priv_if_deinit instead of _mdns_pcb_deinit. While functionally equivalent, this could cause issues if the global state structure was changed in other ways. | +| [_mdns_dup_interface](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3030) | [mdns_priv_pcb_set_duplicate](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_pcb.c#L186) | | +| [_mdns_check_a_collision](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3054) | [check_a_collision](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L321) | | +| [_mdns_check_aaaa_collision](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3090) | [check_aaaa_collision](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L357) | | +| [_hostname_is_ours](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3122) | [mdns_utils_hostname_is_ours](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L103) | | +| [_mdns_delegate_hostname_add](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3145) | [mdns_priv_delegate_hostname_add](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L420) | | +| [free_address_list](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3163) | [mdns_utils_free_address_list](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L236) | | +| [_mdns_delegate_hostname_set_address](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3173) | [delegate_hostname_set_address](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L438) | | +| [copy_address_list](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3193) | [mdns_utils_copy_address_list](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L212) | | +| [free_delegated_hostnames](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3217) | [free_delegated_hostnames](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L48) | The refactored function now uses s_server->host_list instead of _mdns_host_list, which appears to be a structural change in how the host list is accessed. This is likely safe if s_server is properly initialized, but could cause issues if s_server is NULL. | +| [_mdns_delegate_hostname_remove](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3230) | [delegate_hostname_remove](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L458) | | +| [_mdns_name_is_discovery](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3277) | [is_discovery](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L27) | | +| [_mdns_name_is_selfhosted](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3291) | [is_name_selfhosted](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L494) | | +| [_mdns_name_is_ours](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3314) | [is_ours](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L59) | | +| [_mdns_read_u16](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3380) | [mdns_utils_read_u16](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.h#L18) | | +| [_mdns_read_u32](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3392) | [mdns_utils_read_u32](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.h#L30) | | +| [_mdns_parse_fqdn](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3406) | [mdns_utils_parse_fqdn](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_utils.c#L69) | | +| [_mdns_question_matches](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3443) | [question_matches](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L517) | The refactored function uses MDNS_UTILS_DEFAULT_DOMAIN instead of MDNS_DEFAULT_DOMAIN, which might be intentional but could potentially cause compatibility issues if these constants have different values. | +| [_mdns_remove_parsed_question](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3478) | [remove_parsed_question](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L552) | | +| [_mdns_txt_items_count_get](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3510) | [get_txt_items_count](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L180) | | +| [_mdns_txt_item_name_get_len](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3537) | [get_txt_item_len](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L207) | | +| [_mdns_result_txt_create](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3553) | [result_txt_create](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L223) | | +| [_mdns_strdup_check](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3649) | [strdup_check](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L121) | | +| [mdns_parse_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L3667) | [mdns_parse_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_receive.c#L586) | The refactored function has been made static, which might limit its accessibility if it needs to be called from other files. Also, several internal function calls have been renamed (e.g., _mdns_get_packet_data to mdns_priv_get_packet_data), which could potentially affect functionality if the new functions don't behave exactly the same way. | +| [_mdns_enable_pcb](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4357) | [mdns_priv_pcb_enable](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_pcb.c#L172) | | +| [_mdns_disable_pcb](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4371) | [mdns_priv_pcb_disable](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_pcb.c#L153) | | +| [nibble_to_hex](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4388) | [nibble_to_hex](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L38) | | +| [perform_event_action](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4397) | [perform_event_action](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L47) | | +| [post_mdns_disable_pcb](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4468) | [post_disable_pcb](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L184) | | +| [post_mdns_enable_pcb](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4473) | [post_enable_pcb](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L190) | | +| [post_mdns_announce_pcb](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4478) | [post_announce_pcb](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L196) | | +| [mdns_preset_if_handle_system_event](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4484) | [handle_system_event_for_preset](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L203) | | +| [_mdns_search_free](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4577) | [search_free](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L341) | | +| [_mdns_search_init](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4589) | [search_init](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L353) | | +| [_mdns_search_finish](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4647) | [search_finish](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L57) | | +| [_mdns_search_add](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4660) | [search_add](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L70) | | +| [_mdns_search_finish_done](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4669) | [mdns_priv_query_done](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L179) | | +| [_mdns_search_finish_done](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4669) | [search_finish](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L57) | | +| [_mdns_result_addr_create_ip](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4685) | [mdns_priv_result_addr_create_ip](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L651) | | +| [_mdns_result_update_ttl](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4702) | [mdns_priv_query_update_result_ttl](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.h#L99) | | +| [_mdns_result_add_ip](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4710) | [result_add_ip](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L483) | | +| [_mdns_search_result_add_ip](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4739) | [mdns_priv_query_result_add_ip](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L512) | | +| [_mdns_search_result_add_ptr](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4797) | [mdns_priv_query_result_add_ptr](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L612) | | +| [_mdns_search_result_add_srv](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4839) | [mdns_priv_query_result_add_srv](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L570) | | +| [_mdns_search_result_add_txt](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4881) | [mdns_priv_query_result_add_txt](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L433) | | +| [_mdns_search_find_from](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4931) | [mdns_priv_query_find_from](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L195) | | +| [_mdns_create_search_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L4998) | [create_search_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L267) | | +| [_mdns_search_send_pcb](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5055) | [mdns_priv_query_send](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L325) | | +| [_mdns_search_send](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5071) | [search_send](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L79) | | +| [_mdns_tx_handle_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5097) | [handle_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1815) | | +| [_mdns_tx_handle_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5097) | [mdns_priv_pcb_schedule_tx_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_pcb.c#L211) | | +| [_mdns_remap_self_service_hostname](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5154) | [mdns_priv_remap_self_service_hostname](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L502) | | +| [_mdns_sync_browse_result_link_free](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5168) | [sync_browse_result_link_free](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L234) | | +| [_mdns_free_action](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5183) | [_mdns_free_action](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L120) | The refactored version delegates cleanup to specialized functions (mdns_priv_*_action) instead of directly freeing resources. While this is likely correct, we should verify that these helper functions properly handle all the cases that were previously handled directly (like mdns_mem_free for hostnames and free_address_list for delegate hostnames). | +| [_mdns_execute_action](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5230) | [_mdns_execute_action](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L155) | The refactored version delegates all action handling to helper functions (mdns_priv_*_action) rather than directly implementing the logic. While this improves modularity, we should verify that all the original functionality (particularly the hostname/instance setting logic and semaphore handling) is properly implemented in these helper functions. | +| [_mdns_send_search_action](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5317) | [send_search_action](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L411) | The refactored function uses mdns_priv_queue_action instead of directly using xQueueSend on _mdns_server->action_queue. While this is likely an abstraction improvement, we should verify that mdns_priv_queue_action properly handles the queue operation with the same semantics (particularly the (TickType_t)0 timeout behavior). | +| [_mdns_scheduler_run](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5343) | [mdns_priv_send_packets](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_send.c#L1702) | The refactored function uses mdns_priv_queue_action() instead of directly calling xQueueSend(), which appears to be a wrapper function. While this is likely safe, we should verify that mdns_priv_queue_action() maintains the same behavior as the original xQueueSend() call with (TickType_t)0 timeout. | +| [_mdns_search_run](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5380) | [mdns_priv_query_start_stop](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L131) | | +| [_mdns_service_task](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5412) | [_mdns_service_task](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L194) | | +| [_mdns_timer_cb](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5434) | [_mdns_timer_cb](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L216) | The refactored function calls different internal functions (mdns_priv_send_packets and mdns_priv_query_start_stop) compared to the original (_mdns_scheduler_run and _mdns_search_run). This might indicate a functional change in the timer callback behavior. | +| [_mdns_start_timer](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5440) | [_mdns_start_timer](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L222) | | +| [_mdns_stop_timer](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5455) | [_mdns_stop_timer](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L237) | | +| [_mdns_task_create_with_caps](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5468) | [_mdns_task_create_with_caps](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L250) | | +| [_mdns_service_task_start](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5493) | [_mdns_service_task_start](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L275) | | +| [_mdns_service_task_stop](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5532) | [_mdns_service_task_stop](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L312) | The refactored version uses 's_action_queue' instead of '_mdns_server->action_queue' which might be a bug if these are not equivalent variables. | +| [mdns_post_custom_action_tcpip_if](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5553) | [post_custom_action](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L159) | | +| [set_default_duplicated_interfaces](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5574) | [set_default_duplicated_interfaces](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L287) | | +| [unregister_predefined_handlers](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5592) | [mdns_priv_netif_unregister_predefined_handlers](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L305) | The event handler function name changed from mdns_preset_if_handle_system_event to handle_system_event_for_preset. Need to verify this is an intentional rename and the new function has equivalent functionality. | +| [mdns_netif_action](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5609) | [mdns_netif_action](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L387) | The refactored version uses renamed functions (post_custom_action and get_if_from_netif) instead of the original mdns_post_custom_action_tcpip_if and _mdns_get_if_from_esp_netif. While this appears to be a simple rename, we should verify these functions are equivalent in behavior. | +| [mdns_register_netif](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5614) | [mdns_register_netif](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L392) | | +| [mdns_unregister_netif](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5640) | [mdns_unregister_netif](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L418) | The refactored function calls mdns_priv_service_lock() twice (at the beginning and at the end) instead of calling mdns_priv_service_unlock() at the end, which would cause a deadlock. | +| [mdns_init](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5660) | [mdns_init](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L343) | The error handling flow has changed - in the original code, if _mdns_service_task_start() fails, it would disable all PCBs, but in the refactored version this cleanup is handled by mdns_priv_netif_deinit() which might have different behavior. | +| [mdns_init](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5660) | [mdns_priv_netif_init](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_netif.c#L318) | The error handling flow has changed - in the original code, if _mdns_service_task_start() fails, it would disable all PCBs, but in the refactored version this cleanup is handled by mdns_priv_netif_deinit() which might have different behavior. | +| [mdns_init](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5660) | [mdns_priv_responder_init](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L30) | The error handling flow has changed - in the original code, if _mdns_service_task_start() fails, it would disable all PCBs, but in the refactored version this cleanup is handled by mdns_priv_netif_deinit() which might have different behavior. | +| [mdns_free](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5758) | [mdns_free](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_service.c#L383) | The refactored version doesn't explicitly show the cleanup of search_once and browse items in the main mdns_free function, though they might be handled by mdns_priv_query_free and mdns_priv_browse_free respectively. | +| [mdns_free](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5758) | [mdns_priv_responder_free](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L61) | The refactored version doesn't explicitly show the cleanup of search_once and browse items in the main mdns_free function, though they might be handled by mdns_priv_query_free and mdns_priv_browse_free respectively. | +| [mdns_hostname_set](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5811) | [mdns_hostname_set](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L585) | The refactored version uses mdns_priv_queue_action instead of directly calling xQueueSend, which is likely an improvement, but we should verify that mdns_priv_queue_action properly handles the queue operation and error cases. | +| [mdns_hostname_get](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5841) | [mdns_hostname_get](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L615) | The lock/unlock macros MDNS_SERVICE_LOCK/UNLOCK were renamed to mdns_priv_service_lock/unlock, and the global variable _mdns_server was renamed to s_server. While functionally equivalent, this could cause issues if other parts of the codebase still reference the old names. | +| [mdns_delegate_hostname_add](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5859) | [mdns_delegate_hostname_add](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L633) | The refactored version uses mdns_utils_copy_address_list instead of copy_address_list, and mdns_priv_queue_action instead of direct xQueueSend. While these appear to be safe changes (likely just internal function renames), we should verify that these helper functions maintain the same behavior as the original implementations. | +| [mdns_delegate_hostname_remove](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5890) | [mdns_delegate_hostname_remove](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L664) | The refactored function uses mdns_priv_queue_action instead of directly using xQueueSend, which is likely an improvement, but we should verify that mdns_priv_queue_action properly handles the queue operations and error cases. | +| [mdns_delegate_hostname_set_address](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5919) | [mdns_delegate_hostname_set_address](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L693) | The refactored version uses mdns_priv_queue_action instead of directly calling xQueueSend, which is likely fine but should be verified that it maintains the same timeout behavior (TickType_t)0. | +| [mdns_hostname_exists](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5949) | [mdns_hostname_exists](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L723) | | +| [mdns_instance_name_set](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5958) | [mdns_instance_name_set](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L732) | The refactored version uses a different queue action function (mdns_priv_queue_action) instead of directly using xQueueSend, which appears to be a safe change, but the error handling behavior should be verified to be equivalent. | +| [mdns_service_add_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L5991) | [mdns_service_add_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L761) | | +| [mdns_service_add](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6033) | [mdns_service_add](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L803) | | +| [mdns_service_exists](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6042) | [mdns_service_exists](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L812) | | +| [mdns_service_exists_with_instance](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6051) | [mdns_service_exists_with_instance](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L821) | | +| [_copy_mdns_txt_items](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6061) | [copy_txt_items](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L831) | | +| [_copy_delegated_host_address_list](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6114) | [copy_delegated_host_address_list](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L884) | | +| [_mdns_lookup_service](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6126) | [lookup_service](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_console.c#L1139) | | +| [mdns_service_port_set_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6206) | [mdns_service_port_set_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L976) | | +| [mdns_service_port_set](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6224) | [mdns_service_port_set](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L994) | | +| [mdns_service_txt_set_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6232) | [mdns_service_txt_set_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1002) | | +| [mdns_service_txt_set](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6262) | [mdns_service_txt_set](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1032) | | +| [mdns_service_txt_item_set_for_host_with_explicit_value_len](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6270) | [mdns_service_txt_item_set_for_host_with_explicit_value_len](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1040) | The refactored version uses different lock/unlock function names (mdns_priv_service_lock/unlock instead of MDNS_SERVICE_LOCK/UNLOCK) and different variable names (s_server instead of _mdns_server). While functionally equivalent, this could cause issues if there are macro dependencies elsewhere in the code. | +| [mdns_service_txt_item_set_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6326) | [mdns_service_txt_item_set_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1096) | | +| [mdns_service_txt_item_set](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6334) | [mdns_service_txt_item_set](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1104) | | +| [mdns_service_txt_item_set_with_explicit_value_len](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6343) | [mdns_service_txt_item_set_with_explicit_value_len](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1113) | | +| [mdns_service_txt_item_remove_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6352) | [mdns_service_txt_item_remove_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1122) | | +| [mdns_service_txt_item_remove](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6399) | [mdns_service_txt_item_remove](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1169) | | +| [_mdns_service_subtype_remove_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6407) | [service_subtype_remove_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1177) | | +| [mdns_service_subtype_remove_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6436) | [mdns_service_subtype_remove_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1206) | | +| [_mdns_service_subtype_add_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6469) | [service_subtype_add_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1239) | | +| [mdns_service_subtype_add_multiple_items_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6493) | [mdns_service_subtype_add_multiple_items_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1263) | | +| [mdns_service_subtype_add_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6530) | [mdns_service_subtype_add_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1300) | | +| [_mdns_service_find_subtype_needed_sendbye](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6538) | [service_find_subtype_needed_sendbye](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1308) | | +| [mdns_service_subtype_update_multiple_items_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6588) | [mdns_service_subtype_update_multiple_items_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1358) | | +| [mdns_service_instance_name_set_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6635) | [mdns_service_instance_name_set_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1405) | | +| [mdns_service_instance_name_set](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6661) | [mdns_service_instance_name_set](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1431) | | +| [mdns_service_remove_for_host](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6669) | [mdns_service_remove_for_host](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1439) | | +| [mdns_service_remove](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6722) | [mdns_service_remove](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1492) | | +| [mdns_service_remove_all](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6730) | [mdns_service_remove_all](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1500) | | +| [mdns_query_results_free](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6758) | [mdns_query_results_free](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L671) | | +| [_mdns_query_results_free](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6765) | [mdns_priv_query_results_free](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L23) | | +| [mdns_query_async_delete](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6796) | [mdns_query_async_delete](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L678) | The lock/unlock functions were renamed from MDNS_SERVICE_LOCK/UNLOCK to mdns_priv_service_lock/unlock, and _mdns_search_free was renamed to search_free. While functionally equivalent, these changes should be verified to ensure they maintain the same locking semantics and memory management behavior. | +| [mdns_query_async_get_results](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6812) | [mdns_query_async_get_results](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L694) | | +| [mdns_query_async_new](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6826) | [mdns_query_async_new](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L708) | | +| [mdns_query_generic](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6848) | [mdns_query_generic](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L730) | | +| [mdns_query](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6879) | [mdns_query](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L762) | | +| [mdns_query_ptr](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6884) | [mdns_query_ptr](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L767) | | +| [mdns_query_srv](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6893) | [mdns_query_srv](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L776) | | +| [mdns_query_txt](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6902) | [mdns_query_txt](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L785) | | +| [mdns_lookup_delegated_service](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6911) | [mdns_lookup_delegated_service](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1525) | | +| [mdns_lookup_selfhosted_service](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6926) | [mdns_lookup_selfhosted_service](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_responder.c#L1540) | | +| [mdns_query_a](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6942) | [mdns_query_a](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L795) | | +| [mdns_query_aaaa](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L6981) | [mdns_query_aaaa](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_querier.c#L834) | | +| [mdns_debug_packet](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7021) | [dbg_packet](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_debug.c#L17) | The function was renamed from mdns_debug_packet to dbg_packet and made static, which might affect its visibility in the codebase. Also, the debug print function was renamed from _mdns_dbg_printf to dbg_printf, and utility functions were renamed from _mdns_* to mdns_utils_*. These changes should be verified for consistency across the codebase. | +| [_mdns_sync_browse_action](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7251) | [mdns_priv_browse_sync](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L593) | | +| [_mdns_send_browse_action](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7273) | [send_browse_action](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L25) | The queue action check changed from direct xQueueSend to mdns_priv_queue_action wrapper. Need to verify mdns_priv_queue_action handles the queue operation correctly. | +| [_mdns_browse_item_free](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7296) | [browse_item_free](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L48) | | +| [_mdns_browse_init](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7309) | [browse_init](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L140) | | +| [mdns_browse_new](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7340) | [mdns_browse_new](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L615) | The condition in the refactored mdns_browse_new function checks `mdns_priv_is_server_init()` which returns true when server is initialized, while the original checked `!_mdns_server` which returns true when server is NOT initialized. This logic appears to be inverted. | +| [mdns_browse_delete](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7361) | [mdns_browse_delete](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L636) | | +| [_mdns_browse_finish](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7384) | [browse_finish](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L118) | | +| [_mdns_browse_add](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7406) | [browse_add](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L174) | The global variable _mdns_server->browse has been replaced with s_browse, which might indicate a change in how the browse list is managed. Ensure this change is intentional and properly handled throughout the codebase. | +| [_mdns_browse_send](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7435) | [browse_send](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L79) | | +| [_mdns_add_browse_result](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7456) | [add_browse_result](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L286) | | +| [_mdns_browse_result_add_ip](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7483) | [mdns_priv_browse_result_add_ip](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L313) | | +| [_mdns_browse_find_from](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7548) | [mdns_priv_browse_find](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L203) | | +| [is_txt_item_in_list](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7578) | [is_txt_item_in_list](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L374) | | +| [_mdns_browse_result_add_txt](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7596) | [mdns_priv_browse_result_add_txt](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L392) | | +| [_mdns_copy_address_in_previous_result](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7694) | [copy_address_in_previous_result](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L490) | | +| [_mdns_browse_result_add_srv](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7715) | [mdns_priv_browse_result_add_srv](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L511) | | +| [_mdns_browse_sync](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7795) | [browse_sync](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_browser.c#L58) | | +| [_debug_printf_result](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7816) | [dbg_printf_result](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_debug.c#L275) | | +| [debug_printf_browse_result](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7847) | [mdns_debug_printf_browse_result](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_debug.c#L306) | | +| [debug_printf_browse_result_all](https://github.com/espressif/esp-protocols/blob/master/components/mdns/mdns.c#L7854) | [mdns_debug_printf_browse_result_all](https://github.com/espressif/esp-protocols/blob/48fef6ffbedde8f019b3aca0af57cac91e65560c/components/mdns/mdns_debug.c#L313) | | From ed87fa2574911d8f39e0c56178aebcea3dccd649 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 4 Apr 2025 10:54:57 +0200 Subject: [PATCH 24/27] fix(mdns): Add data-flow diagram --- components/mdns/mdns_browser.c | 2 +- components/mdns/mdns_debug.c | 1 + components/mdns/mdns_diagram.md | 51 ++++++++++ components/mdns/mdns_netif.c | 1 + components/mdns/mdns_networking_lwip.c | 1 + components/mdns/mdns_networking_socket.c | 1 + components/mdns/mdns_querier.c | 1 + components/mdns/mdns_responder.c | 1 + components/mdns/mdns_send.c | 1 + components/mdns/mdns_service.c | 99 ++++++++++--------- .../mdns/private_include/mdns_private.h | 34 +------ .../mdns/private_include/mdns_service.h | 32 ++++++ .../host_unit_test/stubs/mdns_networking.c | 1 + 13 files changed, 145 insertions(+), 81 deletions(-) create mode 100644 components/mdns/mdns_diagram.md create mode 100644 components/mdns/private_include/mdns_service.h diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index 1e50271617..f42f68edd3 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -6,13 +6,13 @@ #include #include "mdns_private.h" #include "mdns_browser.h" -#include "mdns_send.h" #include "mdns_mem_caps.h" #include "mdns_debug.h" #include "mdns_utils.h" #include "mdns_querier.h" #include "mdns_responder.h" #include "mdns_netif.h" +#include "mdns_service.h" #include "esp_log.h" static const char *TAG = "mdns_browser"; diff --git a/components/mdns/mdns_debug.c b/components/mdns/mdns_debug.c index 6a485a41fb..a620577d70 100644 --- a/components/mdns/mdns_debug.c +++ b/components/mdns/mdns_debug.c @@ -8,6 +8,7 @@ #include #include #include +#include "freertos/FreeRTOS.h" #include "sdkconfig.h" #include "mdns_private.h" #include "mdns_utils.h" diff --git a/components/mdns/mdns_diagram.md b/components/mdns/mdns_diagram.md new file mode 100644 index 0000000000..b17797df97 --- /dev/null +++ b/components/mdns/mdns_diagram.md @@ -0,0 +1,51 @@ +```mermaid +graph TB + %% Housekeeping modules at the top + subgraph Housekeeping [Support Modules] + Service[mdns_service.c] + Utils[mdns_utils.c] + MemCaps[mdns_mem_caps.c] + Debug[mdns_debug.c] + end + + %% Switch to LR direction for the main flow + subgraph MainFlow [Main Data Flow] + direction LR + + %% Network on left side + Network((Network)) <--> Networking + + %% Networking layer + subgraph Networking [Networking Layer] + LWIP[mdns_networking_lwip.c] + Socket[mdns_networking_socket.c] + end + + %% Traffic flow + Networking --> |Incoming| Receive[mdns_receive.c] + Send[mdns_send.c] --> |Outgoing| Networking + + %% Core MDNS components + Receive --> Responder[mdns_responder.c] + Receive --> Browser[mdns_browser.c] + Receive --> Querier[mdns_querier.c] + + Responder --> Send + Browser --> Send + Querier --> Send + + PCB[mdns_pcb.c] --> Send + NetIF[mdns_netif.c] + + %% Users on the right side, aligned vertically + Responder --> Advertise((User: Advertising)) + Querier --> Search((User: Searching)) + Browser --> Browse((User: Browsing)) + end + + %% Style user nodes + style Advertise fill:#f9f,stroke:#333,stroke-width:2px + style Search fill:#f9f,stroke:#333,stroke-width:2px + style Browse fill:#f9f,stroke:#333,stroke-width:2px + style Housekeeping fill:#e6f7ff,stroke:#333,stroke-width:1px +``` diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c index 88ead18e8a..eb7e6b476a 100644 --- a/components/mdns/mdns_netif.c +++ b/components/mdns/mdns_netif.c @@ -17,6 +17,7 @@ #include "mdns_netif.h" #include "mdns_pcb.h" #include "mdns_responder.h" +#include "mdns_service.h" static const char *TAG = "mdns_netif"; diff --git a/components/mdns/mdns_networking_lwip.c b/components/mdns/mdns_networking_lwip.c index a3a0bf34ef..373d957a9c 100644 --- a/components/mdns/mdns_networking_lwip.c +++ b/components/mdns/mdns_networking_lwip.c @@ -21,6 +21,7 @@ #include "mdns_mem_caps.h" #include "mdns_utils.h" #include "mdns_netif.h" +#include "mdns_service.h" /* * MDNS Server Networking diff --git a/components/mdns/mdns_networking_socket.c b/components/mdns/mdns_networking_socket.c index 61124126f9..ee6e1b5ffa 100644 --- a/components/mdns/mdns_networking_socket.c +++ b/components/mdns/mdns_networking_socket.c @@ -24,6 +24,7 @@ #include "mdns_mem_caps.h" #include "mdns_utils.h" #include "mdns_netif.h" +#include "mdns_service.h" #if defined(CONFIG_IDF_TARGET_LINUX) #include diff --git a/components/mdns/mdns_querier.c b/components/mdns/mdns_querier.c index 70cfc59ec5..d61cb06ebe 100644 --- a/components/mdns/mdns_querier.c +++ b/components/mdns/mdns_querier.c @@ -13,6 +13,7 @@ #include "mdns_pcb.h" #include "mdns_netif.h" #include "mdns_responder.h" +#include "mdns_service.h" static const char *TAG = "mdns_querier"; static mdns_search_once_t *s_search_once; diff --git a/components/mdns/mdns_responder.c b/components/mdns/mdns_responder.c index 43591fab8c..05469212cc 100644 --- a/components/mdns/mdns_responder.c +++ b/components/mdns/mdns_responder.c @@ -14,6 +14,7 @@ #include "mdns_send.h" #include "mdns_querier.h" #include "mdns_pcb.h" +#include "mdns_service.h" typedef struct mdns_server_s { const char *hostname; diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index e3a9ab616c..a02ef0b5bd 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -15,6 +15,7 @@ #include "mdns_netif.h" #include "mdns_pcb.h" #include "mdns_responder.h" +#include "mdns_service.h" static const char *TAG = "mdns_send"; static const char *MDNS_SUB_STR = "_sub"; diff --git a/components/mdns/mdns_service.c b/components/mdns/mdns_service.c index cc523a2aec..6aee2fba9f 100644 --- a/components/mdns/mdns_service.c +++ b/components/mdns/mdns_service.c @@ -5,18 +5,14 @@ */ #include #include "mdns_private.h" -#include "mdns_networking.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "freertos/semphr.h" #include "esp_check.h" #include "mdns.h" -#include "mdns_private.h" -#include "mdns_networking.h" #include "mdns_mem_caps.h" #include "mdns_utils.h" -#include "mdns_debug.h" #include "mdns_browser.h" #include "mdns_netif.h" #include "mdns_send.h" @@ -25,10 +21,21 @@ #include "mdns_pcb.h" #include "mdns_responder.h" +#define MDNS_SERVICE_STACK_DEPTH CONFIG_MDNS_TASK_STACK_SIZE +#define MDNS_TASK_PRIORITY CONFIG_MDNS_TASK_PRIORITY +#if (MDNS_TASK_PRIORITY > ESP_TASK_PRIO_MAX) +#error "mDNS task priority is higher than ESP_TASK_PRIO_MAX" +#elif (MDNS_TASK_PRIORITY > ESP_TASKD_EVENT_PRIO) +#warning "mDNS task priority is higher than ESP_TASKD_EVENT_PRIO, mDNS library might not work correctly" +#endif +#define MDNS_TASK_AFFINITY CONFIG_MDNS_TASK_AFFINITY + +#define MDNS_SERVICE_LOCK() xSemaphoreTake(s_service_semaphore, portMAX_DELAY) +#define MDNS_SERVICE_UNLOCK() xSemaphoreGive(s_service_semaphore) -static volatile TaskHandle_t _mdns_service_task_handle = NULL; -static SemaphoreHandle_t _mdns_service_semaphore = NULL; -static StackType_t *_mdns_stack_buffer; +static volatile TaskHandle_t s_service_task_handle = NULL; +static SemaphoreHandle_t s_service_semaphore = NULL; +static StackType_t *s_stack_buffer; static QueueHandle_t s_action_queue; static esp_timer_handle_t s_timer_handle; @@ -112,12 +119,10 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) #endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ } - - /** * @brief Free action data */ -static void _mdns_free_action(mdns_action_t *action) +static void free_action(mdns_action_t *action) { switch (action->type) { case ACTION_SEARCH_ADD: @@ -152,7 +157,7 @@ static void _mdns_free_action(mdns_action_t *action) /** * @brief Called from service thread to execute given action */ -static void _mdns_execute_action(mdns_action_t *action) +static void execute_action(mdns_action_t *action) { switch (action->type) { case ACTION_SYSTEM_EVENT: @@ -191,7 +196,7 @@ static void _mdns_execute_action(mdns_action_t *action) /** * @brief the main MDNS service task. Packets are received and parsed here */ -static void _mdns_service_task(void *pvParameters) +static void service_task(void *pvParameters) { mdns_action_t *a = NULL; for (;;) { @@ -202,27 +207,27 @@ static void _mdns_service_task(void *pvParameters) break; } MDNS_SERVICE_LOCK(); - _mdns_execute_action(a); + execute_action(a); MDNS_SERVICE_UNLOCK(); } } else { vTaskDelay(500 * portTICK_PERIOD_MS); } } - _mdns_service_task_handle = NULL; + s_service_task_handle = NULL; vTaskDelay(portMAX_DELAY); } -static void _mdns_timer_cb(void *arg) +static void timer_cb(void *arg) { mdns_priv_send_packets(); mdns_priv_query_start_stop(); } -static esp_err_t _mdns_start_timer(void) +static esp_err_t start_timer(void) { esp_timer_create_args_t timer_conf = { - .callback = _mdns_timer_cb, + .callback = timer_cb, .arg = NULL, .dispatch_method = ESP_TIMER_TASK, .name = "mdns_timer" @@ -234,7 +239,7 @@ static esp_err_t _mdns_start_timer(void) return esp_timer_start_periodic(s_timer_handle, MDNS_TIMER_PERIOD_US); } -static esp_err_t _mdns_stop_timer(void) +static esp_err_t stop_timer(void) { esp_err_t err = ESP_OK; if (s_timer_handle) { @@ -247,21 +252,21 @@ static esp_err_t _mdns_stop_timer(void) return err; } -static esp_err_t _mdns_task_create_with_caps(void) +static esp_err_t create_task_with_caps(void) { esp_err_t ret = ESP_OK; static StaticTask_t mdns_task_buffer; - _mdns_stack_buffer = mdns_mem_task_malloc(MDNS_SERVICE_STACK_DEPTH); - ESP_GOTO_ON_FALSE(_mdns_stack_buffer != NULL, ESP_FAIL, err, TAG, "failed to allocate memory for the mDNS task's stack"); + s_stack_buffer = mdns_mem_task_malloc(MDNS_SERVICE_STACK_DEPTH); + ESP_GOTO_ON_FALSE(s_stack_buffer != NULL, ESP_FAIL, err, TAG, "failed to allocate memory for the mDNS task's stack"); - _mdns_service_task_handle = xTaskCreateStaticPinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, MDNS_TASK_PRIORITY, _mdns_stack_buffer, &mdns_task_buffer, MDNS_TASK_AFFINITY); - ESP_GOTO_ON_FALSE(_mdns_service_task_handle != NULL, ESP_FAIL, err, TAG, "failed to create task for the mDNS"); + s_service_task_handle = xTaskCreateStaticPinnedToCore(service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, MDNS_TASK_PRIORITY, s_stack_buffer, &mdns_task_buffer, MDNS_TASK_AFFINITY); + ESP_GOTO_ON_FALSE(s_service_task_handle != NULL, ESP_FAIL, err, TAG, "failed to create task for the mDNS"); return ret; err: - mdns_mem_task_free(_mdns_stack_buffer); + mdns_mem_task_free(s_stack_buffer); return ret; } @@ -272,22 +277,22 @@ static esp_err_t _mdns_task_create_with_caps(void) * - ESP_OK on success * - ESP_FAIL on error */ -static esp_err_t _mdns_service_task_start(void) +static esp_err_t service_task_start(void) { esp_err_t ret = ESP_OK; - if (!_mdns_service_semaphore) { - _mdns_service_semaphore = xSemaphoreCreateMutex(); - ESP_RETURN_ON_FALSE(_mdns_service_semaphore != NULL, ESP_FAIL, TAG, "Failed to create the mDNS service lock"); + if (!s_service_semaphore) { + s_service_semaphore = xSemaphoreCreateMutex(); + ESP_RETURN_ON_FALSE(s_service_semaphore != NULL, ESP_FAIL, TAG, "Failed to create the mDNS service lock"); } MDNS_SERVICE_LOCK(); - ESP_GOTO_ON_ERROR(_mdns_start_timer(), err, TAG, "Failed to start the mDNS service timer"); + ESP_GOTO_ON_ERROR(start_timer(), err, TAG, "Failed to start the mDNS service timer"); - if (!_mdns_service_task_handle) { - ESP_GOTO_ON_ERROR(_mdns_task_create_with_caps(), err_stop_timer, TAG, "Failed to start the mDNS service task"); + if (!s_service_task_handle) { + ESP_GOTO_ON_ERROR(create_task_with_caps(), err_stop_timer, TAG, "Failed to start the mDNS service task"); #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) && !CONFIG_IDF_TARGET_LINUX StackType_t *mdns_debug_stack_buffer; StaticTask_t *mdns_debug_task_buffer; - xTaskGetStaticBuffers(_mdns_service_task_handle, &mdns_debug_stack_buffer, &mdns_debug_task_buffer); + xTaskGetStaticBuffers(s_service_task_handle, &mdns_debug_stack_buffer, &mdns_debug_task_buffer); ESP_LOGD(TAG, "mdns_debug_stack_buffer:%p mdns_debug_task_buffer:%p\n", mdns_debug_stack_buffer, mdns_debug_task_buffer); #endif // CONFIG_IDF_TARGET_LINUX } @@ -295,11 +300,11 @@ static esp_err_t _mdns_service_task_start(void) return ret; err_stop_timer: - _mdns_stop_timer(); + stop_timer(); err: MDNS_SERVICE_UNLOCK(); - vSemaphoreDelete(_mdns_service_semaphore); - _mdns_service_semaphore = NULL; + vSemaphoreDelete(s_service_semaphore); + s_service_semaphore = NULL; return ret; } @@ -309,24 +314,24 @@ static esp_err_t _mdns_service_task_start(void) * @return * - ESP_OK */ -static esp_err_t _mdns_service_task_stop(void) +static esp_err_t service_task_stop(void) { - _mdns_stop_timer(); - if (_mdns_service_task_handle) { - TaskHandle_t task_handle = _mdns_service_task_handle; + stop_timer(); + if (s_service_task_handle) { + TaskHandle_t task_handle = s_service_task_handle; mdns_action_t action; mdns_action_t *a = &action; action.type = ACTION_TASK_STOP; if (xQueueSend(s_action_queue, &a, (TickType_t)0) != pdPASS) { - _mdns_service_task_handle = NULL; + s_service_task_handle = NULL; } - while (_mdns_service_task_handle) { + while (s_service_task_handle) { vTaskDelay(10 / portTICK_PERIOD_MS); } vTaskDelete(task_handle); } - vSemaphoreDelete(_mdns_service_semaphore); - _mdns_service_semaphore = NULL; + vSemaphoreDelete(s_service_semaphore); + s_service_semaphore = NULL; return ESP_OK; } @@ -363,7 +368,7 @@ esp_err_t mdns_init(void) goto free_queue; } - if (_mdns_service_task_start()) { + if (service_task_start()) { //service start failed! err = ESP_FAIL; goto free_all_and_disable_pcbs; @@ -390,14 +395,14 @@ void mdns_free(void) mdns_priv_netif_unregister_predefined_handlers(); mdns_service_remove_all(); - _mdns_service_task_stop(); + service_task_stop(); // at this point, the service task is deleted, so we can destroy the stack size - mdns_mem_task_free(_mdns_stack_buffer); + mdns_mem_task_free(s_stack_buffer); mdns_priv_pcb_deinit(); if (s_action_queue) { mdns_action_t *c; while (xQueueReceive(s_action_queue, &c, 0) == pdTRUE) { - _mdns_free_action(c); + free_action(c); } vQueueDelete(s_action_queue); } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 15fba8a23d..616b55778b 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -3,8 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#ifndef MDNS_PRIVATE_H_ -#define MDNS_PRIVATE_H_ +#pragma once #include "sdkconfig.h" #include "mdns.h" @@ -85,14 +84,6 @@ #define MDNS_ANSWER_AAAA_SIZE 16 #define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on -#define MDNS_SERVICE_STACK_DEPTH CONFIG_MDNS_TASK_STACK_SIZE -#define MDNS_TASK_PRIORITY CONFIG_MDNS_TASK_PRIORITY -#if (MDNS_TASK_PRIORITY > ESP_TASK_PRIO_MAX) -#error "mDNS task priority is higher than ESP_TASK_PRIO_MAX" -#elif (MDNS_TASK_PRIORITY > ESP_TASKD_EVENT_PRIO) -#warning "mDNS task priority is higher than ESP_TASKD_EVENT_PRIO, mDNS library might not work correctly" -#endif -#define MDNS_TASK_AFFINITY CONFIG_MDNS_TASK_AFFINITY #define MDNS_SERVICE_ADD_TIMEOUT_MS CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS #define MDNS_PACKET_QUEUE_LEN 16 // Maximum packets that can be queued for parsing @@ -121,9 +112,6 @@ #define MDNS_TIMER_PERIOD_US (CONFIG_MDNS_TIMER_PERIOD_MS*1000) -#define MDNS_SERVICE_LOCK() xSemaphoreTake(_mdns_service_semaphore, portMAX_DELAY) -#define MDNS_SERVICE_UNLOCK() xSemaphoreGive(_mdns_service_semaphore) - #define queueToEnd(type, queue, item) \ if (!queue) { \ queue = item; \ @@ -416,23 +404,3 @@ typedef struct { } browse_sync; } data; } mdns_action_t; - - -/** - * @brief Lock mdns service - */ -void mdns_priv_service_lock(void); - -/** - * @brief Unlock mdns service - */ -void mdns_priv_service_unlock(void); - -/** - * @brief Send the given action to the service queue - */ -bool mdns_priv_queue_action(mdns_action_t *action); - - - -#endif /* MDNS_PRIVATE_H_ */ diff --git a/components/mdns/private_include/mdns_service.h b/components/mdns/private_include/mdns_service.h new file mode 100644 index 0000000000..597da0f590 --- /dev/null +++ b/components/mdns/private_include/mdns_service.h @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "mdns_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Lock mdns service + */ +void mdns_priv_service_lock(void); + +/** + * @brief Unlock mdns service + */ +void mdns_priv_service_unlock(void); + +/** + * @brief Send the given action to the service queue + */ +bool mdns_priv_queue_action(mdns_action_t *action); + +#ifdef __cplusplus +} +#endif diff --git a/components/mdns/tests/host_unit_test/stubs/mdns_networking.c b/components/mdns/tests/host_unit_test/stubs/mdns_networking.c index 9bd385d494..2bca2e5216 100644 --- a/components/mdns/tests/host_unit_test/stubs/mdns_networking.c +++ b/components/mdns/tests/host_unit_test/stubs/mdns_networking.c @@ -5,6 +5,7 @@ */ #include "mdns_networking.h" #include "mdns_mem_caps.h" +#include "mdns_service.h" struct pbuf { void *payload; From 6b5fb9135c06bcc4fbd0ccc80f786e2dc5a53648 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 11 Apr 2025 15:02:56 +0200 Subject: [PATCH 25/27] fix(mdns): Make debug module more flexible and enable routing printfs to esp_log component --- components/mdns/Kconfig | 14 +++++ components/mdns/mdns_debug.c | 54 +++++++++++++++++++- components/mdns/private_include/mdns_debug.h | 4 +- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig index 04380a4630..bde726d1b7 100644 --- a/components/mdns/Kconfig +++ b/components/mdns/Kconfig @@ -142,6 +142,20 @@ menu "mDNS" help Enable for the library to log received and sent mDNS packets to stdout. + config MDNS_DEBUG_USE_ESP_LOG + bool "Route debug prints to ESP_LOG" + depends on MDNS_ENABLE_DEBUG_PRINTS + default y + help + Enable this option to route debug prints to ESP_LOG, which allows more flexibility. + + config MDNS_DEBUG_BUFFER_SIZE + int "Size of temporary buffer for debug prints" + depends on MDNS_DEBUG_USE_ESP_LOG + default 1024 + help + This buffer is used to output mDNS packets in debug prints. + config MDNS_ENABLE_CONSOLE_CLI bool "Enable Command Line Interface on device console" default y diff --git a/components/mdns/mdns_debug.c b/components/mdns/mdns_debug.c index a620577d70..127174eaf9 100644 --- a/components/mdns/mdns_debug.c +++ b/components/mdns/mdns_debug.c @@ -6,14 +6,58 @@ #include #include -#include #include -#include "freertos/FreeRTOS.h" #include "sdkconfig.h" #include "mdns_private.h" #include "mdns_utils.h" +#ifdef CONFIG_MDNS_DEBUG_USE_ESP_LOG + +#include +#include "esp_log.h" + +#define MDNS_DBG_MAX_LINE CONFIG_MDNS_DEBUG_BUFFER_SIZE + +static char s_mdns_dbg_buf[MDNS_DBG_MAX_LINE]; +static size_t s_mdns_dbg_pos = 0; + +static void mdns_dbg_puts(const char *str) +{ + ESP_LOGI("mdns", "%s", str); +} + +static inline void mdns_dbg_flush(void) +{ + if (s_mdns_dbg_pos > 0) { + s_mdns_dbg_buf[s_mdns_dbg_pos] = '\0'; + mdns_dbg_puts(s_mdns_dbg_buf); + s_mdns_dbg_pos = 0; + } +} + +static void mdns_dbg_printf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int len = vsnprintf(s_mdns_dbg_buf + s_mdns_dbg_pos, MDNS_DBG_MAX_LINE - s_mdns_dbg_pos, fmt, ap); + va_end(ap); + + if (len < 0) { + return; + } + + s_mdns_dbg_pos += len; + + if (s_mdns_dbg_pos >= MDNS_DBG_MAX_LINE - 1) { + mdns_dbg_flush(); + } +} + +#define dbg_printf(...) mdns_dbg_printf(__VA_ARGS__) +#else #define dbg_printf(...) printf(__VA_ARGS__) +#define mdns_dbg_flush() +#endif void static dbg_packet(const uint8_t *data, size_t len) { @@ -239,6 +283,7 @@ void static dbg_packet(const uint8_t *data, size_t len) } } } + mdns_dbg_flush(); } void mdns_debug_tx_packet(mdns_tx_packet_t *p, uint8_t packet[MDNS_MAX_PACKET_SIZE], uint16_t index) @@ -255,6 +300,7 @@ void mdns_debug_tx_packet(mdns_tx_packet_t *p, uint8_t packet[MDNS_MAX_PACKET_SI } #endif dbg_packet(packet, index); + mdns_dbg_flush(); } void mdns_debug_rx_packet(mdns_rx_packet_t *packet, const uint8_t* data, uint16_t len) @@ -271,6 +317,7 @@ void mdns_debug_rx_packet(mdns_rx_packet_t *packet, const uint8_t* data, uint16_ } #endif dbg_packet(data, len); + mdns_dbg_flush(); } static void dbg_printf_result(mdns_result_t *r_t) @@ -302,6 +349,7 @@ static void dbg_printf_result(mdns_result_t *r_t) #endif r_a = r_a->next; } + mdns_dbg_flush(); } void mdns_debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t) @@ -309,6 +357,7 @@ void mdns_debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t) dbg_printf("----------------sync browse %s.%s result---------------\n", b_t->service, b_t->proto); dbg_printf("browse pointer: %p\n", b_t); dbg_printf_result(r_t); + mdns_dbg_flush(); } void mdns_debug_printf_browse_result_all(mdns_result_t *r_t) @@ -319,4 +368,5 @@ void mdns_debug_printf_browse_result_all(mdns_result_t *r_t) dbg_printf_result(r_t); r_t = r_t->next; } + mdns_dbg_flush(); } diff --git a/components/mdns/private_include/mdns_debug.h b/components/mdns/private_include/mdns_debug.h index 496c61cde5..e980389ce3 100644 --- a/components/mdns/private_include/mdns_debug.h +++ b/components/mdns/private_include/mdns_debug.h @@ -6,6 +6,7 @@ #pragma once #include +#include "sdkconfig.h" #include "mdns_private.h" #ifdef __cplusplus @@ -13,13 +14,14 @@ extern "C" { #endif #ifdef CONFIG_MDNS_ENABLE_DEBUG_PRINTS +#include "esp_log.h" /* Define the debug macros for the mDNS module */ #define DBG_BROWSE_RESULTS(result, browse) mdns_debug_printf_browse_result(result, browse) #define DBG_BROWSE_RESULTS_WITH_MSG(result, ...) do { \ - printf(__VA_ARGS__); \ + ESP_LOGD("mdns", __VA_ARGS__); \ mdns_debug_printf_browse_result_all(result); \ } while(0) From 4379c7e5b3b71538dd278b8d5eb8d9bcbff4fdd4 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 11 Apr 2025 15:11:32 +0200 Subject: [PATCH 26/27] fix(mdns): Address minor review comments --- components/mdns/mdns_browser.c | 1 + components/mdns/mdns_netif.c | 6 +----- components/mdns/mdns_send.c | 1 + components/mdns/mdns_service.c | 5 ++++- components/mdns/mdns_utils.c | 7 +++++-- components/mdns/private_include/mdns_private.h | 2 +- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/components/mdns/mdns_browser.c b/components/mdns/mdns_browser.c index f42f68edd3..a720d67af8 100644 --- a/components/mdns/mdns_browser.c +++ b/components/mdns/mdns_browser.c @@ -152,6 +152,7 @@ static mdns_browse_t *browse_init(const char *service, const char *proto, mdns_b browse->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); if (!browse->service) { browse_item_free(browse); + HOOK_MALLOC_FAILED; return NULL; } } diff --git a/components/mdns/mdns_netif.c b/components/mdns/mdns_netif.c index eb7e6b476a..116fd43530 100644 --- a/components/mdns/mdns_netif.c +++ b/components/mdns/mdns_netif.c @@ -5,8 +5,8 @@ */ #include +#include "sdkconfig.h" #include "esp_log.h" -#include "esp_check.h" #include "esp_event.h" #include "mdns.h" #include "mdns_private.h" @@ -66,7 +66,6 @@ static mdns_interfaces_t s_esp_netifs[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 @@ -178,7 +177,6 @@ static esp_err_t post_custom_action(mdns_if_t mdns_if, mdns_event_actions_t even return ESP_OK; } - /** * @brief Dispatch interface changes based on system events */ @@ -284,7 +282,6 @@ static void handle_system_event_for_preset(void *arg, esp_event_base_t event_bas } #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; @@ -384,7 +381,6 @@ esp_err_t mdns_priv_netif_deinit(void) /* * 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); diff --git a/components/mdns/mdns_send.c b/components/mdns/mdns_send.c index a02ef0b5bd..d4fe56d5a8 100644 --- a/components/mdns/mdns_send.c +++ b/components/mdns/mdns_send.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include "sdkconfig.h" #include "mdns_private.h" #include "mdns_send.h" #include "mdns_utils.h" diff --git a/components/mdns/mdns_service.c b/components/mdns/mdns_service.c index 6aee2fba9f..4f54217cff 100644 --- a/components/mdns/mdns_service.c +++ b/components/mdns/mdns_service.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include "sdkconfig.h" #include "mdns_private.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -258,13 +259,15 @@ static esp_err_t create_task_with_caps(void) static StaticTask_t mdns_task_buffer; s_stack_buffer = mdns_mem_task_malloc(MDNS_SERVICE_STACK_DEPTH); - ESP_GOTO_ON_FALSE(s_stack_buffer != NULL, ESP_FAIL, err, TAG, "failed to allocate memory for the mDNS task's stack"); + ESP_GOTO_ON_FALSE(s_stack_buffer != NULL, ESP_FAIL, alloc_failed, TAG, "failed to allocate memory for the mDNS task's stack"); s_service_task_handle = xTaskCreateStaticPinnedToCore(service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, MDNS_TASK_PRIORITY, s_stack_buffer, &mdns_task_buffer, MDNS_TASK_AFFINITY); ESP_GOTO_ON_FALSE(s_service_task_handle != NULL, ESP_FAIL, err, TAG, "failed to create task for the mDNS"); return ret; +alloc_failed: + HOOK_MALLOC_FAILED; err: mdns_mem_task_free(s_stack_buffer); return ret; diff --git a/components/mdns/mdns_utils.c b/components/mdns/mdns_utils.c index c1f33bf268..7e02bad2c3 100644 --- a/components/mdns/mdns_utils.c +++ b/components/mdns/mdns_utils.c @@ -4,12 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include "sdkconfig.h" #include "mdns_private.h" #include "mdns_mem_caps.h" #include "esp_log.h" #include "mdns_utils.h" #include "mdns_responder.h" +static const char *TAG = "mdns_utils"; static const char *MDNS_DEFAULT_DOMAIN = "local"; static const char *MDNS_SUB_STR = "_sub"; @@ -119,7 +121,7 @@ bool mdns_utils_hostname_is_ours(const char *hostname) bool mdns_utils_service_match(const mdns_service_t *srv, const char *service, const char *proto, const char *hostname) { - if (!service || !proto || !srv->hostname) { + if (!service || !proto || !srv || !srv->hostname) { return false; } return !strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && @@ -164,7 +166,7 @@ bool mdns_utils_service_match_instance(const mdns_service_t *srv, const char *in if (!service || !proto) { return false; } - // instance==NULL -> _mdns_instance_name_match() will check the default instance + // instance==NULL -> mdns_utils_instance_name_match() will check the default instance // hostname==NULL -> matches if instance, service and proto matches return !strcasecmp(srv->service, service) && mdns_utils_instance_name_match(srv->instance, instance) && !strcasecmp(srv->proto, proto) && (mdns_utils_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); @@ -216,6 +218,7 @@ mdns_ip_addr_t *mdns_utils_copy_address_list(const mdns_ip_addr_t *address_list) while (address_list != NULL) { mdns_ip_addr_t *addr = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); if (addr == NULL) { + HOOK_MALLOC_FAILED; mdns_utils_free_address_list(head); return NULL; } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 616b55778b..f96c1e292e 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -140,7 +140,7 @@ #define queueFree(type, queue) while (queue) { type * _q = queue; queue = queue->next; free(_q); } #ifndef HOOK_MALLOC_FAILED -#define HOOK_MALLOC_FAILED do { ESP_LOGE(TAG, "Cannot allocate memory (line: %d, free heap: %" PRIu32 " bytes)", __LINE__, esp_get_free_heap_size()); } while(0) +#define HOOK_MALLOC_FAILED do { ESP_LOGE(TAG, "Cannot allocate memory (%s(%d), free heap: %" PRIu32 " bytes)", __func__, __LINE__, esp_get_free_heap_size()); } while(0) #endif typedef size_t mdns_if_t; From c42b578cde6c2314a4248e9320c9e4425bcddef0 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 14 Apr 2025 11:16:16 +0200 Subject: [PATCH 27/27] fix(mdns): Debug prints with small buffer --- components/mdns/mdns_debug.c | 58 +++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/components/mdns/mdns_debug.c b/components/mdns/mdns_debug.c index 127174eaf9..56eb4a1c05 100644 --- a/components/mdns/mdns_debug.c +++ b/components/mdns/mdns_debug.c @@ -35,24 +35,68 @@ static inline void mdns_dbg_flush(void) } } -static void mdns_dbg_printf(const char *fmt, ...) +static void mdns_dbg_vprintf(const char *fmt, va_list args) { - va_list ap; - va_start(ap, fmt); - int len = vsnprintf(s_mdns_dbg_buf + s_mdns_dbg_pos, MDNS_DBG_MAX_LINE - s_mdns_dbg_pos, fmt, ap); - va_end(ap); + // Try to format directly into the buffer + int len = vsnprintf(s_mdns_dbg_buf + s_mdns_dbg_pos, + MDNS_DBG_MAX_LINE - s_mdns_dbg_pos, + fmt, args); if (len < 0) { - return; + return; // Error in formatting } - s_mdns_dbg_pos += len; + // Check if the entire formatted string fit in the buffer + if (len < (MDNS_DBG_MAX_LINE - s_mdns_dbg_pos)) { + // If it fit, just update the position + s_mdns_dbg_pos += len; + } else { + // The formatted string was truncated because it didn't fit + // First, flush what we have (the partial string) + mdns_dbg_flush(); + + // Create a new va_list copy and try again with the full buffer + va_list args_copy; + va_copy(args_copy, args); + // Format again with the entire buffer available + len = vsnprintf(s_mdns_dbg_buf, MDNS_DBG_MAX_LINE - 1, fmt, args_copy); + va_end(args_copy); + + if (len < 0) { + return; // Error + } + + // Check if content will be lost (true truncation) + if (len >= MDNS_DBG_MAX_LINE - 1) { + // This is when actual content will be lost - log a warning + ESP_LOGW("mdns", "Message truncated: length (%d) exceeds buffer size (%d). Consider increasing CONFIG_MDNS_DEBUG_BUFFER_SIZE.", + len, MDNS_DBG_MAX_LINE - 1); + + // Display what we could fit, then flush and return + s_mdns_dbg_pos = MDNS_DBG_MAX_LINE - 1; + mdns_dbg_flush(); + return; + } + + // If we get here, the whole message fit this time + s_mdns_dbg_pos = len; + } + + // If buffer is nearly full after this operation, flush it if (s_mdns_dbg_pos >= MDNS_DBG_MAX_LINE - 1) { mdns_dbg_flush(); } } +static void mdns_dbg_printf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + mdns_dbg_vprintf(fmt, ap); + va_end(ap); +} + #define dbg_printf(...) mdns_dbg_printf(__VA_ARGS__) #else #define dbg_printf(...) printf(__VA_ARGS__)