Skip to content

Commit

Permalink
feat(mdns): support update subtype
Browse files Browse the repository at this point in the history
  • Loading branch information
zwx1995esp committed Nov 14, 2024
1 parent 0b5e362 commit 062b8dc
Show file tree
Hide file tree
Showing 2 changed files with 206 additions and 15 deletions.
64 changes: 63 additions & 1 deletion components/mdns/include/mdns.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ typedef struct {
const char *value; /*!< item value string */
} mdns_txt_item_t;

/**
* @brief mDNS basic subtype item structure
* Used in mdns_service_subtype_xxx() APIs
*/
typedef struct {
const char *subtype; /*!< subtype name */
} mdns_subtype_item_t;

/**
* @brief mDNS query linked list IP item
*/
Expand Down Expand Up @@ -544,7 +552,7 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char
const char *key);

/**
* @brief Add subtype for service.
* @brief Add a subtype for service.
*
* @param instance_name instance name. If NULL, will find the first service with the same service type and protocol.
* @param service_type service type (_http, _ftp, etc)
Expand All @@ -561,6 +569,60 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char
esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const char *service_type, const char *proto,
const char *hostname, const char *subtype);

/**
* @brief Remove a subtype for service.
*
* @param instance_name instance name. If NULL, will find the first service with the same service type and protocol.
* @param service_type service type (_http, _ftp, etc)
* @param proto service protocol (_tcp, _udp)
* @param hostname service hostname. If NULL, local hostname will be used.
* @param subtype The subtype to remove.
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NOT_FOUND Service not found
*/
esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const char *service_type, const char *proto,
const char *hostname, const char *subtype);

/**
* @brief Add multiple subtypes for service at once.
*
* @param instance_name instance name. If NULL, will find the first service with the same service type and protocol.
* @param service_type service type (_http, _ftp, etc)
* @param proto service protocol (_tcp, _udp)
* @param hostname service hostname. If NULL, local hostname will be used.
* @param subtype the pointer of subtype array to add.
* @param num_items number of items in subtype array
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NOT_FOUND Service not found
* - ESP_ERR_NO_MEM memory error
*/
esp_err_t mdns_service_subtype_add_multiple_items_for_host(const char *instance_name, const char *service_type, const char *proto,
const char *hostname, mdns_subtype_item_t subtype[], uint8_t num_items);

/**
* @brief Update subtype for service.
*
* @param instance_name instance name. If NULL, will find the first service with the same service type and protocol.
* @param service_type service type (_http, _ftp, etc)
* @param proto service protocol (_tcp, _udp)
* @param hostname service hostname. If NULL, local hostname will be used.
* @param subtype the pointer of subtype array to add.
* @param num_items number of items in subtype array
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NOT_FOUND Service not found
* - ESP_ERR_NO_MEM memory error
*/
esp_err_t mdns_service_subtype_update_multiple_items_for_host(const char *instance_name, const char *service_type, const char *proto,
const char *hostname, mdns_subtype_item_t subtype[], uint8_t num_items);
/**
* @brief Remove and free all services from mDNS server
*
Expand Down
157 changes: 143 additions & 14 deletions components/mdns/mdns.c
Original file line number Diff line number Diff line change
Expand Up @@ -2794,6 +2794,16 @@ static void _mdns_remove_scheduled_service_packets(mdns_service_t *service)
}
}

static void _mdns_free_service_subtype(mdns_service_t *service)
{
while (service->subtype) {
mdns_subtype_t *next = service->subtype->next;
free((char *)service->subtype->subtype);
free(service->subtype);
service->subtype = next;
}
}

/**
* @brief free service memory
*
Expand All @@ -2815,12 +2825,7 @@ static void _mdns_free_service(mdns_service_t *service)
free((char *)s->value);
free(s);
}
while (service->subtype) {
mdns_subtype_t *next = service->subtype->next;
free((char *)service->subtype->subtype);
free(service->subtype);
service->subtype = next;
}
_mdns_free_service_subtype(service);
free(service);
}

Expand Down Expand Up @@ -6299,7 +6304,36 @@ esp_err_t mdns_service_txt_item_remove(const char *service, const char *proto, c
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,
static esp_err_t _mdns_service_subtype_remove_for_host(mdns_srv_item_t *service, const char *subtype)
{
esp_err_t ret = ESP_ERR_NOT_FOUND;
mdns_subtype_t *srv_subtype = service->service->subtype;
mdns_subtype_t *pre = service->service->subtype;
while (srv_subtype) {
if (strcmp(srv_subtype->subtype, subtype) == 0) {
// Target subtype is found.
if (srv_subtype == service->service->subtype) {
// The first node needs to be removed
service->service->subtype = service->service->subtype->next;
} else {
pre->next = srv_subtype->next;
}
free((char *)srv_subtype->subtype);
free(srv_subtype);
ret = ESP_OK;
break;
}
pre = srv_subtype;
srv_subtype = srv_subtype->next;
}
if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "Subtype : %s doesn't exist", subtype);
}

return ret;
}

esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const char *service, const char *proto,
const char *hostname, const char *subtype)
{
MDNS_SERVICE_LOCK();
Expand All @@ -6310,30 +6344,125 @@ esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const cha
mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_name, service, proto, hostname);
ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist");

mdns_subtype_t *srv_subtype = s->service->subtype;
ret = _mdns_service_subtype_remove_for_host(s, subtype);
ESP_GOTO_ON_ERROR(ret, err, TAG, "Failed to remove the subtype: %s", subtype);

// TODO: Need to transmit a sendbye message for the removed subtype.
// TODO: Need to remove this subtype answer from the scheduled answer list.
err:
MDNS_SERVICE_UNLOCK();
return ret;
}

static esp_err_t _mdns_service_subtype_add_for_host(mdns_srv_item_t *service, const char *subtype)
{
esp_err_t ret = ESP_OK;
mdns_subtype_t *srv_subtype = service->service->subtype;
while (srv_subtype) {
ESP_GOTO_ON_FALSE(strcmp(srv_subtype->subtype, subtype) != 0, ESP_ERR_INVALID_ARG, err, TAG, "The same subtype has already been added");
ESP_GOTO_ON_FALSE(strcmp(srv_subtype->subtype, subtype) != 0, ESP_ERR_INVALID_ARG, err, TAG, "Subtype: %s has already been added", subtype);
srv_subtype = srv_subtype->next;
}

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;
subtype_item->next = service->service->subtype;
service->service->subtype = subtype_item;

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_subtype_add_multiple_items_for_host(const char *instance_name, const char *service, const char *proto,
const char *hostname, mdns_subtype_item_t subtype[], uint8_t num_items)
{
MDNS_SERVICE_LOCK();
esp_err_t ret = ESP_OK;
int cur_index = 0;
ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) &&
(num_items > 0), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments");

mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_name, service, proto, hostname);
ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist");

for (; cur_index < num_items; cur_index++) {
ret = _mdns_service_subtype_add_for_host(s, subtype[cur_index].subtype);
if (ret == ESP_OK) {
continue;
} else if (ret == ESP_ERR_NO_MEM) {
ESP_LOGE(TAG, "Out of memory");
goto err;
} else {
ESP_LOGE(TAG, "Failed to add subtype: %s", subtype[cur_index].subtype);
goto exit;
}
}

_mdns_announce_all_pcbs(&s, 1, false);
err:
if (ret == ESP_ERR_NO_MEM) {
for (int idx = 0; idx < cur_index; idx++) {
_mdns_service_subtype_remove_for_host(s, subtype[idx].subtype);
}
}
exit:
MDNS_SERVICE_UNLOCK();
return ret;
}

esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const char *service_type, const char *proto,
const char *hostname, const char *subtype)
{
mdns_subtype_item_t _subtype[1];
_subtype[0].subtype = subtype;
return mdns_service_subtype_add_multiple_items_for_host(instance_name, service_type, proto, hostname, _subtype, 1);
}

esp_err_t mdns_service_subtype_update_multiple_items_for_host(const char *instance_name, const char *service_type, const char *proto,
const char *hostname, mdns_subtype_item_t subtype[], uint8_t num_items)
{
MDNS_SERVICE_LOCK();
esp_err_t ret = ESP_OK;
int cur_index = 0;
ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service_type) && !_str_null_or_empty(proto) &&
(num_items > 0), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments");

mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_name, service_type, proto, hostname);
ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist");

// TODO: find subtype needs to say sendbye
_mdns_free_service_subtype(s->service);

for (; cur_index < num_items; cur_index++) {
ret = _mdns_service_subtype_add_for_host(s, subtype[cur_index].subtype);
if (ret == ESP_OK) {
continue;
} else if (ret == ESP_ERR_NO_MEM) {
ESP_LOGE(TAG, "Out of memory");
goto err;
} else {
ESP_LOGE(TAG, "Failed to add subtype: %s", subtype[cur_index].subtype);
goto exit;
}
}

_mdns_announce_all_pcbs(&s, 1, false);
err:
if (ret == ESP_ERR_NO_MEM) {
for (int idx = 0; idx < cur_index; idx++) {
_mdns_service_subtype_remove_for_host(s, subtype[idx].subtype);
}
}
exit:
MDNS_SERVICE_UNLOCK();
return ret;
}

esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, const char *service, const char *proto, const char *host,
const char *instance)
{
Expand Down

0 comments on commit 062b8dc

Please sign in to comment.