diff --git a/components/esp8266/include/esp_event.h b/components/esp8266/include/esp_event.h index 0a792bc2..dfb42e85 100644 --- a/components/esp8266/include/esp_event.h +++ b/components/esp8266/include/esp_event.h @@ -23,6 +23,11 @@ #include "lwip/ip_addr.h" #include "tcpip_adapter.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 4401ee3a..99bb43a0 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -1,6 +1,5 @@ if(CONFIG_ENABLE_MDNS) set(COMPONENT_SRCS "src/mdns.c" - "src/mdns_console.c" "src/mdns_networking.c") set(COMPONENT_PRIV_INCLUDEDIRS "private_include") @@ -9,5 +8,12 @@ endif() set(COMPONENT_ADD_INCLUDEDIRS "include") 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() diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig index daea5377..81b87d12 100644 --- a/components/mdns/Kconfig +++ b/components/mdns/Kconfig @@ -7,6 +7,14 @@ config ENABLE_MDNS help 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 int "Max number of services" range 1 64 diff --git a/components/mdns/component.mk b/components/mdns/component.mk index df87e77c..8b4f6d18 100644 --- a/components/mdns/component.mk +++ b/components/mdns/component.mk @@ -4,3 +4,7 @@ COMPONENT_PRIV_INCLUDEDIRS := private_include ifdef CONFIG_ENABLE_MDNS COMPONENT_SRCDIRS := src endif + +ifndef CONFIG_ENABLE_MDNS_CONSOLE +COMPONENT_OBJEXCLUDE := src/mdns_console.o +endif diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h index 6e7f80ea..a04588ec 100644 --- a/components/mdns/private_include/mdns_networking.h +++ b/components/mdns/private_include/mdns_networking.h @@ -5,6 +5,8 @@ * MDNS Server Networking -- private include * */ +#include "mdns.h" + #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/queue.h" @@ -19,8 +21,7 @@ #include "esp_system.h" #include "esp_timer.h" #include "esp_event_loop.h" -#include "mdns.h" -#include "mdns_private.h" + /** * @brief Queue RX packet action diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 939b9e89..0a8f7598 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -14,6 +14,12 @@ #ifndef MDNS_PRIVATE_H_ #define MDNS_PRIVATE_H_ +#include +#include +#include "tcpip_adapter.h" +#include "esp_timer.h" +#include "mdns.h" + //#define MDNS_ENABLE_DEBUG #ifdef MDNS_ENABLE_DEBUG @@ -52,7 +58,7 @@ #define MDNS_ANSWER_SDPTR 0x80 #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_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 @@ -115,9 +121,9 @@ #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 MDNS_SEARCH_LOCK() xSemaphoreTake(_mdns_server->search.lock, portMAX_DELAY) -#define MDNS_SEARCH_UNLOCK() xSemaphoreGive(_mdns_server->search.lock) - +#ifndef HOOK_MALLOC_FAILED +#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 { 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 * servers; mdns_out_answer_t * additional; + bool queued; } mdns_tx_packet_t; typedef struct { @@ -315,7 +322,7 @@ typedef struct mdns_search_once_s { uint32_t started_at; uint32_t sent_at; uint32_t timeout; - SemaphoreHandle_t lock; + SemaphoreHandle_t done_semaphore; uint16_t type; uint8_t max_results; uint8_t num_results; diff --git a/components/mdns/src/mdns.c b/components/mdns/src/mdns.c index f9281a3f..0f52ecf8 100644 --- a/components/mdns/src/mdns.c +++ b/components/mdns/src/mdns.c @@ -13,11 +13,10 @@ // limitations under the License. #include "mdns.h" -#include "mdns_networking.h" #include "mdns_private.h" - +#include "mdns_networking.h" +#include "esp_log.h" #include -#include #ifdef MDNS_ENABLE_DEBUG 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; +static const char *TAG = "MDNS"; + static volatile TaskHandle_t _mdns_service_task_handle = 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 ret = malloc(strlen(in) + 3); if (ret == NULL) { + HOOK_MALLOC_FAILED; return NULL; } sprintf(ret, "%s-2", in); } else { 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); int baseLen = p - in; //length of 'bla' in 'bla-123' //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)); if (!action) { + HOOK_MALLOC_FAILED; 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; } data_len += l; + } else { + HOOK_MALLOC_FAILED; + // continue } 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)); if (!a) { + HOOK_MALLOC_FAILED; return false; } 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)); if (!packet) { + HOOK_MALLOC_FAILED; return NULL; } 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; ihostname)) { mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); if (!q) { + HOOK_MALLOC_FAILED; _mdns_free_tx_packet(packet); 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]; 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)) { 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) { _services = (mdns_srv_item_t **)malloc(sizeof(mdns_srv_item_t *) * services_final_len); if (!_services) { + HOOK_MALLOC_FAILED; 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; } +/** + * @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 */ @@ -1739,6 +1791,7 @@ static mdns_txt_linked_item_t * _mdns_allocate_txt(size_t num_items, mdns_txt_it for (i=0; ikey = 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)); if (!s) { + HOOK_MALLOC_FAILED; 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) { + if (!service) { + return; + } mdns_tx_packet_t * p = NULL; mdns_tx_packet_t * q = _mdns_server->tx_queue_head; while (q) { @@ -1934,7 +1991,6 @@ static void _mdns_free_service(mdns_service_t * service) if (!service) { return; } - _mdns_remove_scheduled_service_packets(service); free((char *)service->instance); free((char *)service->service); 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); _mdns_append_string(ours, &index, tmp); free(tmp); + } else { + HOOK_MALLOC_FAILED; + // continue } 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); + if (!txt) { + HOOK_MALLOC_FAILED; + return; + } memset(txt, 0, sizeof(mdns_txt_item_t) * num_items); 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); if (!key) { + HOOK_MALLOC_FAILED; 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; if (value_len > 0) { char * value = (char *)malloc(value_len + 1); + if (!value) { + HOOK_MALLOC_FAILED; + goto handle_error;//error + } memcpy(value, data + i, value_len); value[value_len] = 0; 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)); if (!parsed_packet) { + HOOK_MALLOC_FAILED; return; } 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; mdns_srv_item_t * a = _mdns_server->services; 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) { + HOOK_MALLOC_FAILED; goto clear_rx_packet; } question->next = parsed_packet->questions; @@ -2587,8 +2657,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) 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) { + HOOK_MALLOC_FAILED; goto clear_rx_packet; } question->next = parsed_packet->questions; @@ -2709,8 +2780,10 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) if (search_result) { if (search_result->type == MDNS_TYPE_PTR) { - result->port = port; - result->hostname = strdup(name->host); + if (!result->hostname) { // assign host/port for this entry only if not previously set + result->port = port; + result->hostname = strdup(name->host); + } } else { _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) { mdns_txt_item_t * txt = NULL; 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; if (search_result->type == MDNS_TYPE_PTR) { @@ -2794,11 +2863,17 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } } if (!result->txt) { - result->txt = txt; - result->txt_count = txt_count; + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_count); + if (txt_count) { + result->txt = txt; + result->txt_count = txt_count; + } } } 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) { 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->service); free(search->proto); - vSemaphoreDelete(search->lock); + vSemaphoreDelete(search->done_semaphore); 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)); if (!search) { + HOOK_MALLOC_FAILED; return NULL; } memset(search, 0, sizeof(mdns_search_once_t)); - search->lock = xSemaphoreCreateMutex(); - if (!search->lock) { + search->done_semaphore = xSemaphoreCreateBinary(); + if (!search->done_semaphore) { free(search); 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->next = NULL; - xSemaphoreTake(search->lock, 0); - return search; } @@ -3105,7 +3179,7 @@ static void _mdns_search_finish(mdns_search_once_t * search) { search->state = SEARCH_OFF; 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)); if (!a) { + HOOK_MALLOC_FAILED; return NULL; } 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) { r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); if (!r) { + HOOK_MALLOC_FAILED; 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) { r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); if (!r) { + HOOK_MALLOC_FAILED; 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) { r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); if (!r) { + HOOK_MALLOC_FAILED; return; } @@ -3307,7 +3385,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it while (r) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol) { if (r->txt) { - return; + goto free_txt; } r->txt = txt; 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) { r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); if (!r) { - for (i=0; iresult = r; search->num_results++; } + return; + +free_txt: + for (i=0; iinterfaces[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); if (!packet) { 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) { + 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; iservices == action->data.srv_del.service) { _mdns_server->services = a->next; _mdns_send_bye(&a, 1, false); + _mdns_remove_scheduled_service_packets(a->service); _mdns_free_service(a->service); free(a); } else { @@ -3729,6 +3831,7 @@ static void _mdns_execute_action(mdns_action_t * action) mdns_srv_item_t * b = a->next; a->next = a->next->next; _mdns_send_bye(&b, 1, false); + _mdns_remove_scheduled_service_packets(b->service); _mdns_free_service(b->service); free(b); } @@ -3742,6 +3845,7 @@ static void _mdns_execute_action(mdns_action_t * action) while (a) { mdns_srv_item_t * s = a; a = a->next; + _mdns_remove_scheduled_service_packets(s->service); _mdns_free_service(s->service); free(s); } @@ -3757,7 +3861,17 @@ static void _mdns_execute_action(mdns_action_t * action) _mdns_search_finish(action->data.search_add.search); break; 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; case ACTION_RX_HANDLE: 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)); if (!action) { + HOOK_MALLOC_FAILED; 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 + * + * 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() { + MDNS_SERVICE_LOCK(); mdns_tx_packet_t * p = _mdns_server->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; } - MDNS_SERVICE_LOCK(); if ((int32_t)(p->send_at - (xTaskGetTickCount() * portTICK_PERIOD_MS)) < 0) { action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (action) { - _mdns_server->tx_queue_head = p->next; action->type = ACTION_TX_HANDLE; action->data.tx_handle.packet = p; + p->queued = true; if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { free(action); - _mdns_server->tx_queue_head = p; + p->queued = false; } + } else { + HOOK_MALLOC_FAILED; + // continue } } MDNS_SERVICE_UNLOCK(); @@ -3826,7 +3953,6 @@ static void _mdns_search_run() 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; @@ -3930,7 +4056,10 @@ static esp_err_t _mdns_service_task_start() if (!_mdns_service_task_handle) { xTaskCreatePinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, 1, (TaskHandle_t * const)(&_mdns_service_task_handle), 0); if (!_mdns_service_task_handle) { + _mdns_stop_timer(); MDNS_SERVICE_UNLOCK(); + vSemaphoreDelete(_mdns_service_semaphore); + _mdns_service_semaphore = NULL; return ESP_FAIL; } } @@ -3946,7 +4075,6 @@ static esp_err_t _mdns_service_task_start() */ static esp_err_t _mdns_service_task_stop() { - MDNS_SERVICE_LOCK(); _mdns_stop_timer(); if (_mdns_service_task_handle) { mdns_action_t action; @@ -3960,7 +4088,8 @@ static esp_err_t _mdns_service_task_stop() vTaskDelay(10 / portTICK_PERIOD_MS); } } - MDNS_SERVICE_UNLOCK(); + vSemaphoreDelete(_mdns_service_semaphore); + _mdns_service_semaphore = NULL; 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)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_OK; } action->type = ACTION_SYSTEM_EVENT; @@ -3997,6 +4127,7 @@ esp_err_t mdns_init() _mdns_server = (mdns_server_t *)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)); @@ -4013,12 +4144,6 @@ esp_err_t mdns_init() goto free_lock; } - if (_mdns_service_task_start()) { - //service start failed! - err = ESP_FAIL; - goto free_all; - } - uint8_t i; ip6_addr_t tmp_addr6; 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; -free_all: +free_all_and_disable_pcbs: + for (i=0; iaction_queue); free_lock: vSemaphoreDelete(_mdns_server->lock); @@ -4050,8 +4185,8 @@ void mdns_free() if (!_mdns_server) { return; } - _mdns_service_task_stop(); mdns_service_remove_all(_mdns_server); + _mdns_service_task_stop(); for (i=0; iinstance); free(h->service); free(h->proto); - vSemaphoreDelete(h->lock); + vSemaphoreDelete(h->done_semaphore); if (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)); if (!action) { + HOOK_MALLOC_FAILED; free(new_hostname); 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)); if (!action) { + HOOK_MALLOC_FAILED; free(new_instance); 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)); if (!item) { + HOOK_MALLOC_FAILED; _mdns_free_service(s); 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)); if (!action) { + HOOK_MALLOC_FAILED; _mdns_free_service(s); free(item); 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)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } 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)); if (!action) { + HOOK_MALLOC_FAILED; _mdns_free_linked_txt(new_txt); 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)); if (!action) { + HOOK_MALLOC_FAILED; 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)); if (!action) { + HOOK_MALLOC_FAILED; 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)); if (!action) { + HOOK_MALLOC_FAILED; free(new_instance); 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)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } 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)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } 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); return ESP_ERR_NO_MEM; } - xSemaphoreTake(search->lock, portMAX_DELAY); + xSemaphoreTake(search->done_semaphore, portMAX_DELAY); *results = search->result; _mdns_search_free(search); diff --git a/components/mdns/src/mdns_console.c b/components/mdns/src/mdns_console.c index 4ac521c9..17bffa55 100644 --- a/components/mdns/src/mdns_console.c +++ b/components/mdns/src/mdns_console.c @@ -11,7 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -#ifdef MDNS_ENABLE_CONSOLE #include #include #include "esp_console.h" @@ -1058,4 +1057,4 @@ void mdns_console_register() register_mdns_query_ip(); register_mdns_query_svc(); } -#endif + diff --git a/components/mdns/src/mdns_networking.c b/components/mdns/src/mdns_networking.c index b8c5bd62..3ccc124e 100644 --- a/components/mdns/src/mdns_networking.c +++ b/components/mdns/src/mdns_networking.c @@ -4,8 +4,9 @@ * */ #include -#include +#include "mdns_private.h" #include "mdns_networking.h" +#include "esp_log.h" extern mdns_server_t * _mdns_server; @@ -14,6 +15,7 @@ extern mdns_server_t * _mdns_server; * MDNS Server Networking * */ +static const char *TAG = "MDNS_Networking"; 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)); if (!packet) { + HOOK_MALLOC_FAILED; //missed packet - no memory pbuf_free(this_pb); continue; @@ -240,6 +243,9 @@ typedef struct { struct tcpip_api_call_data call; tcpip_adapter_if_t tcpip_if; mdns_ip_protocol_t ip_protocol; + struct pbuf *pbt; + const ip_addr_t *ip; + uint16_t port; esp_err_t err; } 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, .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; } @@ -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, .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; } +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) { - 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); if (pbt == NULL) { return 0; } memcpy((uint8_t *)pbt->payload, data, len); - err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif); - pbuf_free(pbt); - if (err) { + mdns_api_call_t msg = { + .tcpip_if = tcpip_if, + .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 len; diff --git a/examples/protocols/mdns/CMakeLists.txt b/examples/protocols/mdns/CMakeLists.txt index ced29ce4..88b7c1e3 100644 --- a/examples/protocols/mdns/CMakeLists.txt +++ b/examples/protocols/mdns/CMakeLists.txt @@ -1,6 +1,6 @@ -# The following five lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly +# The following 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) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(mdns) +project(mdns-test) diff --git a/examples/protocols/mdns/main/CMakeLists.txt b/examples/protocols/mdns/main/CMakeLists.txt index 0391d47a..814837ea 100644 --- a/examples/protocols/mdns/main/CMakeLists.txt +++ b/examples/protocols/mdns/main/CMakeLists.txt @@ -1,3 +1,4 @@ set(COMPONENT_SRCS "mdns_example_main.c") +set(COMPONENT_ADD_INCLUDEDIRS ".") register_component() diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index 3122e030..a55b0bf4 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -8,7 +8,7 @@ config WIFI_SSID config WIFI_PASSWORD string "WiFi Password" - default "myssid" + default "mypassword" help WiFi password (WPA or WPA2) for the example to use. @@ -26,4 +26,4 @@ config MDNS_INSTANCE help mDNS Instance Name for example to use -endmenu \ No newline at end of file +endmenu diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c old mode 100755 new mode 100644 index 6023c0b4..bac352da --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -145,13 +145,13 @@ static void mdns_print_results(mdns_result_t * results){ if(r->txt_count){ printf(" TXT : [%u] ", r->txt_count); for(t=0; ttxt_count; t++){ - printf("%s=%s; ", r->txt[t].key, r->txt[t].value); + printf("%s=%s; ", r->txt[t].key, r->txt[t].value?r->txt[t].value:"NULL"); } printf("\n"); } a = r->addr; while(a){ - if(a->addr.type == MDNS_IP_PROTOCOL_V6){ + if(a->addr.type == IPADDR_TYPE_V6){ printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); } else { printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); @@ -170,7 +170,7 @@ static void query_mdns_service(const char * service_name, const char * proto) mdns_result_t * results = NULL; esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); if(err){ - ESP_LOGE(TAG, "Query Failed"); + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); return; } if(!results){ @@ -192,10 +192,10 @@ static void query_mdns_host(const char * host_name) esp_err_t err = mdns_query_a(host_name, 2000, &addr); if(err){ if(err == ESP_ERR_NOT_FOUND){ - ESP_LOGW(TAG, "Host was not found!"); + ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err)); return; } - ESP_LOGE(TAG, "Query Failed"); + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); return; }