mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-18 13:02:21 +02:00
mdns: fix mdns probe/reply behavior
* send correct hostnames when probing. * add test for mdns host delegation. * Original commit: espressif/esp-idf@d2a5d25984
This commit is contained in:
committed by
suren-gabrielyan-espressif
parent
4049b3b5ed
commit
418fb60dd9
@ -45,6 +45,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char *
|
|||||||
static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol);
|
static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol);
|
||||||
static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol);
|
static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol);
|
||||||
static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol);
|
static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol);
|
||||||
|
static bool _mdns_append_host_list_in_services(mdns_out_answer_t ** destination, mdns_srv_item_t * services[], size_t services_len, bool flush, bool bye);
|
||||||
static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye);
|
static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1499,26 +1500,43 @@ static bool _mdns_question_exists(mdns_out_question_t * needle, mdns_out_questio
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye)
|
static bool _mdns_append_host(mdns_out_answer_t ** destination, mdns_host_item_t * host, 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);
|
|
||||||
if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, self_host, flush, bye)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, self_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)) {
|
if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) {
|
if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _mdns_append_host_list_in_services(mdns_out_answer_t ** destination, mdns_srv_item_t * services[],
|
||||||
|
size_t services_len, bool flush, bool bye)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < services_len; i++) {
|
||||||
|
mdns_host_item_t *host = mdns_get_host_item(services[i]->service->hostname);
|
||||||
|
if (!_mdns_append_host(destination, host, flush, bye)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static 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);
|
||||||
|
if (!_mdns_append_host(destination, self_host, flush, bye)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mdns_host_item_t * host = _mdns_host_list;
|
||||||
|
while (host != NULL) {
|
||||||
host = host->next;
|
host = host->next;
|
||||||
|
if (!_mdns_append_host(destination, host, flush, bye)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1563,6 +1581,7 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (include_ip) {
|
if (include_ip) {
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t));
|
mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t));
|
||||||
if (!q) {
|
if (!q) {
|
||||||
HOOK_MALLOC_FAILED;
|
HOOK_MALLOC_FAILED;
|
||||||
@ -1572,7 +1591,7 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_
|
|||||||
q->next = NULL;
|
q->next = NULL;
|
||||||
q->unicast = first;
|
q->unicast = first;
|
||||||
q->type = MDNS_TYPE_ANY;
|
q->type = MDNS_TYPE_ANY;
|
||||||
q->host = _mdns_server->hostname;
|
q->host = services[i]->service->hostname;
|
||||||
q->service = NULL;
|
q->service = NULL;
|
||||||
q->proto = NULL;
|
q->proto = NULL;
|
||||||
q->domain = MDNS_DEFAULT_DOMAIN;
|
q->domain = MDNS_DEFAULT_DOMAIN;
|
||||||
@ -1582,8 +1601,9 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_
|
|||||||
} else {
|
} else {
|
||||||
queueToEnd(mdns_out_question_t, packet->questions, q);
|
queueToEnd(mdns_out_question_t, packet->questions, q);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!_mdns_append_host_list(&packet->servers, false, false)) {
|
if (!_mdns_append_host_list_in_services(&packet->servers, services, len, false, false)) {
|
||||||
_mdns_free_tx_packet(packet);
|
_mdns_free_tx_packet(packet);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1614,7 +1634,7 @@ static mdns_tx_packet_t * _mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (include_ip) {
|
if (include_ip) {
|
||||||
if (!_mdns_append_host_list(&packet->servers, true, false)) {
|
if (!_mdns_append_host_list_in_services(&packet->servers, services, len, true, false)) {
|
||||||
_mdns_free_tx_packet(packet);
|
_mdns_free_tx_packet(packet);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1675,7 +1695,7 @@ static void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (include_ip) {
|
if (include_ip) {
|
||||||
_mdns_append_host_list(&packet->answers, true, true);
|
_mdns_append_host_list_in_services(&packet->answers, services, len, true, true);
|
||||||
}
|
}
|
||||||
_mdns_dispatch_tx_packet(packet);
|
_mdns_dispatch_tx_packet(packet);
|
||||||
_mdns_free_tx_packet(packet);
|
_mdns_free_tx_packet(packet);
|
||||||
@ -1841,7 +1861,7 @@ static void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco
|
|||||||
if (include_ip) {
|
if (include_ip) {
|
||||||
_mdns_dealloc_answer(&p->additional, MDNS_TYPE_A, NULL);
|
_mdns_dealloc_answer(&p->additional, MDNS_TYPE_A, NULL);
|
||||||
_mdns_dealloc_answer(&p->additional, MDNS_TYPE_AAAA, NULL);
|
_mdns_dealloc_answer(&p->additional, MDNS_TYPE_AAAA, NULL);
|
||||||
_mdns_append_host_list(&p->answers, true, false);
|
_mdns_append_host_list_in_services(&p->answers, services, len, true, false);
|
||||||
}
|
}
|
||||||
_pcb->state = PCB_ANNOUNCE_1;
|
_pcb->state = PCB_ANNOUNCE_1;
|
||||||
}
|
}
|
||||||
@ -2231,9 +2251,7 @@ static void _mdns_free_service(mdns_service_t * service)
|
|||||||
free((char *)service->instance);
|
free((char *)service->instance);
|
||||||
free((char *)service->service);
|
free((char *)service->service);
|
||||||
free((char *)service->proto);
|
free((char *)service->proto);
|
||||||
if (service->hostname) {
|
|
||||||
free((char *)service->hostname);
|
free((char *)service->hostname);
|
||||||
}
|
|
||||||
while (service->txt) {
|
while (service->txt) {
|
||||||
mdns_txt_linked_item_t * s = service->txt;
|
mdns_txt_linked_item_t * s = service->txt;
|
||||||
service->txt = service->txt->next;
|
service->txt = service->txt->next;
|
||||||
@ -2552,7 +2570,6 @@ static bool _mdns_delegate_hostname_remove(const char * hostname)
|
|||||||
} else {
|
} else {
|
||||||
prev_host->next = host->next;
|
prev_host->next = host->next;
|
||||||
}
|
}
|
||||||
printf("Free host %p\n", host);
|
|
||||||
free_address_list(host->address_list);
|
free_address_list(host->address_list);
|
||||||
free((char *)host->hostname);
|
free((char *)host->hostname);
|
||||||
free(host);
|
free(host);
|
||||||
|
@ -5,6 +5,7 @@ Shows how to use mDNS to advertise lookup services and hosts
|
|||||||
## Example workflow
|
## Example workflow
|
||||||
|
|
||||||
- mDNS is initialized with host name and instance name defined through the project configuration and `_http._tcp` service is added to be advertised
|
- mDNS is initialized with host name and instance name defined through the project configuration and `_http._tcp` service is added to be advertised
|
||||||
|
- A delegated host `esp32-delegated._local` is added and another `_http._tcp` service is added for this host.
|
||||||
- WiFi STA is started and trying to connect to the access point defined through the project configuration
|
- WiFi STA is started and trying to connect to the access point defined through the project configuration
|
||||||
- The system event handler is used to pass the network events to mDNS so the service is aware when the interface comes up or down
|
- The system event handler is used to pass the network events to mDNS so the service is aware when the interface comes up or down
|
||||||
- GPIO0 (BOOT Button) is initialized as pulled-up input that can be monitored for button press
|
- GPIO0 (BOOT Button) is initialized as pulled-up input that can be monitored for button press
|
||||||
|
@ -12,6 +12,12 @@ menu "Example Configuration"
|
|||||||
help
|
help
|
||||||
mDNS Instance Name for example to use
|
mDNS Instance Name for example to use
|
||||||
|
|
||||||
|
config MDNS_PUBLISH_DELEGATE_HOST
|
||||||
|
bool "Publish a delegated host"
|
||||||
|
help
|
||||||
|
Enable publishing a delegated host other than ESP32.
|
||||||
|
The example will also add a mock service for this host.
|
||||||
|
|
||||||
config MDNS_RESOLVE_TEST_SERVICES
|
config MDNS_RESOLVE_TEST_SERVICES
|
||||||
bool "Resolve test services"
|
bool "Resolve test services"
|
||||||
default n
|
default n
|
||||||
|
@ -34,6 +34,9 @@ static void query_mdns_host_with_getaddrinfo(char * host);
|
|||||||
static void initialise_mdns(void)
|
static void initialise_mdns(void)
|
||||||
{
|
{
|
||||||
char *hostname = generate_hostname();
|
char *hostname = generate_hostname();
|
||||||
|
char delegated_hostname[64];
|
||||||
|
|
||||||
|
snprintf(delegated_hostname, sizeof(delegated_hostname), "%s-delegated", hostname);
|
||||||
//initialize mDNS
|
//initialize mDNS
|
||||||
ESP_ERROR_CHECK( mdns_init() );
|
ESP_ERROR_CHECK( mdns_init() );
|
||||||
//set mDNS hostname (required if you want to advertise services)
|
//set mDNS hostname (required if you want to advertise services)
|
||||||
@ -51,19 +54,23 @@ static void initialise_mdns(void)
|
|||||||
|
|
||||||
//initialize service
|
//initialize service
|
||||||
ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) );
|
ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) );
|
||||||
|
|
||||||
|
#if CONFIG_MDNS_PUBLISH_DELEGATE_HOST
|
||||||
mdns_ip_addr_t addr4, addr6;
|
mdns_ip_addr_t addr4, addr6;
|
||||||
ip4_addr_t ip4_addr;
|
ip4_addr_t ip4_addr;
|
||||||
ip6_addr_t ip6_addr;
|
ip6_addr_t ip6_addr;
|
||||||
ip4addr_aton("10.0.0.1", &ip4_addr);
|
ip4addr_aton("10.0.0.1", &ip4_addr); // mock address
|
||||||
addr4.addr.u_addr.ip4.addr = ip4_addr.addr;
|
addr4.addr.u_addr.ip4.addr = ip4_addr.addr;
|
||||||
addr4.addr.type = ESP_IPADDR_TYPE_V4;
|
addr4.addr.type = ESP_IPADDR_TYPE_V4;
|
||||||
addr4.next = &addr6;
|
addr4.next = &addr6;
|
||||||
ip6addr_aton("fd11:22::1", &ip6_addr);
|
ip6addr_aton("fd11:22::1", &ip6_addr); // mock address
|
||||||
memcpy(addr6.addr.u_addr.ip6.addr, ip6_addr.addr, sizeof(ip6_addr.addr));
|
memcpy(addr6.addr.u_addr.ip6.addr, ip6_addr.addr, sizeof(ip6_addr.addr));
|
||||||
addr6.addr.type = ESP_IPADDR_TYPE_V6;
|
addr6.addr.type = ESP_IPADDR_TYPE_V6;
|
||||||
addr6.next = NULL;
|
addr6.next = NULL;
|
||||||
ESP_ERROR_CHECK( mdns_delegate_hostname_add("test-device", &addr4) );
|
ESP_ERROR_CHECK( mdns_delegate_hostname_add(delegated_hostname, &addr4) );
|
||||||
ESP_ERROR_CHECK( mdns_service_add_for_host("test0", "_http", "_tcp", "test-device", 1234, serviceTxtData, 3) );
|
ESP_ERROR_CHECK( mdns_service_add_for_host("test0", "_http", "_tcp", delegated_hostname, 1234, serviceTxtData, 3) );
|
||||||
|
#endif // CONFIG_MDNS_PUBLISH_DELEGATE_HOST
|
||||||
|
|
||||||
//add another TXT item
|
//add another TXT item
|
||||||
ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") );
|
ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") );
|
||||||
//change TXT item value
|
//change TXT item value
|
||||||
@ -186,16 +193,10 @@ static void mdns_example_task(void *pvParameters)
|
|||||||
query_mdns_host_with_gethostbyname("tinytester-lwip.local");
|
query_mdns_host_with_gethostbyname("tinytester-lwip.local");
|
||||||
query_mdns_host_with_getaddrinfo("tinytester-lwip.local");
|
query_mdns_host_with_getaddrinfo("tinytester-lwip.local");
|
||||||
#endif
|
#endif
|
||||||
bool removed = false;
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
check_button();
|
check_button();
|
||||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||||
if (pdTICKS_TO_MS(xTaskGetTickCount()) >= 15 * 1000 && ! removed) {
|
|
||||||
ESP_LOGI(TAG, "Remove delegate device\n");
|
|
||||||
ESP_ERROR_CHECK(mdns_delegate_hostname_remove("test-device"));
|
|
||||||
removed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ from tiny_test_fw import DUT
|
|||||||
|
|
||||||
stop_mdns_server = Event()
|
stop_mdns_server = Event()
|
||||||
esp_answered = Event()
|
esp_answered = Event()
|
||||||
|
esp_delegated_answered = Event()
|
||||||
|
|
||||||
|
|
||||||
def get_dns_query_for_esp(esp_host):
|
def get_dns_query_for_esp(esp_host):
|
||||||
@ -68,6 +69,8 @@ def mdns_server(esp_host):
|
|||||||
if not esp_answered.is_set():
|
if not esp_answered.is_set():
|
||||||
sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT))
|
sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT))
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
sock.sendto(get_dns_query_for_esp(esp_host + '-delegated'), (MCAST_GRP,UDP_PORT))
|
||||||
|
time.sleep(0.2)
|
||||||
data, addr = sock.recvfrom(1024)
|
data, addr = sock.recvfrom(1024)
|
||||||
dns = dpkt.dns.DNS(data)
|
dns = dpkt.dns.DNS(data)
|
||||||
if len(dns.qd) > 0 and dns.qd[0].type == dpkt.dns.DNS_A:
|
if len(dns.qd) > 0 and dns.qd[0].type == dpkt.dns.DNS_A:
|
||||||
@ -81,6 +84,9 @@ def mdns_server(esp_host):
|
|||||||
if dns.an[0].name == esp_host + u'.local':
|
if dns.an[0].name == esp_host + u'.local':
|
||||||
print('Received answer to esp32-mdns query: {}'.format(dns.__repr__()))
|
print('Received answer to esp32-mdns query: {}'.format(dns.__repr__()))
|
||||||
esp_answered.set()
|
esp_answered.set()
|
||||||
|
if dns.an[0].name == esp_host + u'-delegated.local':
|
||||||
|
print('Received answer to esp32-mdns-delegate query: {}'.format(dns.__repr__()))
|
||||||
|
esp_delegated_answered.set()
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
break
|
break
|
||||||
except dpkt.UnpackError:
|
except dpkt.UnpackError:
|
||||||
@ -120,6 +126,8 @@ def test_examples_protocol_mdns(env, extra_data):
|
|||||||
# 3. check the mdns name is accessible
|
# 3. check the mdns name is accessible
|
||||||
if not esp_answered.wait(timeout=30):
|
if not esp_answered.wait(timeout=30):
|
||||||
raise ValueError('Test has failed: did not receive mdns answer within timeout')
|
raise ValueError('Test has failed: did not receive mdns answer within timeout')
|
||||||
|
if not esp_delegated_answered.wait(timeout=30):
|
||||||
|
raise ValueError('Test has failed: did not receive mdns answer for delegated host within timeout')
|
||||||
# 4. check DUT output if mdns advertized host is resolved
|
# 4. check DUT output if mdns advertized host is resolved
|
||||||
dut1.expect(re.compile(r'mdns-test: Query A: tinytester.local resolved to: 127.0.0.1'), timeout=30)
|
dut1.expect(re.compile(r'mdns-test: Query A: tinytester.local resolved to: 127.0.0.1'), timeout=30)
|
||||||
dut1.expect(re.compile(r'mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1'), timeout=30)
|
dut1.expect(re.compile(r'mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1'), timeout=30)
|
||||||
|
Reference in New Issue
Block a user