diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 54cd8a3ee1..416740d137 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -114,11 +114,49 @@ void mdns_free(void); */ esp_err_t mdns_hostname_set(const char * hostname); -esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t *address); +/** + * @brief Adds a hostname and address to be delegated + * A/AAAA queries will be replied for the hostname and + * services can be added to this host. + * + * @param hostname Hostname to add + * @param address_list The IP address list of the host + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + * + */ +esp_err_t mdns_delegate_hostname_add(const char * hostname, const mdns_ip_addr_t *address_list); +/** + * @brief Remove a delegated hostname + * All the services added to this host will also be removed. + * + * @param hostname Hostname to remove + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + * + */ esp_err_t mdns_delegate_hostname_remove(const char * hostname); -bool mdns_hostname_exists(const char *hostname); +/** + * @brief Query whether a hostname has been added + * + * @param hostname Hostname to query + * + * @return + * - true The hostname has been added. + * - false The hostname has not been added. + * + */ +bool mdns_hostname_exists(const char * hostname); /** * @brief Set the default instance name for mDNS server @@ -152,10 +190,39 @@ esp_err_t mdns_instance_name_set(const char * instance_name); esp_err_t mdns_service_add(const char * instance_name, const char * service_type, const char * proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items); -esp_err_t mdns_service_add_custom_host(const char *instance_name, const char *service_type, const char *proto, - const char *hostname, uint16_t port, mdns_txt_item_t txt[], size_t num_items); +/** + * @brief Add service to mDNS server with a delegated hostname + * + * @param instance_name instance name to set. If NULL, + * global instance name or hostname will be used + * @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 port service port + * @param txt string array of TXT data (eg. {{"var","val"},{"other","2"}}) + * @param num_items number of items in TXT data + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + * - ESP_FAIL failed to add service + */ +esp_err_t mdns_service_add_for_host(const char * instance_name, const char * service_type, const char * proto, + const char * hostname, uint16_t port, mdns_txt_item_t txt[], size_t num_items); -bool mdns_service_exists(const char *service_type, const char *proto, const char *hostname); +/** + * @brief Check whether a service has been added. + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, checks for the local hostname. + * + * @return + * - true Correspondding service has been added. + * - false Service not found. + */ +bool mdns_service_exists(const char * service_type, const char * proto, const char * hostname); /** * @brief Remove service from mDNS server @@ -171,6 +238,19 @@ bool mdns_service_exists(const char *service_type, const char *proto, const char */ esp_err_t mdns_service_remove(const char * service_type, const char * proto); +/** + * @brief Remove service from mDNS server with hostname + * + * @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. + * + * @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_remove_for_host(const char * service_type, const char * proto, const char *hostname); /** @@ -188,7 +268,22 @@ esp_err_t mdns_service_remove_for_host(const char * service_type, const char * p */ esp_err_t mdns_service_instance_name_set(const char * service_type, const char * proto, const char * instance_name); -esp_err_t mdns_service_instance_name_set_for_host(const char * service_type, const char * proto, const char *hostname, const char * instance_name); +/** + * @brief Set instance name for service with hostname + * + * @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 instance_name instance name to set + * + * @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_instance_name_set_for_host(const char * service_type, const char * proto, const char * hostname, + const char * instance_name); /** * @brief Set service port @@ -206,7 +301,21 @@ esp_err_t mdns_service_instance_name_set_for_host(const char * service_type, con esp_err_t mdns_service_port_set(const char * service_type, const char * proto, uint16_t port); -esp_err_t mdns_service_port_set_for_host(const char *service_type, const char *proto, const char *hostname, +/** + * @brief Set service port with hostname + * + * @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 port service port + * + * @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_port_set_for_host(const char * service_type, const char * proto, const char * hostname, uint16_t port); /** @@ -225,7 +334,22 @@ esp_err_t mdns_service_port_set_for_host(const char *service_type, const char *p */ esp_err_t mdns_service_txt_set(const char * service_type, const char * proto, mdns_txt_item_t txt[], uint8_t num_items); -esp_err_t mdns_service_txt_set_for_host(const char *service_type, const char *proto, const char *hostname, +/** + * @brief Replace all TXT items for service with hostname + * + * @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 txt array of TXT data (eg. {{"var","val"},{"other","2"}}) + * @param num_items number of items in TXT data + * + * @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_txt_set_for_host(const char * service_type, const char * proto, const char * hostname, mdns_txt_item_t txt[], uint8_t num_items); /** @@ -245,8 +369,23 @@ esp_err_t mdns_service_txt_set_for_host(const char *service_type, const char *pr esp_err_t mdns_service_txt_item_set(const char * service_type, const char * proto, const char * key, const char * value); -esp_err_t mdns_service_txt_item_set_for_host(const char *service_type, const char *proto, const char *hostname, - const char *key, const char *value); +/** + * @brief Set/Add TXT item for service TXT record with hostname + * + * @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 key the key that you want to add/update + * @param value the new value of the key + * + * @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_txt_item_set_for_host(const char * service_type, const char * proto, const char * hostname, + const char * key, const char * value); /** * @brief Remove TXT item for service TXT record @@ -263,8 +402,22 @@ esp_err_t mdns_service_txt_item_set_for_host(const char *service_type, const cha */ esp_err_t mdns_service_txt_item_remove(const char * service_type, const char * proto, const char * key); -esp_err_t mdns_service_txt_item_remove_for_host(const char *service_type, const char *proto, const char *hostname, - const char *key); +/** + * @brief Remove TXT item for service TXT record with hostname + * + * @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 key the key that you want to remove + * + * @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_txt_item_remove_for_host(const char * service_type, const char * proto, const char * hostname, + const char * key); /** * @brief Remove and free all services from mDNS server diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 35aa4e09c6..e72dce5ae8 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -31,7 +31,7 @@ static const char * MDNS_DEFAULT_DOMAIN = "local"; static const char * MDNS_SUB_STR = "_sub"; mdns_server_t * _mdns_server = NULL; -static mdns_host_item_t *_mdns_host_list = NULL; +static mdns_host_item_t * _mdns_host_list = NULL; static mdns_host_item_t _mdns_self_host; static const char *TAG = "MDNS"; @@ -146,7 +146,8 @@ static char * _mdns_mangle_name(char* in) { return ret; } -static bool _mdns_service_match(const mdns_service_t *srv, const char *service, const char *proto, const char *hostname) +static bool _mdns_service_match(const mdns_service_t * srv, const char * service, const char * proto, + const char * hostname) { return !strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && (_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); @@ -160,7 +161,7 @@ static bool _mdns_service_match(const mdns_service_t *srv, const char *service, * * @return the service item if found or NULL on error */ -static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto, const char *hostname) +static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto, const char * hostname) { mdns_srv_item_t * s = _mdns_server->services; while (s) { @@ -172,14 +173,14 @@ static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char return NULL; } -static mdns_host_item_t *mdns_get_host_item(const char *hostname, uint8_t address_type) +static mdns_host_item_t * mdns_get_host_item(const char * hostname) { if (hostname == NULL || strcasecmp(hostname, _mdns_server->hostname) == 0) { return &_mdns_self_host; } - mdns_host_item_t *host = _mdns_host_list; + mdns_host_item_t * host = _mdns_host_list; while (host != NULL) { - if (strcasecmp(host->hostname, hostname) == 0 && host->address.type == address_type) { + if (strcasecmp(host->hostname, hostname) == 0) { return host; } host = host->next; @@ -754,7 +755,7 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns * * @param packet MDNS packet * @param index offset in the packet - * @param server the server + * @param hostname the hostname address to add * @param ip the IP address to add * * @return length of added data: 0 on error or length on success @@ -805,7 +806,7 @@ static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, const * * @param packet MDNS packet * @param index offset in the packet - * @param hostnamek the hostname address to add + * @param hostname the hostname address to add * @param ipv6 the IPv6 address to add * * @return length of added data: 0 on error or length on success @@ -932,11 +933,36 @@ static bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) } #endif +static uint8_t _mdns_append_host_answer(uint8_t * packet, uint16_t * index, mdns_host_item_t * host, + uint8_t address_type, bool flush, bool bye) +{ + mdns_ip_addr_t * addr = host->address_list; + uint8_t num_records = 0; + + while (addr != NULL) { + if (addr->addr.type == address_type) { + if (address_type == ESP_IPADDR_TYPE_V4 && + _mdns_append_a_record(packet, index, host->hostname, addr->addr.u_addr.ip4.addr, flush, bye) <= 0) { + break; + } +#if CONFIG_LWIP_IPV6 + if (address_type == ESP_IPADDR_TYPE_V6 && + _mdns_append_aaaa_record(packet, index, host->hostname, (uint8_t *)addr->addr.u_addr.ip6.addr, flush, + bye) <= 0) { + break; + } +#endif // CONFIG_LWIP_IPV6 + num_records++; + } + addr = addr->next; + } + return num_records; +} + /** * @brief Append answer to packet * * @return number of answers added to the packet - * XXX: create the answers here */ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_answer_t * answer, mdns_if_t tcpip_if) { @@ -982,11 +1008,7 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ } return 1; } else if (answer->host != NULL) { - if (_mdns_append_a_record(packet, index, answer->host->hostname, answer->host->address.u_addr.ip4.addr, answer->flush, answer->bye) <= 0) { - return 0; - } else { - return 1; - } + return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V4, answer->flush, answer->bye); } } #if CONFIG_LWIP_IPV6 @@ -1017,12 +1039,7 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ } return 1; } else if (answer->host != NULL) { - if (_mdns_append_aaaa_record(packet, index, answer->host->hostname, (uint8_t*)answer->host->address.u_addr.ip6.addr, answer->flush, answer->bye) <= 0) { - return 0; - } else { - return 1; - } - + return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V6, answer->flush, answer->bye); } } #endif @@ -1278,7 +1295,8 @@ static void _mdns_dealloc_answer(mdns_out_answer_t ** destination, uint16_t type /** * @brief Allocate new answer and add it to answer list (destination) */ -static bool _mdns_alloc_answer(mdns_out_answer_t ** destination, uint16_t type, mdns_service_t * service, mdns_host_item_t *host, bool flush, bool bye) +static bool _mdns_alloc_answer(mdns_out_answer_t ** destination, uint16_t type, mdns_service_t * service, + mdns_host_item_t * host, bool flush, bool bye) { mdns_out_answer_t * d = *destination; while (d) { @@ -1330,25 +1348,24 @@ static mdns_tx_packet_t * _mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip return packet; } -static bool _mdns_create_answer_from_service(mdns_tx_packet_t *packet, mdns_service_t *service, - mdns_parsed_question_t *question, bool shared, bool send_flush) +static bool _mdns_create_answer_from_service(mdns_tx_packet_t * packet, mdns_service_t * service, + mdns_parsed_question_t * question, bool shared, bool send_flush) { - mdns_host_item_t *host4 = mdns_get_host_item(service->hostname, ESP_IPADDR_TYPE_V4); - mdns_host_item_t *host6 = mdns_get_host_item(service->hostname, ESP_IPADDR_TYPE_V6); + mdns_host_item_t * host = mdns_get_host_item(service->hostname); if (question->type == MDNS_TYPE_PTR || question->type == MDNS_TYPE_ANY) { if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service, NULL, false, false) || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false) || - !_mdns_alloc_answer(shared ? &packet->additional : &packet->answers, MDNS_TYPE_A, service, host4, - send_flush, false) || - !_mdns_alloc_answer(shared ? &packet->additional : &packet->answers, MDNS_TYPE_AAAA, service, host6, + !_mdns_alloc_answer(shared ? &packet->additional : &packet->answers, MDNS_TYPE_A, service, host, send_flush, + false) || + !_mdns_alloc_answer(shared ? &packet->additional : &packet->answers, MDNS_TYPE_AAAA, service, host, send_flush, false)) { return false; } } else if (question->type == MDNS_TYPE_SRV) { if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || - !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_A, service, host4, send_flush, false) || - !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_AAAA, service, host6, send_flush, false)) { + !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_A, service, host, send_flush, false) || + !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_AAAA, service, host, send_flush, false)) { return false; } } else if (question->type == MDNS_TYPE_TXT) { @@ -1364,14 +1381,11 @@ static bool _mdns_create_answer_from_service(mdns_tx_packet_t *packet, mdns_serv return true; } -static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t *packet, const char *hostname, bool send_flush) +static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t * packet, const char * hostname, bool send_flush) { - mdns_host_item_t *host4; - mdns_host_item_t *host6; - host4 = mdns_get_host_item(hostname, ESP_IPADDR_TYPE_V4); - host6 = mdns_get_host_item(hostname, ESP_IPADDR_TYPE_V6); - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host4, send_flush, false) || - !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host6, send_flush, false)) { + mdns_host_item_t * host = mdns_get_host_item(hostname); + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host, send_flush, false) || + !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, send_flush, false)) { return false; } return true; @@ -1379,7 +1393,6 @@ static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t *packet, const ch /** * @brief Create answer packet to questions from parsed packet - * XXX: reply from here */ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) { @@ -1486,9 +1499,10 @@ static bool _mdns_question_exists(mdns_out_question_t * needle, mdns_out_questio return false; } -bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye) { +bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye) +{ if (!_str_null_or_empty(_mdns_server->hostname)) { - mdns_host_item_t *self_host = mdns_get_host_item(_mdns_server->hostname, ESP_IPADDR_TYPE_ANY); + mdns_host_item_t * self_host = mdns_get_host_item(_mdns_server->hostname); if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, self_host, flush, bye)) { return false; } @@ -1496,16 +1510,13 @@ bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool b return false; } } - mdns_host_item_t *host = _mdns_host_list; - while(host != NULL) { - if (host->address.type == ESP_IPADDR_TYPE_V4) { - if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { - return false; - } - } else if (host->address.type == ESP_IPADDR_TYPE_V6) { - if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { - return false; - } + mdns_host_item_t * host = _mdns_host_list; + while (host != NULL) { + if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { + return false; + } + if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { + return false; } host = host->next; } @@ -2048,7 +2059,9 @@ static void _mdns_free_linked_txt(mdns_txt_linked_item_t *txt) * * @return pointer to the service or NULL on error */ -static mdns_service_t * _mdns_create_service(const char * service, const char * proto, const char *hostname, uint16_t port, const char * instance, size_t num_items, mdns_txt_item_t txt[]) +static mdns_service_t * _mdns_create_service(const char * service, const char * proto, const char * hostname, + uint16_t port, const char * instance, size_t num_items, + mdns_txt_item_t txt[]) { mdns_service_t * s = (mdns_service_t *)malloc(sizeof(mdns_service_t)); if (!s) { @@ -2068,7 +2081,6 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * s->txt = new_txt; s->port = port; - assert(hostname != NULL); if (hostname) { s->hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); if (!s->hostname) { @@ -2219,6 +2231,9 @@ static void _mdns_free_service(mdns_service_t * service) free((char *)service->instance); free((char *)service->service); free((char *)service->proto); + if (service->hostname) { + free((char *)service->hostname); + } while (service->txt) { mdns_txt_linked_item_t * s = service->txt; service->txt = service->txt->next; @@ -2439,12 +2454,12 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t * ip, mdns_if_t tcpip_if) } #endif -static bool _hostname_is_ours(const char *hostname) +static bool _hostname_is_ours(const char * hostname) { if (strcasecmp(hostname, _mdns_server->hostname) == 0) { return true; } - mdns_host_item_t *host = _mdns_host_list; + mdns_host_item_t * host = _mdns_host_list; while (host != NULL) { if (strcasecmp(hostname, host->hostname) == 0) { return true; @@ -2454,31 +2469,64 @@ static bool _hostname_is_ours(const char *hostname) return false; } -static bool _mdns_delegate_hostname_add(const char *hostname, const esp_ip_addr_t *address) +static bool _mdns_delegate_hostname_add(const char * hostname, mdns_ip_addr_t * address_list) { if (_hostname_is_ours(hostname)) { return true; } - mdns_host_item_t *host = (mdns_host_item_t *)malloc(sizeof(mdns_host_item_t)); + mdns_host_item_t * host = (mdns_host_item_t *)malloc(sizeof(mdns_host_item_t)); if (host == NULL) { return false; } - host->address = *address; + host->address_list = address_list; host->hostname = hostname; host->next = _mdns_host_list; _mdns_host_list = host; return true; } -static bool _mdns_delegate_hostname_remove(const char *hostname) +static void free_address_list(mdns_ip_addr_t * address_list) { - mdns_srv_item_t *srv = _mdns_server->services; - mdns_srv_item_t *prev_srv = NULL; + while (address_list != NULL) { + mdns_ip_addr_t * next = address_list->next; + free(address_list); + address_list = next; + } +} + +static mdns_ip_addr_t * copy_address_list(const mdns_ip_addr_t * address_list) +{ + mdns_ip_addr_t * head = NULL; + mdns_ip_addr_t * tail = NULL; + while (address_list != NULL) { + mdns_ip_addr_t * addr = (mdns_ip_addr_t *)malloc(sizeof(mdns_ip_addr_t)); + if (addr == NULL) { + free_address_list(head); + return NULL; + } + addr->addr = address_list->addr; + addr->next = NULL; + if (head == NULL) { + head = addr; + tail = addr; + } else { + tail->next = addr; + tail = tail->next; + } + address_list = address_list->next; + } + return head; +} + +static bool _mdns_delegate_hostname_remove(const char * hostname) +{ + mdns_srv_item_t * srv = _mdns_server->services; + mdns_srv_item_t * prev_srv = NULL; while (srv) { if (strcasecmp(srv->service->hostname, hostname) == 0) { - mdns_srv_item_t *to_free = srv; + mdns_srv_item_t * to_free = srv; _mdns_send_bye(&srv, 1, false); _mdns_remove_scheduled_service_packets(srv->service); if (prev_srv == NULL) { @@ -2486,6 +2534,7 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) srv = srv->next; } else { prev_srv->next = srv->next; + srv = srv->next; } _mdns_free_service(to_free->service); free(to_free); @@ -2494,8 +2543,8 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) srv = srv->next; } } - mdns_host_item_t *host = _mdns_host_list; - mdns_host_item_t *prev_host = NULL; + mdns_host_item_t * host = _mdns_host_list; + mdns_host_item_t * prev_host = NULL; while (host != NULL) { if (strcasecmp(hostname, host->hostname) == 0) { if (prev_host == NULL) { @@ -2503,6 +2552,8 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) } else { prev_host->next = host->next; } + printf("Free host %p\n", host); + free_address_list(host->address_list); free((char *)host->hostname); free(host); break; @@ -2542,7 +2593,7 @@ static bool _mdns_name_is_ours(mdns_name_t * name) if (_str_null_or_empty(name->service) && _str_null_or_empty(name->proto)) { if (!_str_null_or_empty(name->host) && !_str_null_or_empty(_mdns_server->hostname) - && _hostname_is_ours(name->host) == 0) + && _hostname_is_ours(name->host)) { return true; } @@ -4232,7 +4283,8 @@ static void _mdns_execute_action(mdns_action_t * action) free(action->data.rx_handle.packet); break; case ACTION_DELEGATE_HOSTNAME_ADD: - _mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, &action->data.delegate_hostname.address); + _mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, + action->data.delegate_hostname.address_list); break; case ACTION_DELEGATE_HOSTNAME_REMOVE: _mdns_delegate_hostname_remove(action->data.delegate_hostname.hostname); @@ -4644,7 +4696,6 @@ esp_err_t mdns_hostname_set(const char * hostname) action->data.hostname_set.hostname = new_hostname; action->data.hostname_set.calling_task = xTaskGetCurrentTaskHandle(); if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { - assert(false); free(new_hostname); free(action); return ESP_ERR_NO_MEM; @@ -4653,12 +4704,12 @@ esp_err_t mdns_hostname_set(const char * hostname) return ERR_OK; } -esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t *address) +esp_err_t mdns_delegate_hostname_add(const char * hostname, const mdns_ip_addr_t * address_list) { if (!_mdns_server) { - return ESP_ERR_INVALID_ARG; + return ESP_ERR_INVALID_STATE; } - if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1) || address_list == NULL) { return ESP_ERR_INVALID_ARG; } char * new_hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); @@ -4674,7 +4725,7 @@ esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t } action->type = ACTION_DELEGATE_HOSTNAME_ADD; action->data.delegate_hostname.hostname = new_hostname; - action->data.delegate_hostname.address = *address; + action->data.delegate_hostname.address_list = copy_address_list(address_list); if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { free(new_hostname); free(action); @@ -4686,7 +4737,7 @@ esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t esp_err_t mdns_delegate_hostname_remove(const char * hostname) { if (!_mdns_server) { - return ESP_ERR_INVALID_ARG; + return ESP_ERR_INVALID_STATE; } if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; @@ -4712,14 +4763,15 @@ esp_err_t mdns_delegate_hostname_remove(const char * hostname) return ERR_OK; } -bool mdns_hostname_exists(const char *hostname) { +bool mdns_hostname_exists(const char * hostname) +{ return _hostname_is_ours(hostname); } esp_err_t mdns_instance_name_set(const char * instance) { if (!_mdns_server) { - return ESP_ERR_INVALID_ARG; + return ESP_ERR_INVALID_STATE; } if (_str_null_or_empty(instance) || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; @@ -4749,9 +4801,8 @@ esp_err_t mdns_instance_name_set(const char * instance) * MDNS SERVICES * */ -esp_err_t mdns_service_add_custom_host(const char *instance, const char *service, const char *proto, - const char *hostname, uint16_t port, - mdns_txt_item_t txt[], size_t num_items) +esp_err_t mdns_service_add_for_host(const char * instance, const char * service, const char * proto, + const char * hostname, 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) { return ESP_ERR_INVALID_ARG; @@ -4799,8 +4850,7 @@ esp_err_t mdns_service_add_custom_host(const char *instance, const char *service size_t start = xTaskGetTickCount(); size_t timeout_ticks = pdMS_TO_TICKS(MDNS_SERVICE_ADD_TIMEOUT_MS); - while (_mdns_get_service_item(service, proto, hostname) == NULL) - { + while (_mdns_get_service_item(service, proto, hostname) == NULL) { uint32_t expired = xTaskGetTickCount() - start; if (expired >= timeout_ticks) { return ESP_FAIL; // Timeout @@ -4811,19 +4861,21 @@ esp_err_t mdns_service_add_custom_host(const char *instance, const char *service return ESP_OK; } -esp_err_t mdns_service_add(const char *instance, const char *service, const char *proto, uint16_t port, +esp_err_t mdns_service_add(const char * instance, const char * service, const char * proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - assert(_mdns_server->hostname != NULL); - return mdns_service_add_custom_host(instance, service, proto, _mdns_server->hostname, port, txt, num_items); + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + return mdns_service_add_for_host(instance, service, proto, _mdns_server->hostname, port, txt, num_items); } -bool mdns_service_exists(const char *service_type, const char *proto, const char *hostname) +bool mdns_service_exists(const char * service_type, const char * proto, const char * hostname) { return _mdns_get_service_item(service_type, proto, hostname) != NULL; } -esp_err_t mdns_service_port_set_for_host(const char *service, const char *proto, const char *hostname, uint16_t port) +esp_err_t mdns_service_port_set_for_host(const char * service, const char * proto, const char * hostname, uint16_t port) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { return ESP_ERR_INVALID_ARG; @@ -4848,11 +4900,15 @@ esp_err_t mdns_service_port_set_for_host(const char *service, const char *proto, return ESP_OK; } -esp_err_t mdns_service_port_set(const char *service, const char *proto, uint16_t port) { +esp_err_t mdns_service_port_set(const char * service, const char * proto, uint16_t port) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } return mdns_service_port_set_for_host(service, proto, _mdns_server->hostname, port); } -esp_err_t mdns_service_txt_set_for_host(const char *service, const char *proto, const char *hostname, +esp_err_t mdns_service_txt_set_for_host(const char * service, const char * proto, const char * hostname, mdns_txt_item_t txt[], uint8_t num_items) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || (num_items && txt == NULL)) { @@ -4889,12 +4945,16 @@ esp_err_t mdns_service_txt_set_for_host(const char *service, const char *proto, return ESP_OK; } -esp_err_t mdns_service_txt_set(const char *service, const char *proto, mdns_txt_item_t txt[], uint8_t num_items) +esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_txt_item_t txt[], uint8_t num_items) { + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } return mdns_service_txt_set_for_host(service, proto, _mdns_server->hostname, txt, num_items); } -esp_err_t mdns_service_txt_item_set_for_host(const char * service, const char * proto, const char *hostname, const char * key, const char * value) +esp_err_t mdns_service_txt_item_set_for_host(const char * service, const char * proto, const char * hostname, + const char * key, const char * value) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(key) || !value) { return ESP_ERR_INVALID_ARG; @@ -4931,12 +4991,16 @@ esp_err_t mdns_service_txt_item_set_for_host(const char * service, const char * return ESP_OK; } -esp_err_t mdns_service_txt_item_set(const char *service, const char *proto, const char *key, const char *value) +esp_err_t mdns_service_txt_item_set(const char * service, const char * proto, const char * key, const char * value) { + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } return mdns_service_txt_item_set_for_host(service, proto, _mdns_server->hostname, key, value); } -esp_err_t mdns_service_txt_item_remove_for_host(const char * service, const char * proto, const char *hostname, const char * key) +esp_err_t mdns_service_txt_item_remove_for_host(const char * service, const char * proto, const char * hostname, + const char * key) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(key)) { return ESP_ERR_INVALID_ARG; @@ -4966,13 +5030,16 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char * service, const char return ESP_OK; } -esp_err_t mdns_service_txt_item_remove(const char *service, const char *proto, const char *key) +esp_err_t mdns_service_txt_item_remove(const char * service, const char * proto, const char * key) { + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } return mdns_service_txt_item_remove_for_host(service, proto, _mdns_server->hostname, key); } -esp_err_t mdns_service_instance_name_set_for_host(const char *service, const char *proto, const char *hostname, - const char *instance) +esp_err_t mdns_service_instance_name_set_for_host(const char * service, const char * proto, const char * hostname, + const char * instance) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; @@ -5006,12 +5073,15 @@ esp_err_t mdns_service_instance_name_set_for_host(const char *service, const cha 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) { + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } return mdns_service_instance_name_set_for_host(service, proto, _mdns_server->hostname, instance); } -esp_err_t mdns_service_remove_for_host(const char * service, const char * proto, const char *hostname) +esp_err_t mdns_service_remove_for_host(const char * service, const char * proto, const char * hostname) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; @@ -5035,8 +5105,11 @@ esp_err_t mdns_service_remove_for_host(const char * service, const char * proto, return ESP_OK; } -esp_err_t mdns_service_remove(const char *service_type, const char *proto) +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(service_type, proto, _mdns_server->hostname); } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 6acdf92833..4b8f8806c7 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -19,8 +19,9 @@ #include "esp_timer.h" #include "esp_netif_ip_addr.h" #include "freertos/FreeRTOS.h" +#include "mdns.h" -#define MDNS_ENABLE_DEBUG +//#define MDNS_ENABLE_DEBUG #ifdef MDNS_ENABLE_DEBUG #define _mdns_dbg_printf(...) printf(__VA_ARGS__) @@ -309,7 +310,7 @@ typedef struct mdns_out_question_s { typedef struct mdns_host_item_t { const char * hostname; - esp_ip_addr_t address; + mdns_ip_addr_t *address_list; struct mdns_host_item_t *next; } mdns_host_item_t; @@ -441,7 +442,7 @@ typedef struct { } rx_handle; struct { const char * hostname; - esp_ip_addr_t address; + mdns_ip_addr_t *address_list; } delegate_hostname; } data; } mdns_action_t; diff --git a/components/mdns/test/test_mdns.c b/components/mdns/test/test_mdns.c index 9dc9fe090a..abdad0e63e 100644 --- a/components/mdns/test/test_mdns.c +++ b/components/mdns/test/test_mdns.c @@ -4,6 +4,7 @@ #define MDNS_HOSTNAME "test-hostname" +#define MDNS_DELEGATE_HOSTNAME "delegate-hostname" #define MDNS_INSTANCE "test-instance" #define MDNS_SERVICE_NAME "_http" #define MDNS_SERVICE_PROTO "_tcp" @@ -42,6 +43,10 @@ TEST_CASE("mdns api return expected err-code and do not leak memory", "[mdns][le { mdns_txt_item_t serviceTxtData[CONFIG_MDNS_MAX_SERVICES] = { {NULL, NULL}, }; + mdns_ip_addr_t addr; + addr.addr.type = ESP_IPADDR_TYPE_V4; + addr.addr.u_addr.ip4.addr = esp_ip4addr_aton("127.0.0.1"); + addr.next = NULL; for (int i=0; itcpip_if], ip_protocol_str[r->ip_protocol]); - if (r->instance_name) { + if(r->instance_name){ printf(" PTR : %s\n", r->instance_name); } - if (r->hostname) { + if(r->hostname){ printf(" SRV : %s.local:%u\n", r->hostname, r->port); } - if (r->txt_count) { + if(r->txt_count){ printf(" TXT : [%u] ", r->txt_count); - for (t = 0; t < r->txt_count; t++) { - printf("%s=%s; ", r->txt[t].key, r->txt[t].value ? r->txt[t].value : "NULL"); + for(t=0; ttxt_count; t++){ + 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 == ESP_IPADDR_TYPE_V6) { + while(a){ + if(a->addr.type == ESP_IPADDR_TYPE_V6){ printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); } else { printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); @@ -111,17 +110,17 @@ static void mdns_print_results(mdns_result_t *results) } -static void query_mdns_service(const char *service_name, const char *proto) +static void query_mdns_service(const char * service_name, const char * proto) { ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); - mdns_result_t *results = NULL; + mdns_result_t * results = NULL; esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); - if (err) { + if(err){ ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); return; } - if (!results) { + if(!results){ ESP_LOGW(TAG, "No results found!"); return; } @@ -130,7 +129,7 @@ static void query_mdns_service(const char *service_name, const char *proto) mdns_query_results_free(results); } -static void query_mdns_host(const char *host_name) +static void query_mdns_host(const char * host_name) { ESP_LOGI(TAG, "Query A: %s.local", host_name); @@ -138,8 +137,8 @@ static void query_mdns_host(const char *host_name) addr.addr = 0; esp_err_t err = mdns_query_a(host_name, 2000, &addr); - if (err) { - if (err == ESP_ERR_NOT_FOUND) { + if(err){ + if(err == ESP_ERR_NOT_FOUND){ ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err)); return; } @@ -193,7 +192,7 @@ static void mdns_example_task(void *pvParameters) check_button(); vTaskDelay(50 / portTICK_PERIOD_MS); if (pdTICKS_TO_MS(xTaskGetTickCount()) >= 15 * 1000 && ! removed) { - printf("Remove device\n"); + ESP_LOGI(TAG, "Remove delegate device\n"); ESP_ERROR_CHECK(mdns_delegate_hostname_remove("test-device")); removed = true; } @@ -221,7 +220,7 @@ void app_main(void) /** Generate host name based on sdkconfig, optionally adding a portion of MAC address to it. * @return host name string allocated from the heap */ -static char *generate_hostname(void) +static char* generate_hostname(void) { #ifndef CONFIG_MDNS_ADD_MAC_TO_HOSTNAME return strdup(CONFIG_MDNS_HOSTNAME); @@ -241,7 +240,7 @@ static char *generate_hostname(void) * @brief Executes gethostbyname and displays list of resolved addresses. * Note: This function is used only to test advertised mdns hostnames resolution */ -static void query_mdns_host_with_gethostbyname(char *host) +static void query_mdns_host_with_gethostbyname(char * host) { struct hostent *res = gethostbyname(host); if (res) { @@ -257,10 +256,10 @@ static void query_mdns_host_with_gethostbyname(char *host) * @brief Executes getaddrinfo and displays list of resolved addresses. * Note: This function is used only to test advertised mdns hostnames resolution */ -static void query_mdns_host_with_getaddrinfo(char *host) +static void query_mdns_host_with_getaddrinfo(char * host) { struct addrinfo hints; - struct addrinfo *res; + struct addrinfo * res; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -269,8 +268,8 @@ static void query_mdns_host_with_getaddrinfo(char *host) if (!getaddrinfo(host, NULL, &hints, &res)) { while (res) { ESP_LOGI(TAG, "getaddrinfo: %s resolved to: %s", host, - res->ai_family == AF_INET ? - inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr) : + res->ai_family == AF_INET? + inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr): inet_ntoa(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr)); res = res->ai_next; }