feat(mdns): Sync code from esp-idf

Commit ID: 2f8508c7

1. Fix possible crash when probing on particular interface with duplicated service instances due to naming conflicts on network. Issue: MDNS server initially sends probing packets to resolve naming confilicts with already registered service instances. In case of a conflict, instance name is altered and probing restarts. Original instance however wasnnot removed from the structure and upon service removal only one entry was removed and a dangling service might have been kept in the structure to bring about a crash. Resolution: Keep only one instance of a service in the probing structure

2. Enable pcbs before starting service thread to avoid updating pcb's internal variables from concurent tasks. Possible race condition: user task runs mdns_init, which enables pcbs while mdns-task already created could execute enable/disable of the same pcbs if an appropriate system event received

3. Fix possible deadlock on mdns deinit calling mdns_free(). Mnds_free() initiates stop and delete timer tasks, which after locking the mutex could lead to a dead lock in case timer task executed before deleting the task, as it would wait indefinitelly for unlocking the mutex. This condition is fixed by calling _mdns_stop_timer without locking the mutex, because there's no need to protect any data when stopping and deleting the timer task

4. Fix race condition in updating packet data from user task when failed to allocate or queue a new service. Issue: mdns_service_add API allocates and queues an action to be processed in mdns task context; when allocation or queueing fails, allocated structure needs to be freed. Function _mdns_free_service did not only fee all the structures, but also updates packet data. Resolution: Moved removal of packet data outside of _mdns_free_service function

5. Fix possible crash when packet scheduled to transmit contained service which might have been already removed. Packets scheduled to transmit are pushed to action queue and removed from tx_queue_head structure, which is searched for all remaining services and while service is removed, then service questions/asnwers are also removed from this structure. This update fixes possible crash when packet is pushed to action queue, and when service is removed, its answers are removed from tx_queue_head, but not from action queue. This could lead to a crash when the packet is poped from action queue containing questions/answers to already removed (freed) service

6. Use binary semaphore instead of mutex when searching. Mdns_search_once_t::lock is used to synchronize tasks (taken by one task and given by the other) so it should not be a mutex. Convert to semaphore, and rename to indicate its purpose

7. Fix memory leak in pbuf if tcpipadapter failed to get netif

8. Fix malfuctional query_txt. When running a query for a single txt, result entries were not created and attached to result structure. This issue was introduced when fixing memory leak in txt structure, which worked correctly for PTR queries, but caused trouble for TXT query

9. Fix possible crash when mdns_free called while action queue not empty

10. Fix memory leak when query for service receives multiple ptr entries for one instance

11. Fix crash after init if no memory for task. Mdns init first starts timer task, then starts service task. If service task failed to be created, timer task needs to be stopped too

12. Fixed crash on free undefined ptr after skipped strdup. Shortcircuit evaluation may cause skip of _mdns_strdup_check of any further question field, which after clear_rx_packet freed undefined memory

13. Fix networking running udp_sendif from lwip thread

14. Check all mallocs for failure and add default hook to log error with free heap. Solves crash about _mdns_result_txt_create when stress test

15. Fixed static memory leak

16. Resolve memory leak when txt record received multiple times

17. Skip sending search when finished, not properly locked timer task

18. Sending search packets also in probing and announcing state. Mdns queries did not work properly when send imeadiately after set_hostname, which cuased reinit of pcb and therefore restarted probing, so search packets were blocked until probing finished
This commit is contained in:
dongheng
2019-05-17 16:04:21 +08:00
parent 1a86bb75f6
commit 9a72ce0903
9 changed files with 277 additions and 79 deletions

View File

@ -23,6 +23,11 @@
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "tcpip_adapter.h" #include "tcpip_adapter.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@ -1,6 +1,5 @@
if(CONFIG_ENABLE_MDNS) if(CONFIG_ENABLE_MDNS)
set(COMPONENT_SRCS "src/mdns.c" set(COMPONENT_SRCS "src/mdns.c"
"src/mdns_console.c"
"src/mdns_networking.c") "src/mdns_networking.c")
set(COMPONENT_PRIV_INCLUDEDIRS "private_include") set(COMPONENT_PRIV_INCLUDEDIRS "private_include")
@ -9,5 +8,12 @@ endif()
set(COMPONENT_ADD_INCLUDEDIRS "include") set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_REQUIRES "lwip" "ssl" "tcpip_adapter") set(COMPONENT_REQUIRES "lwip" "ssl" "tcpip_adapter")
if(CONFIG_ENABLE_MDNS_CONSOLE)
set(COMPONENT_SRCS "${COMPONENT_SRCS}"
"src/mdns_console.c")
endif()
set(COMPONENT_REQUIRES "console" "tcpip_adapter" "newlib")
register_component() register_component()

View File

@ -7,6 +7,14 @@ config ENABLE_MDNS
help help
Enable this option and then mDNS is to be used. Enable this option and then mDNS is to be used.
config ENABLE_MDNS_CONSOLE
bool "Enable mDNS console"
default n
depends on ENABLE_MDNS
select USING_ESP_CONSOLE
help
Enable this option and then mDNS console is to be used.
config MDNS_MAX_SERVICES config MDNS_MAX_SERVICES
int "Max number of services" int "Max number of services"
range 1 64 range 1 64

View File

@ -4,3 +4,7 @@ COMPONENT_PRIV_INCLUDEDIRS := private_include
ifdef CONFIG_ENABLE_MDNS ifdef CONFIG_ENABLE_MDNS
COMPONENT_SRCDIRS := src COMPONENT_SRCDIRS := src
endif endif
ifndef CONFIG_ENABLE_MDNS_CONSOLE
COMPONENT_OBJEXCLUDE := src/mdns_console.o
endif

View File

@ -5,6 +5,8 @@
* MDNS Server Networking -- private include * MDNS Server Networking -- private include
* *
*/ */
#include "mdns.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/queue.h" #include "freertos/queue.h"
@ -19,8 +21,7 @@
#include "esp_system.h" #include "esp_system.h"
#include "esp_timer.h" #include "esp_timer.h"
#include "esp_event_loop.h" #include "esp_event_loop.h"
#include "mdns.h"
#include "mdns_private.h"
/** /**
* @brief Queue RX packet action * @brief Queue RX packet action

View File

@ -14,6 +14,12 @@
#ifndef MDNS_PRIVATE_H_ #ifndef MDNS_PRIVATE_H_
#define MDNS_PRIVATE_H_ #define MDNS_PRIVATE_H_
#include <stdint.h>
#include <stdbool.h>
#include "tcpip_adapter.h"
#include "esp_timer.h"
#include "mdns.h"
//#define MDNS_ENABLE_DEBUG //#define MDNS_ENABLE_DEBUG
#ifdef MDNS_ENABLE_DEBUG #ifdef MDNS_ENABLE_DEBUG
@ -52,7 +58,7 @@
#define MDNS_ANSWER_SDPTR 0x80 #define MDNS_ANSWER_SDPTR 0x80
#define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on #define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on
#define MDNS_SERVICE_STACK_DEPTH CONFIG_MDNS_STACKSIZE // Stack size for the service thread #define MDNS_SERVICE_STACK_DEPTH 4096 // Stack size for the service thread
#define MDNS_PACKET_QUEUE_LEN 16 // Maximum packets that can be queued for parsing #define MDNS_PACKET_QUEUE_LEN 16 // Maximum packets that can be queued for parsing
#define MDNS_ACTION_QUEUE_LEN 16 // Maximum actions pending to the server #define MDNS_ACTION_QUEUE_LEN 16 // Maximum actions pending to the server
#define MDNS_TXT_MAX_LEN 1024 // Maximum string length of text data in TXT record #define MDNS_TXT_MAX_LEN 1024 // Maximum string length of text data in TXT record
@ -115,9 +121,9 @@
#define PCB_STATE_IS_ANNOUNCING(s) (s->state > PCB_PROBE_3 && s->state < PCB_RUNNING) #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) #define PCB_STATE_IS_RUNNING(s) (s->state == PCB_RUNNING)
#define MDNS_SEARCH_LOCK() xSemaphoreTake(_mdns_server->search.lock, portMAX_DELAY) #ifndef HOOK_MALLOC_FAILED
#define MDNS_SEARCH_UNLOCK() xSemaphoreGive(_mdns_server->search.lock) #define HOOK_MALLOC_FAILED ESP_LOGE(TAG, "Cannot allocate memory (line: %d, free heap: %d bytes)", __LINE__, esp_get_free_heap_size());
#endif
typedef enum { typedef enum {
PCB_OFF, PCB_DUP, PCB_INIT, PCB_OFF, PCB_DUP, PCB_INIT,
@ -289,6 +295,7 @@ typedef struct mdns_tx_packet_s {
mdns_out_answer_t * answers; mdns_out_answer_t * answers;
mdns_out_answer_t * servers; mdns_out_answer_t * servers;
mdns_out_answer_t * additional; mdns_out_answer_t * additional;
bool queued;
} mdns_tx_packet_t; } mdns_tx_packet_t;
typedef struct { typedef struct {
@ -315,7 +322,7 @@ typedef struct mdns_search_once_s {
uint32_t started_at; uint32_t started_at;
uint32_t sent_at; uint32_t sent_at;
uint32_t timeout; uint32_t timeout;
SemaphoreHandle_t lock; SemaphoreHandle_t done_semaphore;
uint16_t type; uint16_t type;
uint8_t max_results; uint8_t max_results;
uint8_t num_results; uint8_t num_results;

View File

@ -13,11 +13,10 @@
// limitations under the License. // limitations under the License.
#include "mdns.h" #include "mdns.h"
#include "mdns_networking.h"
#include "mdns_private.h" #include "mdns_private.h"
#include "mdns_networking.h"
#include "esp_log.h"
#include <string.h> #include <string.h>
#include <stdlib.h>
#ifdef MDNS_ENABLE_DEBUG #ifdef MDNS_ENABLE_DEBUG
void mdns_debug_packet(const uint8_t * data, size_t len); void mdns_debug_packet(const uint8_t * data, size_t len);
@ -28,6 +27,8 @@ static const char * MDNS_SUB_STR = "_sub";
mdns_server_t * _mdns_server = NULL; mdns_server_t * _mdns_server = NULL;
static const char *TAG = "MDNS";
static volatile TaskHandle_t _mdns_service_task_handle = NULL; static volatile TaskHandle_t _mdns_service_task_handle = NULL;
static SemaphoreHandle_t _mdns_service_semaphore = NULL; static SemaphoreHandle_t _mdns_service_semaphore = NULL;
@ -65,11 +66,16 @@ static char * _mdns_mangle_name(char* in) {
//need to add -2 to string //need to add -2 to string
ret = malloc(strlen(in) + 3); ret = malloc(strlen(in) + 3);
if (ret == NULL) { if (ret == NULL) {
HOOK_MALLOC_FAILED;
return NULL; return NULL;
} }
sprintf(ret, "%s-2", in); sprintf(ret, "%s-2", in);
} else { } else {
ret = malloc(strlen(in) + 2); //one extra byte in case 9-10 or 99-100 etc ret = malloc(strlen(in) + 2); //one extra byte in case 9-10 or 99-100 etc
if (ret == NULL) {
HOOK_MALLOC_FAILED;
return NULL;
}
strcpy(ret, in); strcpy(ret, in);
int baseLen = p - in; //length of 'bla' in 'bla-123' int baseLen = p - in; //length of 'bla' in 'bla-123'
//overwrite suffix with new suffix //overwrite suffix with new suffix
@ -119,6 +125,7 @@ esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet)
action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
@ -559,6 +566,9 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns
return 0; return 0;
} }
data_len += l; data_len += l;
} else {
HOOK_MALLOC_FAILED;
// continue
} }
txt = txt->next; txt = txt->next;
} }
@ -1132,6 +1142,7 @@ static bool _mdns_alloc_answer(mdns_out_answer_t ** destnation, uint16_t type, m
mdns_out_answer_t * a = (mdns_out_answer_t *)malloc(sizeof(mdns_out_answer_t)); mdns_out_answer_t * a = (mdns_out_answer_t *)malloc(sizeof(mdns_out_answer_t));
if (!a) { if (!a) {
HOOK_MALLOC_FAILED;
return false; return false;
} }
a->type = type; a->type = type;
@ -1150,6 +1161,7 @@ static mdns_tx_packet_t * _mdns_alloc_packet_default(tcpip_adapter_if_t tcpip_if
{ {
mdns_tx_packet_t * packet = (mdns_tx_packet_t*)malloc(sizeof(mdns_tx_packet_t)); mdns_tx_packet_t * packet = (mdns_tx_packet_t*)malloc(sizeof(mdns_tx_packet_t));
if (!packet) { if (!packet) {
HOOK_MALLOC_FAILED;
return NULL; return NULL;
} }
memset((uint8_t*)packet, 0, sizeof(mdns_tx_packet_t)); memset((uint8_t*)packet, 0, sizeof(mdns_tx_packet_t));
@ -1287,6 +1299,7 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(tcpip_adapter_if_t tcpip_if,
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t));
if (!q) { if (!q) {
HOOK_MALLOC_FAILED;
_mdns_free_tx_packet(packet); _mdns_free_tx_packet(packet);
return NULL; return NULL;
} }
@ -1312,6 +1325,7 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(tcpip_adapter_if_t tcpip_if,
if (include_ip && !_str_null_or_empty(_mdns_server->hostname)) { if (include_ip && !_str_null_or_empty(_mdns_server->hostname)) {
mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t));
if (!q) { if (!q) {
HOOK_MALLOC_FAILED;
_mdns_free_tx_packet(packet); _mdns_free_tx_packet(packet);
return NULL; return NULL;
} }
@ -1438,20 +1452,13 @@ static void _mdns_pcb_send_bye(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t i
} }
/** /**
* @brief Send probe for particular services on particular PCB * @brief Send probe for additional services on particular PCB
*/ */
static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) static void _mdns_init_pcb_probe_new_service(tcpip_adapter_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_pcb_t * pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol];
size_t services_final_len = len; size_t services_final_len = len;
_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)) { if (PCB_STATE_IS_PROBING(pcb)) {
services_final_len += pcb->probe_services_len; services_final_len += pcb->probe_services_len;
} }
@ -1459,6 +1466,7 @@ static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t
if (services_final_len) { if (services_final_len) {
_services = (mdns_srv_item_t **)malloc(sizeof(mdns_srv_item_t *) * services_final_len); _services = (mdns_srv_item_t **)malloc(sizeof(mdns_srv_item_t *) * services_final_len);
if (!_services) { if (!_services) {
HOOK_MALLOC_FAILED;
return; return;
} }
@ -1495,6 +1503,50 @@ static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t
pcb->state = PCB_PROBE_1; 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
*/
static void _mdns_init_pcb_probe(tcpip_adapter_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 (int 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 Restart the responder on particular PCB * @brief Restart the responder on particular PCB
*/ */
@ -1739,6 +1791,7 @@ static mdns_txt_linked_item_t * _mdns_allocate_txt(size_t num_items, mdns_txt_it
for (i=0; i<num_items; i++) { for (i=0; i<num_items; i++) {
mdns_txt_linked_item_t * new_item = (mdns_txt_linked_item_t *)malloc(sizeof(mdns_txt_linked_item_t)); mdns_txt_linked_item_t * new_item = (mdns_txt_linked_item_t *)malloc(sizeof(mdns_txt_linked_item_t));
if (!new_item) { if (!new_item) {
HOOK_MALLOC_FAILED;
break; break;
} }
new_item->key = strdup(txt[i].key); new_item->key = strdup(txt[i].key);
@ -1785,6 +1838,7 @@ static mdns_service_t * _mdns_create_service(const char * service, const char *
{ {
mdns_service_t * s = (mdns_service_t *)malloc(sizeof(mdns_service_t)); mdns_service_t * s = (mdns_service_t *)malloc(sizeof(mdns_service_t));
if (!s) { if (!s) {
HOOK_MALLOC_FAILED;
return NULL; return NULL;
} }
@ -1846,6 +1900,9 @@ static void _mdns_dealloc_scheduled_service_answers(mdns_out_answer_t ** destina
*/ */
static void _mdns_remove_scheduled_service_packets(mdns_service_t * 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 * p = NULL;
mdns_tx_packet_t * q = _mdns_server->tx_queue_head; mdns_tx_packet_t * q = _mdns_server->tx_queue_head;
while (q) { while (q) {
@ -1934,7 +1991,6 @@ static void _mdns_free_service(mdns_service_t * service)
if (!service) { if (!service) {
return; return;
} }
_mdns_remove_scheduled_service_packets(service);
free((char *)service->instance); free((char *)service->instance);
free((char *)service->service); free((char *)service->service);
free((char *)service->proto); free((char *)service->proto);
@ -2048,6 +2104,9 @@ static int _mdns_check_txt_collision(mdns_service_t * service, const uint8_t * d
sprintf(tmp, "%s=%s", txt->key, txt->value); sprintf(tmp, "%s=%s", txt->key, txt->value);
_mdns_append_string(ours, &index, tmp); _mdns_append_string(ours, &index, tmp);
free(tmp); free(tmp);
} else {
HOOK_MALLOC_FAILED;
// continue
} }
txt = txt->next; txt = txt->next;
} }
@ -2404,6 +2463,10 @@ static void _mdns_result_txt_create(const uint8_t * data, size_t len, mdns_txt_i
} }
mdns_txt_item_t * txt = (mdns_txt_item_t *)malloc(sizeof(mdns_txt_item_t) * num_items); mdns_txt_item_t * txt = (mdns_txt_item_t *)malloc(sizeof(mdns_txt_item_t) * num_items);
if (!txt) {
HOOK_MALLOC_FAILED;
return;
}
memset(txt, 0, sizeof(mdns_txt_item_t) * num_items); memset(txt, 0, sizeof(mdns_txt_item_t) * num_items);
size_t txt_num = 0; size_t txt_num = 0;
@ -2424,6 +2487,7 @@ static void _mdns_result_txt_create(const uint8_t * data, size_t len, mdns_txt_i
} }
char * key = (char *)malloc(name_len + 1); char * key = (char *)malloc(name_len + 1);
if (!key) { if (!key) {
HOOK_MALLOC_FAILED;
goto handle_error;//error goto handle_error;//error
} }
@ -2437,6 +2501,10 @@ static void _mdns_result_txt_create(const uint8_t * data, size_t len, mdns_txt_i
int value_len = partLen - name_len - 1; int value_len = partLen - name_len - 1;
if (value_len > 0) { if (value_len > 0) {
char * value = (char *)malloc(value_len + 1); char * value = (char *)malloc(value_len + 1);
if (!value) {
HOOK_MALLOC_FAILED;
goto handle_error;//error
}
memcpy(value, data + i, value_len); memcpy(value, data + i, value_len);
value[value_len] = 0; value[value_len] = 0;
i += value_len; i += value_len;
@ -2500,6 +2568,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
mdns_parsed_packet_t * parsed_packet = (mdns_parsed_packet_t *)malloc(sizeof(mdns_parsed_packet_t)); mdns_parsed_packet_t * parsed_packet = (mdns_parsed_packet_t *)malloc(sizeof(mdns_parsed_packet_t));
if (!parsed_packet) { if (!parsed_packet) {
HOOK_MALLOC_FAILED;
return; return;
} }
memset(parsed_packet, 0, sizeof(mdns_parsed_packet_t)); memset(parsed_packet, 0, sizeof(mdns_parsed_packet_t));
@ -2560,8 +2629,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
parsed_packet->discovery = true; parsed_packet->discovery = true;
mdns_srv_item_t * a = _mdns_server->services; mdns_srv_item_t * a = _mdns_server->services;
while (a) { while (a) {
mdns_parsed_question_t * question = (mdns_parsed_question_t *)malloc(sizeof(mdns_parsed_question_t)); mdns_parsed_question_t * question = (mdns_parsed_question_t *)calloc(1, sizeof(mdns_parsed_question_t));
if (!question) { if (!question) {
HOOK_MALLOC_FAILED;
goto clear_rx_packet; goto clear_rx_packet;
} }
question->next = parsed_packet->questions; question->next = parsed_packet->questions;
@ -2587,8 +2657,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
parsed_packet->probe = true; parsed_packet->probe = true;
} }
mdns_parsed_question_t * question = (mdns_parsed_question_t *)malloc(sizeof(mdns_parsed_question_t)); mdns_parsed_question_t * question = (mdns_parsed_question_t *)calloc(1, sizeof(mdns_parsed_question_t));
if (!question) { if (!question) {
HOOK_MALLOC_FAILED;
goto clear_rx_packet; goto clear_rx_packet;
} }
question->next = parsed_packet->questions; question->next = parsed_packet->questions;
@ -2709,8 +2780,10 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
if (search_result) { if (search_result) {
if (search_result->type == MDNS_TYPE_PTR) { if (search_result->type == MDNS_TYPE_PTR) {
result->port = port; if (!result->hostname) { // assign host/port for this entry only if not previously set
result->hostname = strdup(name->host); result->port = port;
result->hostname = strdup(name->host);
}
} else { } else {
_mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol); _mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol);
} }
@ -2771,10 +2844,6 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
if (search_result) { if (search_result) {
mdns_txt_item_t * txt = NULL; mdns_txt_item_t * txt = NULL;
size_t txt_count = 0; size_t txt_count = 0;
_mdns_result_txt_create(data_ptr, data_len, &txt, &txt_count);
if (!txt_count) {
continue;
}
mdns_result_t * result = NULL; mdns_result_t * result = NULL;
if (search_result->type == MDNS_TYPE_PTR) { if (search_result->type == MDNS_TYPE_PTR) {
@ -2794,11 +2863,17 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
} }
} }
if (!result->txt) { if (!result->txt) {
result->txt = txt; _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_count);
result->txt_count = txt_count; if (txt_count) {
result->txt = txt;
result->txt_count = txt_count;
}
} }
} else { } else {
_mdns_search_result_add_txt(search_result, txt, txt_count, packet->tcpip_if, packet->ip_protocol); _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_count);
if (txt_count) {
_mdns_search_result_add_txt(search_result, txt, txt_count, packet->tcpip_if, packet->ip_protocol);
}
} }
} else if (ours) { } else if (ours) {
if (parsed_packet->questions && !parsed_packet->probe) { if (parsed_packet->questions && !parsed_packet->probe) {
@ -3038,7 +3113,7 @@ static void _mdns_search_free(mdns_search_once_t * search)
free(search->instance); free(search->instance);
free(search->service); free(search->service);
free(search->proto); free(search->proto);
vSemaphoreDelete(search->lock); vSemaphoreDelete(search->done_semaphore);
free(search); free(search);
} }
@ -3049,12 +3124,13 @@ static mdns_search_once_t * _mdns_search_init(const char * name, const char * se
{ {
mdns_search_once_t * search = (mdns_search_once_t *)malloc(sizeof(mdns_search_once_t)); mdns_search_once_t * search = (mdns_search_once_t *)malloc(sizeof(mdns_search_once_t));
if (!search) { if (!search) {
HOOK_MALLOC_FAILED;
return NULL; return NULL;
} }
memset(search, 0, sizeof(mdns_search_once_t)); memset(search, 0, sizeof(mdns_search_once_t));
search->lock = xSemaphoreCreateMutex(); search->done_semaphore = xSemaphoreCreateBinary();
if (!search->lock) { if (!search->done_semaphore) {
free(search); free(search);
return NULL; return NULL;
} }
@ -3093,8 +3169,6 @@ static mdns_search_once_t * _mdns_search_init(const char * name, const char * se
search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS; search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS;
search->next = NULL; search->next = NULL;
xSemaphoreTake(search->lock, 0);
return search; return search;
} }
@ -3105,7 +3179,7 @@ static void _mdns_search_finish(mdns_search_once_t * search)
{ {
search->state = SEARCH_OFF; search->state = SEARCH_OFF;
queueDetach(mdns_search_once_t, _mdns_server->search_once, search); queueDetach(mdns_search_once_t, _mdns_server->search_once, search);
xSemaphoreGive(search->lock); xSemaphoreGive(search->done_semaphore);
} }
/** /**
@ -3140,6 +3214,7 @@ static mdns_ip_addr_t * _mdns_result_addr_create_ip(ip_addr_t * ip)
{ {
mdns_ip_addr_t * a = (mdns_ip_addr_t *)malloc(sizeof(mdns_ip_addr_t)); mdns_ip_addr_t * a = (mdns_ip_addr_t *)malloc(sizeof(mdns_ip_addr_t));
if (!a) { if (!a) {
HOOK_MALLOC_FAILED;
return NULL; return NULL;
} }
memset(a, 0 , sizeof(mdns_ip_addr_t)); memset(a, 0 , sizeof(mdns_ip_addr_t));
@ -3199,6 +3274,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char *
if (!search->max_results || search->num_results < search->max_results) { if (!search->max_results || search->num_results < search->max_results) {
r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); r = (mdns_result_t *)malloc(sizeof(mdns_result_t));
if (!r) { if (!r) {
HOOK_MALLOC_FAILED;
return; return;
} }
@ -3244,6 +3320,7 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search,
if (!search->max_results || search->num_results < search->max_results) { if (!search->max_results || search->num_results < search->max_results) {
r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); r = (mdns_result_t *)malloc(sizeof(mdns_result_t));
if (!r) { if (!r) {
HOOK_MALLOC_FAILED;
return NULL; return NULL;
} }
@ -3279,6 +3356,7 @@ static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char
if (!search->max_results || search->num_results < search->max_results) { if (!search->max_results || search->num_results < search->max_results) {
r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); r = (mdns_result_t *)malloc(sizeof(mdns_result_t));
if (!r) { if (!r) {
HOOK_MALLOC_FAILED;
return; return;
} }
@ -3307,7 +3385,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it
while (r) { while (r) {
if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol) {
if (r->txt) { if (r->txt) {
return; goto free_txt;
} }
r->txt = txt; r->txt = txt;
r->txt_count = txt_count; r->txt_count = txt_count;
@ -3318,12 +3396,8 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it
if (!search->max_results || search->num_results < search->max_results) { if (!search->max_results || search->num_results < search->max_results) {
r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); r = (mdns_result_t *)malloc(sizeof(mdns_result_t));
if (!r) { if (!r) {
for (i=0; i<txt_count; i++) { HOOK_MALLOC_FAILED;
free((char *)(txt[i].key)); goto free_txt;
free((char *)(txt[i].value));
}
free(txt);
return;
} }
memset(r, 0 , sizeof(mdns_result_t)); memset(r, 0 , sizeof(mdns_result_t));
@ -3335,6 +3409,14 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it
search->result = r; search->result = r;
search->num_results++; search->num_results++;
} }
return;
free_txt:
for (i=0; i<txt_count; i++) {
free((char *)(txt[i].key));
free((char *)(txt[i].value));
}
free(txt);
} }
/** /**
@ -3420,6 +3502,7 @@ static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search
mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t));
if (!q) { if (!q) {
HOOK_MALLOC_FAILED;
_mdns_free_tx_packet(packet); _mdns_free_tx_packet(packet);
return NULL; return NULL;
} }
@ -3442,6 +3525,7 @@ static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search
} }
mdns_out_answer_t * a = (mdns_out_answer_t *)malloc(sizeof(mdns_out_answer_t)); mdns_out_answer_t * a = (mdns_out_answer_t *)malloc(sizeof(mdns_out_answer_t));
if (!a) { if (!a) {
HOOK_MALLOC_FAILED;
_mdns_free_tx_packet(packet); _mdns_free_tx_packet(packet);
return NULL; return NULL;
} }
@ -3467,7 +3551,7 @@ static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search
static void _mdns_search_send_pcb(mdns_search_once_t * search, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) static void _mdns_search_send_pcb(mdns_search_once_t * search, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
{ {
mdns_tx_packet_t * packet = NULL; mdns_tx_packet_t * packet = NULL;
if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb && _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state == PCB_RUNNING) { if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb && _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state > PCB_INIT) {
packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol); packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol);
if (!packet) { if (!packet) {
return; return;
@ -3482,6 +3566,22 @@ static void _mdns_search_send_pcb(mdns_search_once_t * search, tcpip_adapter_if_
*/ */
static void _mdns_search_send(mdns_search_once_t * search) 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; uint8_t i, j;
for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) { for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
for (j=0; j<MDNS_IP_PROTOCOL_MAX; j++) { for (j=0; j<MDNS_IP_PROTOCOL_MAX; j++) {
@ -3671,6 +3771,7 @@ static void _mdns_execute_action(mdns_action_t * action)
if (!txt) { if (!txt) {
txt = (mdns_txt_linked_item_t *)malloc(sizeof(mdns_txt_linked_item_t)); txt = (mdns_txt_linked_item_t *)malloc(sizeof(mdns_txt_linked_item_t));
if (!txt) { if (!txt) {
HOOK_MALLOC_FAILED;
_mdns_free_action(action); _mdns_free_action(action);
return; return;
} }
@ -3719,6 +3820,7 @@ static void _mdns_execute_action(mdns_action_t * action)
if (_mdns_server->services == action->data.srv_del.service) { if (_mdns_server->services == action->data.srv_del.service) {
_mdns_server->services = a->next; _mdns_server->services = a->next;
_mdns_send_bye(&a, 1, false); _mdns_send_bye(&a, 1, false);
_mdns_remove_scheduled_service_packets(a->service);
_mdns_free_service(a->service); _mdns_free_service(a->service);
free(a); free(a);
} else { } else {
@ -3729,6 +3831,7 @@ static void _mdns_execute_action(mdns_action_t * action)
mdns_srv_item_t * b = a->next; mdns_srv_item_t * b = a->next;
a->next = a->next->next; a->next = a->next->next;
_mdns_send_bye(&b, 1, false); _mdns_send_bye(&b, 1, false);
_mdns_remove_scheduled_service_packets(b->service);
_mdns_free_service(b->service); _mdns_free_service(b->service);
free(b); free(b);
} }
@ -3742,6 +3845,7 @@ static void _mdns_execute_action(mdns_action_t * action)
while (a) { while (a) {
mdns_srv_item_t * s = a; mdns_srv_item_t * s = a;
a = a->next; a = a->next;
_mdns_remove_scheduled_service_packets(s->service);
_mdns_free_service(s->service); _mdns_free_service(s->service);
free(s); free(s);
} }
@ -3757,7 +3861,17 @@ static void _mdns_execute_action(mdns_action_t * action)
_mdns_search_finish(action->data.search_add.search); _mdns_search_finish(action->data.search_add.search);
break; break;
case ACTION_TX_HANDLE: case ACTION_TX_HANDLE:
_mdns_tx_handle_packet(action->data.tx_handle.packet); {
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; break;
case ACTION_RX_HANDLE: case ACTION_RX_HANDLE:
mdns_parse_packet(action->data.rx_handle.packet); mdns_parse_packet(action->data.rx_handle.packet);
@ -3779,6 +3893,7 @@ static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_o
action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
@ -3793,26 +3908,38 @@ static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_o
/** /**
* @brief Called from timer task to run mDNS responder * @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() static void _mdns_scheduler_run()
{ {
MDNS_SERVICE_LOCK();
mdns_tx_packet_t * p = _mdns_server->tx_queue_head; mdns_tx_packet_t * p = _mdns_server->tx_queue_head;
mdns_action_t * action = NULL; mdns_action_t * action = NULL;
// find first unqueued packet
while (p && p->queued) {
p = p->next;
}
if (!p) { if (!p) {
MDNS_SERVICE_UNLOCK();
return; return;
} }
MDNS_SERVICE_LOCK();
if ((int32_t)(p->send_at - (xTaskGetTickCount() * portTICK_PERIOD_MS)) < 0) { if ((int32_t)(p->send_at - (xTaskGetTickCount() * portTICK_PERIOD_MS)) < 0) {
action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (action) { if (action) {
_mdns_server->tx_queue_head = p->next;
action->type = ACTION_TX_HANDLE; action->type = ACTION_TX_HANDLE;
action->data.tx_handle.packet = p; action->data.tx_handle.packet = p;
p->queued = true;
if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) {
free(action); free(action);
_mdns_server->tx_queue_head = p; p->queued = false;
} }
} else {
HOOK_MALLOC_FAILED;
// continue
} }
} }
MDNS_SERVICE_UNLOCK(); MDNS_SERVICE_UNLOCK();
@ -3826,7 +3953,6 @@ static void _mdns_search_run()
MDNS_SERVICE_LOCK(); MDNS_SERVICE_LOCK();
mdns_search_once_t * s = _mdns_server->search_once; mdns_search_once_t * s = _mdns_server->search_once;
uint32_t now = xTaskGetTickCount() * portTICK_PERIOD_MS; uint32_t now = xTaskGetTickCount() * portTICK_PERIOD_MS;
if (!s) { if (!s) {
MDNS_SERVICE_UNLOCK(); MDNS_SERVICE_UNLOCK();
return; return;
@ -3930,7 +4056,10 @@ static esp_err_t _mdns_service_task_start()
if (!_mdns_service_task_handle) { if (!_mdns_service_task_handle) {
xTaskCreatePinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, 1, (TaskHandle_t * const)(&_mdns_service_task_handle), 0); xTaskCreatePinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, 1, (TaskHandle_t * const)(&_mdns_service_task_handle), 0);
if (!_mdns_service_task_handle) { if (!_mdns_service_task_handle) {
_mdns_stop_timer();
MDNS_SERVICE_UNLOCK(); MDNS_SERVICE_UNLOCK();
vSemaphoreDelete(_mdns_service_semaphore);
_mdns_service_semaphore = NULL;
return ESP_FAIL; return ESP_FAIL;
} }
} }
@ -3946,7 +4075,6 @@ static esp_err_t _mdns_service_task_start()
*/ */
static esp_err_t _mdns_service_task_stop() static esp_err_t _mdns_service_task_stop()
{ {
MDNS_SERVICE_LOCK();
_mdns_stop_timer(); _mdns_stop_timer();
if (_mdns_service_task_handle) { if (_mdns_service_task_handle) {
mdns_action_t action; mdns_action_t action;
@ -3960,7 +4088,8 @@ static esp_err_t _mdns_service_task_stop()
vTaskDelay(10 / portTICK_PERIOD_MS); vTaskDelay(10 / portTICK_PERIOD_MS);
} }
} }
MDNS_SERVICE_UNLOCK(); vSemaphoreDelete(_mdns_service_semaphore);
_mdns_service_semaphore = NULL;
return ESP_OK; return ESP_OK;
} }
@ -3976,6 +4105,7 @@ esp_err_t mdns_handle_system_event(void *ctx, system_event_t *event)
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
return ESP_OK; return ESP_OK;
} }
action->type = ACTION_SYSTEM_EVENT; action->type = ACTION_SYSTEM_EVENT;
@ -3997,6 +4127,7 @@ esp_err_t mdns_init()
_mdns_server = (mdns_server_t *)malloc(sizeof(mdns_server_t)); _mdns_server = (mdns_server_t *)malloc(sizeof(mdns_server_t));
if (!_mdns_server) { if (!_mdns_server) {
HOOK_MALLOC_FAILED;
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
memset((uint8_t*)_mdns_server, 0, sizeof(mdns_server_t)); memset((uint8_t*)_mdns_server, 0, sizeof(mdns_server_t));
@ -4013,12 +4144,6 @@ esp_err_t mdns_init()
goto free_lock; goto free_lock;
} }
if (_mdns_service_task_start()) {
//service start failed!
err = ESP_FAIL;
goto free_all;
}
uint8_t i; uint8_t i;
ip6_addr_t tmp_addr6; ip6_addr_t tmp_addr6;
tcpip_adapter_ip_info_t if_ip_info; tcpip_adapter_ip_info_t if_ip_info;
@ -4032,9 +4157,19 @@ esp_err_t mdns_init()
} }
} }
if (_mdns_service_task_start()) {
//service start failed!
err = ESP_FAIL;
goto free_all_and_disable_pcbs;
}
return ESP_OK; return ESP_OK;
free_all: free_all_and_disable_pcbs:
for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
_mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V6);
_mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V4);
}
vQueueDelete(_mdns_server->action_queue); vQueueDelete(_mdns_server->action_queue);
free_lock: free_lock:
vSemaphoreDelete(_mdns_server->lock); vSemaphoreDelete(_mdns_server->lock);
@ -4050,8 +4185,8 @@ void mdns_free()
if (!_mdns_server) { if (!_mdns_server) {
return; return;
} }
_mdns_service_task_stop();
mdns_service_remove_all(_mdns_server); mdns_service_remove_all(_mdns_server);
_mdns_service_task_stop();
for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) { for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
for (j=0; j<MDNS_IP_PROTOCOL_MAX; j++) { for (j=0; j<MDNS_IP_PROTOCOL_MAX; j++) {
_mdns_pcb_deinit(i, j); _mdns_pcb_deinit(i, j);
@ -4073,7 +4208,7 @@ void mdns_free()
free(h->instance); free(h->instance);
free(h->service); free(h->service);
free(h->proto); free(h->proto);
vSemaphoreDelete(h->lock); vSemaphoreDelete(h->done_semaphore);
if (h->result) { if (h->result) {
mdns_query_results_free(h->result); mdns_query_results_free(h->result);
} }
@ -4099,6 +4234,7 @@ esp_err_t mdns_hostname_set(const char * hostname)
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
free(new_hostname); free(new_hostname);
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
@ -4127,6 +4263,7 @@ esp_err_t mdns_instance_name_set(const char * instance)
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
free(new_instance); free(new_instance);
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
@ -4166,6 +4303,7 @@ esp_err_t mdns_service_add(const char * instance, const char * service, const ch
item = (mdns_srv_item_t *)malloc(sizeof(mdns_srv_item_t)); item = (mdns_srv_item_t *)malloc(sizeof(mdns_srv_item_t));
if (!item) { if (!item) {
HOOK_MALLOC_FAILED;
_mdns_free_service(s); _mdns_free_service(s);
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
@ -4175,6 +4313,7 @@ esp_err_t mdns_service_add(const char * instance, const char * service, const ch
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
_mdns_free_service(s); _mdns_free_service(s);
free(item); free(item);
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
@ -4211,6 +4350,7 @@ esp_err_t mdns_service_port_set(const char * service, const char * proto, uint16
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
action->type = ACTION_SERVICE_PORT_SET; action->type = ACTION_SERVICE_PORT_SET;
@ -4243,6 +4383,7 @@ esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_tx
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
_mdns_free_linked_txt(new_txt); _mdns_free_linked_txt(new_txt);
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
@ -4270,6 +4411,7 @@ esp_err_t mdns_service_txt_item_set(const char * service, const char * proto, co
} }
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
@ -4306,6 +4448,7 @@ esp_err_t mdns_service_txt_item_remove(const char * service, const char * proto,
} }
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
@ -4343,6 +4486,7 @@ esp_err_t mdns_service_instance_name_set(const char * service, const char * prot
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
free(new_instance); free(new_instance);
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
@ -4369,6 +4513,7 @@ esp_err_t mdns_service_remove(const char * service, const char * proto)
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
action->type = ACTION_SERVICE_DEL; action->type = ACTION_SERVICE_DEL;
@ -4391,6 +4536,7 @@ esp_err_t mdns_service_remove_all()
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
if (!action) { if (!action) {
HOOK_MALLOC_FAILED;
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
action->type = ACTION_SERVICES_CLEAR; action->type = ACTION_SERVICES_CLEAR;
@ -4457,7 +4603,7 @@ esp_err_t mdns_query(const char * name, const char * service, const char * proto
_mdns_search_free(search); _mdns_search_free(search);
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
xSemaphoreTake(search->lock, portMAX_DELAY); xSemaphoreTake(search->done_semaphore, portMAX_DELAY);
*results = search->result; *results = search->result;
_mdns_search_free(search); _mdns_search_free(search);

View File

@ -11,7 +11,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifdef MDNS_ENABLE_CONSOLE
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "esp_console.h" #include "esp_console.h"
@ -1058,4 +1057,4 @@ void mdns_console_register()
register_mdns_query_ip(); register_mdns_query_ip();
register_mdns_query_svc(); register_mdns_query_svc();
} }
#endif

View File

@ -4,8 +4,9 @@
* *
*/ */
#include <string.h> #include <string.h>
#include <stdlib.h> #include "mdns_private.h"
#include "mdns_networking.h" #include "mdns_networking.h"
#include "esp_log.h"
extern mdns_server_t * _mdns_server; extern mdns_server_t * _mdns_server;
@ -14,6 +15,7 @@ extern mdns_server_t * _mdns_server;
* MDNS Server Networking * MDNS Server Networking
* *
*/ */
static const char *TAG = "MDNS_Networking";
static struct udp_pcb * _pcb_main = NULL; static struct udp_pcb * _pcb_main = NULL;
@ -119,6 +121,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip
mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t)); mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t));
if (!packet) { if (!packet) {
HOOK_MALLOC_FAILED;
//missed packet - no memory //missed packet - no memory
pbuf_free(this_pb); pbuf_free(this_pb);
continue; continue;
@ -240,6 +243,9 @@ typedef struct {
struct tcpip_api_call_data call; struct tcpip_api_call_data call;
tcpip_adapter_if_t tcpip_if; tcpip_adapter_if_t tcpip_if;
mdns_ip_protocol_t ip_protocol; mdns_ip_protocol_t ip_protocol;
struct pbuf *pbt;
const ip_addr_t *ip;
uint16_t port;
esp_err_t err; esp_err_t err;
} mdns_api_call_t; } mdns_api_call_t;
@ -275,7 +281,7 @@ esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_prot
.tcpip_if = tcpip_if, .tcpip_if = tcpip_if,
.ip_protocol = ip_protocol .ip_protocol = ip_protocol
}; };
tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call_data*)&msg); tcpip_api_call(_mdns_pcb_init_api, &msg.call);
return msg.err; return msg.err;
} }
@ -285,29 +291,45 @@ esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_pr
.tcpip_if = tcpip_if, .tcpip_if = tcpip_if,
.ip_protocol = ip_protocol .ip_protocol = ip_protocol
}; };
tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call_data*)&msg); tcpip_api_call(_mdns_pcb_deinit_api, &msg.call);
return msg.err; return msg.err;
} }
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;
mdns_pcb_t * _pcb = &_mdns_server->interfaces[msg->tcpip_if].pcbs[msg->ip_protocol];
esp_err_t err = tcpip_adapter_get_netif(msg->tcpip_if, &nif);
if (err) {
pbuf_free(msg->pbt);
msg->err = err;
return err;
}
err = udp_sendto_if (_pcb->pcb, msg->pbt, msg->ip, msg->port, (struct netif *)nif);
pbuf_free(msg->pbt);
msg->err = err;
return err;
}
size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len) size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len)
{ {
struct netif * netif = NULL;
void * nif = NULL;
esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif);
netif = (struct netif *)nif;
if (err) {
return 0;
}
struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if (pbt == NULL) { if (pbt == NULL) {
return 0; return 0;
} }
memcpy((uint8_t *)pbt->payload, data, len); memcpy((uint8_t *)pbt->payload, data, len);
err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif); mdns_api_call_t msg = {
pbuf_free(pbt); .tcpip_if = tcpip_if,
if (err) { .ip_protocol = ip_protocol,
.pbt = pbt,
.ip = ip,
.port = port
};
tcpip_api_call(_mdns_udp_pcb_write_api, &msg.call);
if (msg.err) {
return 0; return 0;
} }
return len; return len;