fix(mdns): Fix API races setting instance name for services

Fixes **API race issue** (described in 8a690503) for API
mdns_service_instance_name_set_for_host()
This commit is contained in:
David Cermak
2024-07-23 10:46:26 +02:00
parent f9f234c440
commit 643dc6d43b
2 changed files with 28 additions and 56 deletions

View File

@ -5108,9 +5108,6 @@ static void _mdns_free_action(mdns_action_t *action)
case ACTION_INSTANCE_SET: case ACTION_INSTANCE_SET:
free(action->data.instance); free(action->data.instance);
break; break;
case ACTION_SERVICE_INSTANCE_SET:
free(action->data.srv_instance.instance);
break;
case ACTION_SEARCH_ADD: case ACTION_SEARCH_ADD:
//fallthrough //fallthrough
case ACTION_SEARCH_SEND: case ACTION_SEARCH_SEND:
@ -5172,15 +5169,6 @@ static void _mdns_execute_action(mdns_action_t *action)
_mdns_server->instance = action->data.instance; _mdns_server->instance = action->data.instance;
_mdns_restart_all_pcbs_no_instance(); _mdns_restart_all_pcbs_no_instance();
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; break;
case ACTION_SERVICES_CLEAR: case ACTION_SERVICES_CLEAR:
_mdns_send_final_bye(false); _mdns_send_final_bye(false);
@ -6344,57 +6332,46 @@ esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const cha
mdns_service_t *srv = s->service; mdns_service_t *srv = s->service;
mdns_subtype_t *subtype_item = (mdns_subtype_t *)malloc(sizeof(mdns_subtype_t)); mdns_subtype_t *subtype_item = (mdns_subtype_t *)malloc(sizeof(mdns_subtype_t));
ESP_GOTO_ON_FALSE(subtype_item, ESP_ERR_NO_MEM, err, TAG, "Out of memory"); ESP_GOTO_ON_FALSE(subtype_item, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory");
subtype_item->subtype = strdup(subtype); subtype_item->subtype = strdup(subtype);
ESP_GOTO_ON_FALSE(subtype_item->subtype, ESP_ERR_NO_MEM, err, TAG, "Out of memory"); ESP_GOTO_ON_FALSE(subtype_item->subtype, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory");
subtype_item->next = srv->subtype; subtype_item->next = srv->subtype;
srv->subtype = subtype_item; srv->subtype = subtype_item;
err: err:
MDNS_SERVICE_UNLOCK(); MDNS_SERVICE_UNLOCK();
if (ret == ESP_ERR_NO_MEM) { return ret;
HOOK_MALLOC_FAILED; out_of_mem:
} MDNS_SERVICE_UNLOCK();
HOOK_MALLOC_FAILED;
free(subtype_item);
return ret; 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) const char *instance)
{ {
MDNS_SERVICE_LOCK(); MDNS_SERVICE_LOCK();
if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { esp_err_t ret = ESP_OK;
MDNS_SERVICE_UNLOCK(); const char *hostname = host ? host : _mdns_server->hostname;
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;
}
mdns_action_t *action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) &&
if (!action) { !_str_null_or_empty(instance) && strlen(instance) <= (MDNS_NAME_BUF_LEN - 1), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments");
HOOK_MALLOC_FAILED;
free(new_instance); mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_old, service, proto, hostname);
return ESP_ERR_NO_MEM; 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; s->service->instance = strndup(instance, MDNS_NAME_BUF_LEN - 1);
action->data.srv_instance.service = s; ESP_GOTO_ON_FALSE(s->service->instance, ESP_ERR_NO_MEM, err, TAG, "Out of memory");
action->data.srv_instance.instance = new_instance; _mdns_probe_all_pcbs(&s, 1, false, false);
if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) {
free(new_instance); err:
free(action); MDNS_SERVICE_UNLOCK();
return ESP_ERR_NO_MEM; return ret;
}
return ESP_OK;
} }
esp_err_t mdns_service_instance_name_set(const char *service, const char *proto, const char *instance) esp_err_t mdns_service_instance_name_set(const char *service, const char *proto, const char *instance)
@ -6402,7 +6379,7 @@ esp_err_t mdns_service_instance_name_set(const char *service, const char *proto,
if (!_mdns_server) { if (!_mdns_server) {
return ESP_ERR_INVALID_STATE; 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 *host) esp_err_t mdns_service_remove_for_host(const char *instance, const char *service, const char *proto, const char *host)
@ -6413,7 +6390,7 @@ esp_err_t mdns_service_remove_for_host(const char *instance, const char *service
ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto), 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"); ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments");
mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname);
ESP_GOTO_ON_FALSE(s, ESP_ERR_INVALID_ARG, err, TAG, "Service doesn't exist"); ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist");
mdns_srv_item_t *a = _mdns_server->services; mdns_srv_item_t *a = _mdns_server->services;
mdns_srv_item_t *b = a; mdns_srv_item_t *b = a;

View File

@ -187,7 +187,6 @@ typedef enum {
ACTION_SYSTEM_EVENT, ACTION_SYSTEM_EVENT,
ACTION_HOSTNAME_SET, ACTION_HOSTNAME_SET,
ACTION_INSTANCE_SET, ACTION_INSTANCE_SET,
ACTION_SERVICE_INSTANCE_SET,
ACTION_SERVICES_CLEAR, ACTION_SERVICES_CLEAR,
ACTION_SEARCH_ADD, ACTION_SEARCH_ADD,
ACTION_SEARCH_SEND, ACTION_SEARCH_SEND,
@ -439,10 +438,6 @@ typedef struct {
mdns_if_t interface; mdns_if_t interface;
mdns_event_actions_t event_action; mdns_event_actions_t event_action;
} sys_event; } sys_event;
struct {
mdns_srv_item_t *service;
char *instance;
} srv_instance;
struct { struct {
mdns_search_once_t *search; mdns_search_once_t *search;
} search_add; } search_add;