diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index d3961ab49..473750bfc 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -17,6 +17,7 @@ #include "mdns_networking.h" #include "esp_log.h" #include "esp_random.h" +#include "esp_check.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); @@ -5107,26 +5108,6 @@ static void _mdns_free_action(mdns_action_t *action) case ACTION_INSTANCE_SET: free(action->data.instance); break; - case ACTION_SERVICE_ADD: - _mdns_free_service(action->data.srv_add.service->service); - free(action->data.srv_add.service); - break; - case ACTION_SERVICE_INSTANCE_SET: - free(action->data.srv_instance.instance); - break; - case ACTION_SERVICE_TXT_REPLACE: - _mdns_free_linked_txt(action->data.srv_txt_replace.txt); - break; - case ACTION_SERVICE_TXT_SET: - free(action->data.srv_txt_set.key); - free(action->data.srv_txt_set.value); - break; - case ACTION_SERVICE_TXT_DEL: - free(action->data.srv_txt_del.key); - break; - case ACTION_SERVICE_SUBTYPE_ADD: - free(action->data.srv_subtype_add.subtype); - break; case ACTION_SEARCH_ADD: //fallthrough case ACTION_SEARCH_SEND: @@ -5167,14 +5148,6 @@ static void _mdns_free_action(mdns_action_t *action) */ static void _mdns_execute_action(mdns_action_t *action) { - mdns_srv_item_t *a = NULL; - mdns_service_t *service; - char *key; - char *value; - char *subtype; - mdns_subtype_t *subtype_item; - mdns_txt_linked_item_t *txt, * t; - switch (action->type) { case ACTION_SYSTEM_EVENT: perform_event_action(action->data.sys_event.interface, action->data.sys_event.event_action); @@ -5194,177 +5167,6 @@ static void _mdns_execute_action(mdns_action_t *action) _mdns_server->instance = action->data.instance; _mdns_restart_all_pcbs_no_instance(); - break; - case ACTION_SERVICE_ADD: - action->data.srv_add.service->next = _mdns_server->services; - _mdns_server->services = action->data.srv_add.service; - _mdns_probe_all_pcbs(&action->data.srv_add.service, 1, false, false); - break; - case ACTION_SERVICE_INSTANCE_SET: - if (action->data.srv_instance.service->service->instance) { - _mdns_send_bye(&action->data.srv_instance.service, 1, false); - free((char *)action->data.srv_instance.service->service->instance); - } - action->data.srv_instance.service->service->instance = action->data.srv_instance.instance; - _mdns_probe_all_pcbs(&action->data.srv_instance.service, 1, false, false); - - break; - case ACTION_SERVICE_PORT_SET: - action->data.srv_port.service->service->port = action->data.srv_port.port; - _mdns_announce_all_pcbs(&action->data.srv_port.service, 1, true); - - break; - case ACTION_SERVICE_TXT_REPLACE: - service = action->data.srv_txt_replace.service->service; - txt = service->txt; - service->txt = NULL; - _mdns_free_linked_txt(txt); - service->txt = action->data.srv_txt_replace.txt; - _mdns_announce_all_pcbs(&action->data.srv_txt_replace.service, 1, false); - - break; - case ACTION_SERVICE_TXT_SET: - service = action->data.srv_txt_set.service->service; - key = action->data.srv_txt_set.key; - value = action->data.srv_txt_set.value; - txt = service->txt; - while (txt) { - if (strcmp(txt->key, key) == 0) { - free((char *)txt->value); - free(key); - txt->value = value; - txt->value_len = action->data.srv_txt_set.value_len; - break; - } - txt = txt->next; - } - if (!txt) { - txt = (mdns_txt_linked_item_t *)malloc(sizeof(mdns_txt_linked_item_t)); - if (!txt) { - HOOK_MALLOC_FAILED; - _mdns_free_action(action); - return; - } - txt->key = key; - txt->value = value; - txt->value_len = action->data.srv_txt_set.value_len; - txt->next = service->txt; - service->txt = txt; - } - - _mdns_announce_all_pcbs(&action->data.srv_txt_set.service, 1, false); - - break; - case ACTION_SERVICE_TXT_DEL: - service = action->data.srv_txt_del.service->service; - key = action->data.srv_txt_del.key; - txt = service->txt; - if (!txt) { - break; - } - if (strcmp(txt->key, key) == 0) { - service->txt = txt->next; - free((char *)txt->key); - free((char *)txt->value); - free(txt); - } else { - while (txt->next) { - if (strcmp(txt->next->key, key) == 0) { - t = txt->next; - txt->next = t->next; - free((char *)t->key); - free((char *)t->value); - free(t); - break; - } else { - txt = txt->next; - } - } - } - free(key); - - _mdns_announce_all_pcbs(&action->data.srv_txt_set.service, 1, false); - - break; - case ACTION_SERVICE_SUBTYPE_ADD: - service = action->data.srv_subtype_add.service->service; - subtype = action->data.srv_subtype_add.subtype; - subtype_item = (mdns_subtype_t *)malloc(sizeof(mdns_subtype_t)); - if (!subtype_item) { - HOOK_MALLOC_FAILED; - _mdns_free_action(action); - return; - } - subtype_item->subtype = subtype; - subtype_item->next = service->subtype; - service->subtype = subtype_item; - break; - case ACTION_SERVICE_DEL: - a = _mdns_server->services; - mdns_srv_item_t *b = a; - if (action->data.srv_del.instance) { - while (a) { - if (_mdns_service_match_instance(a->service, action->data.srv_del.instance, - action->data.srv_del.service, action->data.srv_del.proto, - action->data.srv_del.hostname)) { - if (_mdns_server->services != a) { - b->next = a->next; - } else { - _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); - break; - } - b = a; - a = a->next; - } - } else { - while (a) { - if (_mdns_service_match(a->service, action->data.srv_del.service, action->data.srv_del.proto, - action->data.srv_del.hostname)) { - if (_mdns_server->services != a) { - b->next = a->next; - _mdns_send_bye(&a, 1, false); - _mdns_remove_scheduled_service_packets(a->service); - _mdns_free_service(a->service); - free(a); - a = b->next; - continue; - } else { - _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); - a = _mdns_server->services; - b = a; - continue; - } - } - b = a; - a = a->next; - } - } - free((char *)action->data.srv_del.instance); - free((char *)action->data.srv_del.service); - free((char *)action->data.srv_del.proto); - free((char *)action->data.srv_del.hostname); - break; - case ACTION_SERVICES_CLEAR: - _mdns_send_final_bye(false); - a = _mdns_server->services; - _mdns_server->services = NULL; - 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); - } - break; case ACTION_SEARCH_ADD: _mdns_search_add(action->data.search_add.search); @@ -5409,6 +5211,7 @@ static void _mdns_execute_action(mdns_action_t *action) free((char *)action->data.delegate_hostname.hostname); 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, @@ -5972,6 +5775,7 @@ esp_err_t mdns_delegate_hostname_add(const char *hostname, const mdns_ip_addr_t free(action); return ESP_ERR_NO_MEM; } + xSemaphoreTake(_mdns_server->action_sema, portMAX_DELAY); return ESP_OK; } @@ -6076,7 +5880,7 @@ esp_err_t mdns_instance_name_set(const char *instance) * MDNS SERVICES * */ -esp_err_t mdns_service_add_for_host(const char *instance, const char *service, const char *proto, const char *hostname, +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) || !port || !_mdns_server->hostname) { @@ -6084,69 +5888,37 @@ esp_err_t mdns_service_add_for_host(const char *instance, const char *service, c } MDNS_SERVICE_LOCK(); - if (!_mdns_can_add_more_services()) { - MDNS_SERVICE_UNLOCK(); - return ESP_ERR_NO_MEM; - } + esp_err_t ret = ESP_OK; + const char *hostname = host ? host : _mdns_server->hostname; + mdns_service_t *s = NULL; - if (!hostname) { - hostname = _mdns_server->hostname; - } + ESP_GOTO_ON_FALSE(_mdns_can_add_more_services(), ESP_ERR_NO_MEM, err, TAG, "Cannot add more services"); mdns_srv_item_t *item = _mdns_get_service_item_instance(instance, service, proto, hostname); - MDNS_SERVICE_UNLOCK(); - if (item) { - return ESP_ERR_INVALID_ARG; - } + ESP_GOTO_ON_FALSE(!item, ESP_ERR_INVALID_ARG, err, TAG, "Service already exists"); - mdns_service_t *s = _mdns_create_service(service, proto, hostname, port, instance, num_items, txt); - if (!s) { - return ESP_ERR_NO_MEM; - } + s = _mdns_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 *)malloc(sizeof(mdns_srv_item_t)); - if (!item) { - HOOK_MALLOC_FAILED; - _mdns_free_service(s); - return ESP_ERR_NO_MEM; - } + ESP_GOTO_ON_FALSE(item, ESP_ERR_NO_MEM, err, TAG, "Cannot create service: Out of memory"); item->service = s; item->next = NULL; - 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; - } - action->type = ACTION_SERVICE_ADD; - action->data.srv_add.service = item; - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - _mdns_free_service(s); - free(item); - free(action); - return ESP_ERR_NO_MEM; - } - - size_t start = xTaskGetTickCount(); - size_t timeout_ticks = pdMS_TO_TICKS(MDNS_SERVICE_ADD_TIMEOUT_MS); - MDNS_SERVICE_LOCK(); - mdns_srv_item_t *target = _mdns_get_service_item_instance(instance, service, proto, hostname); + item->next = _mdns_server->services; + _mdns_server->services = item; + _mdns_probe_all_pcbs(&item, 1, false, false); MDNS_SERVICE_UNLOCK(); - while (target == NULL) { - uint32_t expired = xTaskGetTickCount() - start; - if (expired >= timeout_ticks) { - return ESP_FAIL; // Timeout - } - vTaskDelay(MIN(10 / portTICK_PERIOD_MS, timeout_ticks - expired)); - MDNS_SERVICE_LOCK(); - target = _mdns_get_service_item_instance(instance, service, proto, hostname); - MDNS_SERVICE_UNLOCK(); - } - return ESP_OK; + +err: + MDNS_SERVICE_UNLOCK(); + _mdns_free_service(s); + if (ret == ESP_ERR_NO_MEM) { + HOOK_MALLOC_FAILED; + } + return ret; } esp_err_t mdns_service_add(const char *instance, const char *service, const char *proto, uint16_t port, @@ -6155,7 +5927,7 @@ esp_err_t mdns_service_add(const char *instance, const char *service, const char if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_add_for_host(instance, service, proto, _mdns_server->hostname, port, txt, num_items); + return mdns_service_add_for_host(instance, service, proto, NULL, port, txt, num_items); } bool mdns_service_exists(const char *service_type, const char *proto, const char *hostname) @@ -6184,6 +5956,11 @@ static mdns_txt_item_t *_copy_mdns_txt_items(mdns_txt_linked_item_t *items, uint for (mdns_txt_linked_item_t *tmp = items; tmp != NULL; tmp = tmp->next) { ret_index++; } + if (ret_index == 0) { + *txt_count = 0; + *txt_value_len = NULL; + return NULL; + } *txt_count = ret_index; if (ret_index == 0) { // handle empty TXT *txt_value_len = NULL; @@ -6322,32 +6099,22 @@ handle_error: return NULL; } -esp_err_t mdns_service_port_set_for_host(const char *instance, const char *service, const char *proto, const char *hostname, uint16_t port) +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(); - if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { - MDNS_SERVICE_UNLOCK(); - return ESP_ERR_INVALID_ARG; - } + 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, + 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_SERVICE_UNLOCK(); - if (!s) { - return ESP_ERR_NOT_FOUND; - } + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); - 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; - action->data.srv_port.service = s; - action->data.srv_port.port = port; - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; + s->service->port = port; + _mdns_announce_all_pcbs(&s, 1, true); + +err: + MDNS_SERVICE_UNLOCK(); + return ret; } esp_err_t mdns_service_port_set(const char *service, const char *proto, uint16_t port) @@ -6355,47 +6122,37 @@ esp_err_t mdns_service_port_set(const char *service, const char *proto, uint16_t if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_port_set_for_host(NULL, service, proto, _mdns_server->hostname, port); + return mdns_service_port_set_for_host(NULL, service, proto, NULL, port); } -esp_err_t mdns_service_txt_set_for_host(const char *instance, const char *service, const char *proto, const char *hostname, - mdns_txt_item_t txt[], uint8_t num_items) +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(); - if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || (num_items && txt == NULL)) { - MDNS_SERVICE_UNLOCK(); - return ESP_ERR_INVALID_ARG; - } + 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), + 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_SERVICE_UNLOCK(); - if (!s) { - return ESP_ERR_NOT_FOUND; - } + 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); + new_txt = _mdns_allocate_txt(num_items, txt_items); if (!new_txt) { return ESP_ERR_NO_MEM; } } + mdns_service_t *srv = s->service; + mdns_txt_linked_item_t *txt = srv->txt; + srv->txt = NULL; + _mdns_free_linked_txt(txt); + srv->txt = new_txt; + _mdns_announce_all_pcbs(&s, 1, false); - 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; - } - action->type = ACTION_SERVICE_TXT_REPLACE; - action->data.srv_txt_replace.service = s; - action->data.srv_txt_replace.txt = new_txt; - - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - _mdns_free_linked_txt(new_txt); - free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; +err: + MDNS_SERVICE_UNLOCK(); + return ret; } esp_err_t mdns_service_txt_set(const char *service, const char *proto, mdns_txt_item_t txt[], uint8_t num_items) @@ -6403,57 +6160,63 @@ esp_err_t mdns_service_txt_set(const char *service, const char *proto, mdns_txt_ if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_txt_set_for_host(NULL, service, proto, _mdns_server->hostname, txt, num_items); + return mdns_service_txt_set_for_host(NULL, service, proto, NULL, txt, num_items); } 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 *hostname, const char *key, - const char *value, uint8_t value_len) + const char *host, const char *key, const char *value_arg, uint8_t value_len) { MDNS_SERVICE_LOCK(); - if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || - _str_null_or_empty(key) || (!value && value_len)) { - MDNS_SERVICE_UNLOCK(); - return ESP_ERR_INVALID_ARG; - } + 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) && + !((!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_SERVICE_UNLOCK(); - if (!s) { - return ESP_ERR_NOT_FOUND; + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); + + mdns_service_t *srv = s->service; + if (value_len > 0) { + value = (char *) malloc(value_len); + ESP_GOTO_ON_FALSE(value, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + memcpy(value, value_arg, value_len); + } else { + value_len = 0; } - mdns_action_t *action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); - if (!action) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; + mdns_txt_linked_item_t *txt = srv->txt; + while (txt) { + if (strcmp(txt->key, key) == 0) { + free((char *)txt->value); + txt->value = value; + txt->value_len = value_len; + break; + } + txt = txt->next; + } + if (!txt) { + new_txt = (mdns_txt_linked_item_t *)malloc(sizeof(mdns_txt_linked_item_t)); + ESP_GOTO_ON_FALSE(new_txt, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + new_txt->key = strdup(key); + ESP_GOTO_ON_FALSE(new_txt->key, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + new_txt->value = value; + new_txt->value_len = value_len; + new_txt->next = srv->txt; + srv->txt = new_txt; } - action->type = ACTION_SERVICE_TXT_SET; - action->data.srv_txt_set.service = s; - action->data.srv_txt_set.key = strdup(key); - if (!action->data.srv_txt_set.key) { - free(action); - return ESP_ERR_NO_MEM; - } - if (value_len > 0) { - action->data.srv_txt_set.value = (char *)malloc(value_len); - if (!action->data.srv_txt_set.value) { - free(action->data.srv_txt_set.key); - free(action); - return ESP_ERR_NO_MEM; - } - memcpy(action->data.srv_txt_set.value, value, value_len); - action->data.srv_txt_set.value_len = value_len; - } else { - action->data.srv_txt_set.value = NULL; - action->data.srv_txt_set.value_len = 0; - } - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - free(action->data.srv_txt_set.key); - free(action->data.srv_txt_set.value); - free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; + _mdns_announce_all_pcbs(&s, 1, false); + +err: + MDNS_SERVICE_UNLOCK(); + return ret; +out_of_mem: + MDNS_SERVICE_UNLOCK(); + HOOK_MALLOC_FAILED; + free(value); + free(new_txt); + return ret; } esp_err_t mdns_service_txt_item_set_for_host(const char *instance, const char *service, const char *proto, const char *hostname, @@ -6469,7 +6232,7 @@ esp_err_t mdns_service_txt_item_set(const char *service, const char *proto, cons if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, _mdns_server->hostname, key, + return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, NULL, key, value, strlen(value)); } @@ -6479,42 +6242,54 @@ esp_err_t mdns_service_txt_item_set_with_explicit_value_len(const char *service, if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, _mdns_server->hostname, key, - value, value_len); + return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, NULL, key, value, value_len); } -esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char *service, const char *proto, const char *hostname, +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(); - if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(key)) { - MDNS_SERVICE_UNLOCK(); - return ESP_ERR_INVALID_ARG; - } + 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), + 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_SERVICE_UNLOCK(); - if (!s) { - return ESP_ERR_NOT_FOUND; + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); + + mdns_service_t *srv = s->service; + mdns_txt_linked_item_t *txt = srv->txt; + if (!txt) { + goto err; } - mdns_action_t *action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); - if (!action) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; + if (strcmp(txt->key, key) == 0) { + srv->txt = txt->next; + free((char *)txt->key); + free((char *)txt->value); + free(txt); + } else { + while (txt->next) { + if (strcmp(txt->next->key, key) == 0) { + mdns_txt_linked_item_t *t = txt->next; + txt->next = t->next; + free((char *)t->key); + free((char *)t->value); + free(t); + break; + } else { + txt = txt->next; + } + } } - action->type = ACTION_SERVICE_TXT_DEL; - action->data.srv_txt_del.service = s; - action->data.srv_txt_del.key = strdup(key); - if (!action->data.srv_txt_del.key) { - free(action); - return ESP_ERR_NO_MEM; + _mdns_announce_all_pcbs(&s, 1, false); + +err: + MDNS_SERVICE_UNLOCK(); + if (ret == ESP_ERR_NO_MEM) { + HOOK_MALLOC_FAILED; } - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - free(action->data.srv_txt_del.key); - free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; + return ret; } esp_err_t mdns_service_txt_item_remove(const char *service, const char *proto, const char *key) @@ -6522,92 +6297,68 @@ esp_err_t mdns_service_txt_item_remove(const char *service, const char *proto, c if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_txt_item_remove_for_host(NULL, service, proto, _mdns_server->hostname, key); + return mdns_service_txt_item_remove_for_host(NULL, service, proto, NULL, key); } esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const char *service, const char *proto, const char *hostname, const char *subtype) { MDNS_SERVICE_LOCK(); - if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || - _str_null_or_empty(subtype)) { - MDNS_SERVICE_UNLOCK(); - return ESP_ERR_INVALID_ARG; - } + 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"); + mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_name, service, proto, hostname); - MDNS_SERVICE_UNLOCK(); - if (!s) { - return ESP_ERR_NOT_FOUND; - } + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); mdns_subtype_t *srv_subtype = s->service->subtype; while (srv_subtype) { - if (strcmp(srv_subtype->subtype, subtype) == 0) { - // The same subtype has already been added - return ESP_ERR_INVALID_ARG; - } + ESP_GOTO_ON_FALSE(strcmp(srv_subtype->subtype, subtype) != 0, ESP_ERR_INVALID_ARG, err, TAG, "The same subtype has already been added"); srv_subtype = srv_subtype->next; } - mdns_action_t *action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); - if (!action) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; - } + mdns_service_t *srv = s->service; + mdns_subtype_t *subtype_item = (mdns_subtype_t *)malloc(sizeof(mdns_subtype_t)); + ESP_GOTO_ON_FALSE(subtype_item, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + subtype_item->subtype = strdup(subtype); + ESP_GOTO_ON_FALSE(subtype_item->subtype, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + subtype_item->next = srv->subtype; + srv->subtype = subtype_item; - action->type = ACTION_SERVICE_SUBTYPE_ADD; - action->data.srv_subtype_add.service = s; - action->data.srv_subtype_add.subtype = strdup(subtype); - - if (!action->data.srv_subtype_add.subtype) { - free(action); - return ESP_ERR_NO_MEM; - } - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - free(action->data.srv_subtype_add.subtype); - free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; +err: + MDNS_SERVICE_UNLOCK(); + return ret; +out_of_mem: + MDNS_SERVICE_UNLOCK(); + HOOK_MALLOC_FAILED; + free(subtype_item); + return ret; } -esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, const char *service, const char *proto, const char *hostname, +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(); - if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { - MDNS_SERVICE_UNLOCK(); - return ESP_ERR_INVALID_ARG; - } - if (_str_null_or_empty(instance) || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { - MDNS_SERVICE_UNLOCK(); - return ESP_ERR_INVALID_ARG; - } - mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_old, service, proto, hostname); - MDNS_SERVICE_UNLOCK(); - if (!s) { - return ESP_ERR_NOT_FOUND; - } - char *new_instance = strndup(instance, MDNS_NAME_BUF_LEN - 1); - if (!new_instance) { - return ESP_ERR_NO_MEM; - } + esp_err_t ret = ESP_OK; + const char *hostname = host ? host : _mdns_server->hostname; - 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; + 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); + 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); + free((char *)s->service->instance); } - action->type = ACTION_SERVICE_INSTANCE_SET; - action->data.srv_instance.service = s; - action->data.srv_instance.instance = new_instance; - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - free(new_instance); - free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; + s->service->instance = 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); + +err: + MDNS_SERVICE_UNLOCK(); + return ret; } esp_err_t mdns_service_instance_name_set(const char *service, const char *proto, const char *instance) @@ -6615,62 +6366,68 @@ esp_err_t mdns_service_instance_name_set(const char *service, const char *proto, if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_instance_name_set_for_host(NULL, service, proto, _mdns_server->hostname, instance); + return mdns_service_instance_name_set_for_host(NULL, service, proto, NULL, instance); } -esp_err_t mdns_service_remove_for_host(const char *instance, const char *service, const char *proto, const char *hostname) +esp_err_t mdns_service_remove_for_host(const char *instance, const char *service, const char *proto, const char *host) { MDNS_SERVICE_LOCK(); - if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { - MDNS_SERVICE_UNLOCK(); - return ESP_ERR_INVALID_ARG; - } + 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), + ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); mdns_srv_item_t *s = _mdns_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_server->services != a) { + b->next = a->next; + } else { + _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); + break; + } + b = a; + a = a->next; + } + } else { + while (a) { + if (_mdns_service_match(a->service, service, proto, hostname)) { + if (_mdns_server->services != a) { + b->next = a->next; + _mdns_send_bye(&a, 1, false); + _mdns_remove_scheduled_service_packets(a->service); + _mdns_free_service(a->service); + free(a); + a = b->next; + continue; + } else { + _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); + a = _mdns_server->services; + b = a; + continue; + } + } + b = a; + a = a->next; + } + } + +err: MDNS_SERVICE_UNLOCK(); - if (!s) { - return ESP_ERR_NOT_FOUND; - } - - 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; - action->data.srv_del.instance = NULL; - action->data.srv_del.hostname = NULL; - if (!_str_null_or_empty(instance)) { - action->data.srv_del.instance = strndup(instance, MDNS_NAME_BUF_LEN - 1); - if (!action->data.srv_del.instance) { - goto fail; - } - } - - if (!_str_null_or_empty(hostname)) { - action->data.srv_del.hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); - if (!action->data.srv_del.hostname) { - goto fail; - } - } - - action->data.srv_del.service = strndup(service, MDNS_NAME_BUF_LEN - 1); - action->data.srv_del.proto = strndup(proto, MDNS_NAME_BUF_LEN - 1); - if (!action->data.srv_del.service || !action->data.srv_del.proto) { - goto fail; - } - - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - goto fail; - } - return ESP_OK; - -fail: - free((char *)action->data.srv_del.instance); - free((char *)action->data.srv_del.service); - free((char *)action->data.srv_del.proto); - free((char *)action->data.srv_del.hostname); - free(action); - return ESP_ERR_NO_MEM; + return ret; } esp_err_t mdns_service_remove(const char *service_type, const char *proto) @@ -6678,32 +6435,32 @@ esp_err_t mdns_service_remove(const char *service_type, const char *proto) if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_remove_for_host(NULL, service_type, proto, _mdns_server->hostname); + return mdns_service_remove_for_host(NULL, service_type, proto, NULL); } esp_err_t mdns_service_remove_all(void) { - if (!_mdns_server) { - return ESP_ERR_INVALID_ARG; - } MDNS_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) { - MDNS_SERVICE_UNLOCK(); - return ESP_OK; + goto done; } - MDNS_SERVICE_UNLOCK(); - mdns_action_t *action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); - if (!action) { - HOOK_MALLOC_FAILED; - return ESP_ERR_NO_MEM; + _mdns_send_final_bye(false); + mdns_srv_item_t *services = _mdns_server->services; + _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(s); } - action->type = ACTION_SERVICES_CLEAR; - if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { - free(action); - return ESP_ERR_NO_MEM; - } - return ESP_OK; + +done: + MDNS_SERVICE_UNLOCK(); + return ret; } /* diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index f3dbb09d2..381bd4be4 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -187,15 +187,6 @@ typedef enum { ACTION_SYSTEM_EVENT, ACTION_HOSTNAME_SET, ACTION_INSTANCE_SET, - ACTION_SERVICE_ADD, - ACTION_SERVICE_DEL, - ACTION_SERVICE_INSTANCE_SET, - ACTION_SERVICE_PORT_SET, - ACTION_SERVICE_TXT_REPLACE, - ACTION_SERVICE_TXT_SET, - ACTION_SERVICE_TXT_DEL, - ACTION_SERVICE_SUBTYPE_ADD, - ACTION_SERVICES_CLEAR, ACTION_SEARCH_ADD, ACTION_SEARCH_SEND, ACTION_SEARCH_END, @@ -446,41 +437,6 @@ typedef struct { mdns_if_t interface; mdns_event_actions_t event_action; } sys_event; - struct { - mdns_srv_item_t *service; - } srv_add; - struct { - char *instance; - char *service; - char *proto; - char *hostname; - } srv_del; - struct { - mdns_srv_item_t *service; - char *instance; - } srv_instance; - struct { - mdns_srv_item_t *service; - uint16_t port; - } srv_port; - struct { - mdns_srv_item_t *service; - mdns_txt_linked_item_t *txt; - } srv_txt_replace; - struct { - mdns_srv_item_t *service; - char *key; - char *value; - uint8_t value_len; - } srv_txt_set; - struct { - mdns_srv_item_t *service; - char *key; - } srv_txt_del; - struct { - mdns_srv_item_t *service; - char *subtype; - } srv_subtype_add; struct { mdns_search_once_t *search; } search_add; diff --git a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.c b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.c index 1f74c7833..14b913411 100644 --- a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.c +++ b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -9,6 +9,7 @@ #include #include #include "esp32_mock.h" +#include "esp_log.h" void *g_queue; int g_queue_send_shall_fail = 0; @@ -111,3 +112,12 @@ BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, { return pdTRUE; } + +void esp_log_write(esp_log_level_t level, const char *tag, const char *format, ...) +{ +} + +uint32_t esp_log_timestamp(void) +{ + return 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 ecd82e0d0..e8e84ceb4 100644 --- a/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -45,11 +45,6 @@ #define portMAX_DELAY 0xFFFFFFFF #define portTICK_PERIOD_MS 1 -#define ESP_LOGW(a,b) -#define ESP_LOGD(a,b) -#define ESP_LOGE(a,b,c) -#define ESP_LOGV(a,b,c,d) - #define LWIP_HDR_PBUF_H #define __ESP_RANDOM_H__ #define INC_TASK_H diff --git a/components/mdns/tests/unit_test/main/test_mdns.c b/components/mdns/tests/unit_test/main/test_mdns.c index 83e6f1b29..ff024e2fc 100644 --- a/components/mdns/tests/unit_test/main/test_mdns.c +++ b/components/mdns/tests/unit_test/main/test_mdns.c @@ -91,6 +91,7 @@ TEST(mdns, api_fails_with_expected_err) TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_item_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, "key1", "value1") ); TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_item_remove(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, "key1") ); TEST_ASSERT_EQUAL(ESP_OK, mdns_service_port_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 8080) ); + yield_to_all_priorities(); // to remove the service with the updated txt records TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO) ); yield_to_all_priorities(); // Make sure that mdns task has executed to remove the service