Sfoglia il codice sorgente

mdns: Add host test using linux target

David Cermak 4 anni fa
parent
commit
fc7e2d9e90
34 ha cambiato i file con 1174 aggiunte e 7 eliminazioni
  1. 22 7
      components/mdns/CMakeLists.txt
  2. 9 0
      components/mdns/Kconfig
  3. 5 0
      components/mdns/component.mk
  4. 5 0
      components/mdns/host_test/CMakeLists.txt
  5. 25 0
      components/mdns/host_test/README.md
  6. 3 0
      components/mdns/host_test/components/esp_event_mock/CMakeLists.txt
  7. 29 0
      components/mdns/host_test/components/esp_event_mock/esp_event_mock.c
  8. 32 0
      components/mdns/host_test/components/esp_event_mock/include/esp_event.h
  9. 21 0
      components/mdns/host_test/components/esp_event_mock/include/esp_event_base.h
  10. 3 0
      components/mdns/host_test/components/esp_netif_linux/CMakeLists.txt
  11. 9 0
      components/mdns/host_test/components/esp_netif_linux/Kconfig
  12. 163 0
      components/mdns/host_test/components/esp_netif_linux/esp_netif_linux.c
  13. 15 0
      components/mdns/host_test/components/esp_netif_linux/include/esp_wifi_types.h
  14. 3 0
      components/mdns/host_test/components/esp_system_protocols_linux/CMakeLists.txt
  15. 35 0
      components/mdns/host_test/components/esp_system_protocols_linux/esp_log_impl.c
  16. 16 0
      components/mdns/host_test/components/esp_system_protocols_linux/include/bsd_strings.h
  17. 16 0
      components/mdns/host_test/components/esp_system_protocols_linux/include/machine/endian.h
  18. 68 0
      components/mdns/host_test/components/esp_system_protocols_linux/strlcat.c
  19. 5 0
      components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt
  20. 47 0
      components/mdns/host_test/components/esp_timer_linux/esp_timer_linux.c
  21. 41 0
      components/mdns/host_test/components/esp_timer_linux/include/esp_timer.h
  22. 38 0
      components/mdns/host_test/components/esp_timer_linux/timer_task.cpp
  23. 61 0
      components/mdns/host_test/components/esp_timer_linux/timer_task.hpp
  24. 9 0
      components/mdns/host_test/components/freertos_linux/CMakeLists.txt
  25. 7 0
      components/mdns/host_test/components/freertos_linux/Kconfig
  26. 192 0
      components/mdns/host_test/components/freertos_linux/freertos_linux.c
  27. 20 0
      components/mdns/host_test/components/freertos_linux/include/esp_task.h
  28. 46 0
      components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h
  29. 58 0
      components/mdns/host_test/components/freertos_linux/include/freertos/task.h
  30. 51 0
      components/mdns/host_test/components/freertos_linux/queue_unique_ptr.cpp
  31. 55 0
      components/mdns/host_test/components/freertos_linux/queue_unique_ptr.hpp
  32. 4 0
      components/mdns/host_test/main/CMakeLists.txt
  33. 59 0
      components/mdns/host_test/main/main.c
  34. 2 0
      components/mdns/private_include/mdns_private.h

+ 22 - 7
components/mdns/CMakeLists.txt

@@ -1,7 +1,22 @@
-idf_component_register(SRCS "mdns.c"
-                            "mdns_console.c"
-                            "mdns_networking.c"
-                    INCLUDE_DIRS "include"
-                    PRIV_INCLUDE_DIRS "private_include"
-                    REQUIRES lwip console esp_netif
-                    PRIV_REQUIRES esp_timer)
+if(CONFIG_MDNS_NETWORKING_SOCKET)
+    set(MDNS_NETWORKING "mdns_networking_socket.c")
+else()
+    set(MDNS_NETWORKING "mdns_networking_lwip.c")
+endif()
+
+idf_build_get_property(target IDF_TARGET)
+if(${target} STREQUAL "linux")
+    set(dependencies esp_system_protocols_linux)
+    set(srcs "mdns.c" ${MDNS_NETWORKING})
+else()
+    set(dependencies lwip console esp_netif)
+    set(private_dependencies esp_timer)
+    set(srcs "mdns.c" ${MDNS_NETWORKING} "mdns_console.c")
+endif()
+
+idf_component_register(
+        SRCS ${srcs}
+        INCLUDE_DIRS "include"
+        PRIV_INCLUDE_DIRS "private_include"
+        REQUIRES ${dependencies}
+        PRIV_REQUIRES ${private_dependencies})

+ 9 - 0
components/mdns/Kconfig

@@ -75,4 +75,13 @@ menu "mDNS"
             Configures period of mDNS timer, which periodically transmits packets
             and schedules mDNS searches.
 
+    config MDNS_NETWORKING_SOCKET
+        bool "Use BSD sockets for mdns networking"
+        default n
+        help
+            Enables optional mdns networking implementation using BSD sockets
+            in UDP multicast mode.
+            This option creates a new thread to serve receiving packets (TODO).
+            This option uses additional N sockets, where N is number of interfaces.
+
 endmenu

+ 5 - 0
components/mdns/component.mk

@@ -1,2 +1,7 @@
+ifdef CONFIG_MDNS_NETWORKING_SOCKET
+COMPONENT_OBJEXCLUDE := mdns_networking_lwip.o
+else
+COMPONENT_OBJEXCLUDE := mdns_networking_socket.o
+endif
 COMPONENT_ADD_INCLUDEDIRS := include
 COMPONENT_PRIV_INCLUDEDIRS := private_include

+ 5 - 0
components/mdns/host_test/CMakeLists.txt

@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+set(COMPONENTS main)
+project(mdns_host)

+ 25 - 0
components/mdns/host_test/README.md

@@ -0,0 +1,25 @@
+# Setup dummy network interfaces
+```
+sudo ip link add eth2 type dummy
+sudo ip addr add 192.168.1.200/24 dev eth2
+sudo ip link set eth2 up
+sudo ifconfig eth2 multicast
+```
+
+# Dig on a specified interface
+
+```
+dig +short -b 192.168.1.200 -p 5353 @224.0.0.251 myesp.local
+```
+
+# Run avahi to browse services
+
+Avahi needs the netif to have the "multicast" flag set
+
+```bash
+david@david-comp:~/esp/idf (feature/mdns_networking_socket)$ avahi-browse -a -r -p
++;eth2;IPv6;myesp-service2;Web Site;local
++;eth2;IPv4;myesp-service2;Web Site;local
+=;eth2;IPv6;myesp-service2;Web Site;local;myesp.local;192.168.1.200;80;"board=esp32" "u=user" "p=password"
+=;eth2;IPv4;myesp-service2;Web Site;local;myesp.local;192.168.1.200;80;"board=esp32" "u=user" "p=password"
+```

+ 3 - 0
components/mdns/host_test/components/esp_event_mock/CMakeLists.txt

@@ -0,0 +1,3 @@
+idf_component_register(SRCS esp_event_mock.c
+                       INCLUDE_DIRS include
+                       REQUIRES esp_system_protocols_linux)

+ 29 - 0
components/mdns/host_test/components/esp_event_mock/esp_event_mock.c

@@ -0,0 +1,29 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "esp_err.h"
+#include "esp_event.h"
+
+const char * WIFI_EVENT = "WIFI_EVENT";
+const char * IP_EVENT = "IP_EVENT";
+
+esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id, void* event_handler, void* event_handler_arg)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler)
+{
+    return ESP_OK;
+}

+ 32 - 0
components/mdns/host_test/components/esp_event_mock/include/esp_event.h

@@ -0,0 +1,32 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include "stdbool.h"
+#include "esp_err.h"
+#include "esp_event_base.h"
+#include "bsd_strings.h"
+
+#define ESP_EVENT_DECLARE_BASE(x)
+#define ESP_EVENT_ANY_ID       (-1)
+
+typedef void * esp_event_base_t;
+typedef void * system_event_t;
+
+const char* WIFI_EVENT;
+const char* IP_EVENT;
+
+esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id, void* event_handler, void* event_handler_arg);
+
+esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler);

+ 21 - 0
components/mdns/host_test/components/esp_event_mock/include/esp_event_base.h

@@ -0,0 +1,21 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+typedef enum {
+    WIFI_EVENT_STA_CONNECTED,            /**< ESP32 station connected to AP */
+    WIFI_EVENT_STA_DISCONNECTED,         /**< ESP32 station disconnected from AP */
+    WIFI_EVENT_AP_START,                 /**< ESP32 soft-AP start */
+    WIFI_EVENT_AP_STOP,                  /**< ESP32 soft-AP stop */
+} mdns_used_event_t;

+ 3 - 0
components/mdns/host_test/components/esp_netif_linux/CMakeLists.txt

@@ -0,0 +1,3 @@
+idf_component_register(SRCS esp_netif_linux.c
+                       INCLUDE_DIRS include
+                       REQUIRES esp_system_protocols_linux)

+ 9 - 0
components/mdns/host_test/components/esp_netif_linux/Kconfig

@@ -0,0 +1,9 @@
+menu "LWIP-MOCK-CONFIG"
+
+    config LWIP_IPV6
+        bool "Enable IPv6"
+        default true
+        help
+            Enable/disable IPv6
+
+endmenu

+ 163 - 0
components/mdns/host_test/components/esp_netif_linux/esp_netif_linux.c

@@ -0,0 +1,163 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include<stdio.h>
+#include <stdlib.h>
+
+#include "esp_netif.h"
+#include "esp_err.h"
+#include <string.h>	//strlen
+#include <sys/socket.h>
+#include <arpa/inet.h>	//inet_addr
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+#include "esp_netif_types.h"
+
+#define MAX_NETIFS  4
+
+static esp_netif_t* s_netif_list[MAX_NETIFS] = { 0 };
+
+struct esp_netif_obj
+{
+    const char *if_key;
+    const char *if_desc;
+};
+
+esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key)
+{
+    for (int i=0; i<MAX_NETIFS; ++i) {
+        if (s_netif_list[i] && strcmp(s_netif_list[i]->if_key, if_key) == 0) {
+            return s_netif_list[i];
+        }
+    }
+    return NULL;
+}
+
+esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
+{
+    if (esp_netif == NULL) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    struct ifaddrs *addrs, *tmp;
+    getifaddrs(&addrs);
+    tmp = addrs;
+
+    while (tmp) {
+        if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET) {
+            char addr[20];
+            struct sockaddr_in *pAddr = (struct sockaddr_in *) tmp->ifa_addr;
+            inet_ntop(AF_INET, &pAddr->sin_addr, addr, sizeof(addr) );
+            if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) {
+                printf("AF_INET: %s: %s\n", tmp->ifa_name, addr);
+                memcpy(&ip_info->ip.addr, &pAddr->sin_addr, 4);
+                break;
+            }
+        }
+        tmp = tmp->ifa_next;
+    }
+    return ESP_OK;
+}
+
+esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status)
+{
+    return ESP_OK;
+}
+
+
+esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6)
+{
+    if (esp_netif == NULL) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    struct ifaddrs *addrs, *tmp;
+    getifaddrs(&addrs);
+    tmp = addrs;
+
+    while (tmp)
+    {
+        if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET6) {
+            char addr[64];
+            struct sockaddr_in6 *pAddr = (struct sockaddr_in6 *)tmp->ifa_addr;
+            inet_ntop(AF_INET6, &pAddr->sin6_addr, addr, sizeof(addr) );
+            if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) {
+                printf("AF_INET6: %s: %s\n", tmp->ifa_name, addr);
+                memcpy(if_ip6->addr, &pAddr->sin6_addr, 4*4);
+                break;
+            }
+        }
+        tmp = tmp->ifa_next;
+    }
+
+    freeifaddrs(addrs);
+    return ESP_OK;
+}
+
+
+int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
+{
+    if (esp_netif == NULL) {
+        return -1;
+    }
+    uint32_t interfaceIndex = if_nametoindex(esp_netif->if_desc);
+    return interfaceIndex;
+}
+
+esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
+{
+    if (esp_netif == NULL) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    strcpy(name, esp_netif->if_desc);
+    return ESP_OK;
+}
+
+const char *esp_netif_get_desc(esp_netif_t *esp_netif)
+{
+    if (esp_netif == NULL) {
+        return NULL;
+    }
+    return esp_netif->if_desc;
+}
+
+esp_netif_t *esp_netif_new(const esp_netif_config_t *config)
+{
+    if (esp_netif_get_handle_from_ifkey(config->base->if_key)) {
+        return NULL;
+    }
+    esp_netif_t* netif = calloc(1, sizeof(struct esp_netif_obj));
+    if (netif) {
+        netif->if_desc = config->base->if_desc;
+        netif->if_key = config->base->if_key;
+    }
+
+    for (int i=0; i<MAX_NETIFS; ++i) {
+        if (s_netif_list[i] == NULL) {
+            s_netif_list[i] = netif;
+            break;
+        }
+    }
+
+    return netif;
+}
+
+void esp_netif_destroy(esp_netif_t *esp_netif)
+{
+    for (int i=0; i<MAX_NETIFS; ++i) {
+        if (s_netif_list[i] == esp_netif) {
+            s_netif_list[i] = NULL;
+            break;
+        }
+    }
+    free(esp_netif);
+}

+ 15 - 0
components/mdns/host_test/components/esp_netif_linux/include/esp_wifi_types.h

@@ -0,0 +1,15 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "esp_event.h"

+ 3 - 0
components/mdns/host_test/components/esp_system_protocols_linux/CMakeLists.txt

@@ -0,0 +1,3 @@
+idf_component_register(SRCS esp_log_impl.c strlcat.c
+                       INCLUDE_DIRS include
+                       REQUIRES esp_netif_linux esp_timer_linux freertos_linux esp_event_mock esp_netif log esp_common)

+ 35 - 0
components/mdns/host_test/components/esp_system_protocols_linux/esp_log_impl.c

@@ -0,0 +1,35 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "esp_err.h"
+#include "esp_log.h"
+#include <stdlib.h>
+
+void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression)
+{
+    ESP_LOGE("ESP_ERROR_CHECK", "Failed with esp_err_t: 0x%x", rc);
+    ESP_LOGE("ESP_ERROR_CHECK", "Expression: %s", expression);
+    ESP_LOGE("ESP_ERROR_CHECK", "Functions: %s %s(%d)", function, file, line);
+    abort();
+}
+
+void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level)
+{
+    if ( LOG_LOCAL_LEVEL >= log_level ) {
+        ESP_LOG_LEVEL(log_level, tag, "Buffer:%p length:%d", buffer, buff_len);
+        for (int i=0; i<buff_len; ++i) {
+            printf("%02x ", ((uint8_t*)buffer)[i]);
+        }
+        printf("\n");
+    }
+}

+ 16 - 0
components/mdns/host_test/components/esp_system_protocols_linux/include/bsd_strings.h

@@ -0,0 +1,16 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+size_t strlcat(char *dest, const char *src, size_t size);

+ 16 - 0
components/mdns/host_test/components/esp_system_protocols_linux/include/machine/endian.h

@@ -0,0 +1,16 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include_next "endian.h"

+ 68 - 0
components/mdns/host_test/components/esp_system_protocols_linux/strlcat.c

@@ -0,0 +1,68 @@
+/*	$OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp $	*/
+
+/*-
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "string.h"
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left).  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(dst, src, siz)
+        char *dst;
+        const char *src;
+        size_t siz;
+{
+    char *d = dst;
+    const char *s = src;
+    size_t n = siz;
+    size_t dlen;
+
+    /* Find the end of dst and adjust bytes left but don't go past end */
+    while (n-- != 0 && *d != '\0')
+        d++;
+    dlen = d - dst;
+    n = siz - dlen;
+
+    if (n == 0)
+        return(dlen + strlen(s));
+    while (*s != '\0') {
+        if (n != 1) {
+            *d++ = *s;
+            n--;
+        }
+        s++;
+    }
+    *d = '\0';
+
+    return(dlen + (s - src));	/* count does not include NUL */
+}

+ 5 - 0
components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt

@@ -0,0 +1,5 @@
+idf_component_register(SRCS esp_timer_linux.c timer_task.cpp
+                       INCLUDE_DIRS include
+                       REQUIRES esp_system_protocols_linux freertos_linux)
+
+target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)

+ 47 - 0
components/mdns/host_test/components/esp_timer_linux/esp_timer_linux.c

@@ -0,0 +1,47 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "esp_err.h"
+#include "esp_timer.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+void * create_tt(esp_timer_cb_t cb);
+
+void destroy_tt(void* tt);
+
+void set_tout(void* tt, uint32_t ms);
+
+esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args,
+                           esp_timer_handle_t* out_handle)
+{
+    *out_handle = (esp_timer_handle_t)create_tt(create_args->callback);
+    return ESP_OK;
+}
+
+esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period)
+{
+    set_tout(timer, period/1000);
+    return ESP_OK;
+}
+
+esp_err_t esp_timer_stop(esp_timer_handle_t timer)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_timer_delete(esp_timer_handle_t timer)
+{
+    destroy_tt(timer);
+    return ESP_OK;
+}

+ 41 - 0
components/mdns/host_test/components/esp_timer_linux/include/esp_timer.h

@@ -0,0 +1,41 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef struct esp_timer* esp_timer_handle_t;
+
+typedef void (*esp_timer_cb_t)(void* arg);
+
+typedef enum {
+    ESP_TIMER_TASK,
+} esp_timer_dispatch_t;
+
+typedef struct {
+    esp_timer_cb_t callback;        //!< Function to call when timer expires
+    void* arg;                      //!< Argument to pass to the callback
+    esp_timer_dispatch_t dispatch_method;   //!< Call the callback from task or from ISR
+    const char* name;               //!< Timer name, used in esp_timer_dump function
+    bool skip_unhandled_events;     //!< Skip unhandled events for periodic timers
+} esp_timer_create_args_t;
+
+esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args,
+                           esp_timer_handle_t* out_handle);
+esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period);
+
+esp_err_t esp_timer_stop(esp_timer_handle_t timer);
+
+esp_err_t esp_timer_delete(esp_timer_handle_t timer);

+ 38 - 0
components/mdns/host_test/components/esp_timer_linux/timer_task.cpp

@@ -0,0 +1,38 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "timer_task.hpp"
+#include <cstdint>
+#include <vector>
+#include <memory>
+#include <cstring>
+
+extern "C" void * create_tt(cb_t cb)
+{
+    auto * tt = new TimerTaskMock(cb);
+    return tt;
+}
+
+extern "C" void destroy_tt(void* tt)
+{
+    auto * timer_task = static_cast<TimerTaskMock *>(tt);
+    delete(timer_task);
+}
+
+
+extern "C" void set_tout(void* tt, uint32_t ms)
+{
+    auto * timer_task = static_cast<TimerTaskMock *>(tt);
+    timer_task->SetTimeout(ms);
+}

+ 61 - 0
components/mdns/host_test/components/esp_timer_linux/timer_task.hpp

@@ -0,0 +1,61 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include <queue>
+#include <mutex>
+#include <condition_variable>
+#include <memory>
+#include <thread>
+#include <atomic>
+
+typedef void (*cb_t)(void* arg);
+
+class TimerTaskMock
+{
+public:
+    TimerTaskMock(cb_t cb): cb(cb), t(run_static, this), active(false), ms(INT32_MAX) {}
+    ~TimerTaskMock(void) { active = false; t.join(); }
+
+    void SetTimeout(uint32_t m)
+    {
+        ms = m;
+        active = true;
+    }
+
+private:
+
+    static void run_static(TimerTaskMock* timer)
+    {
+        timer->run();
+    }
+
+    void run(void)
+    {
+        while (!active.load()) {
+            std::this_thread::sleep_for(std::chrono::milliseconds(1));
+        }
+
+        while (active.load()) {
+            std::this_thread::sleep_for(std::chrono::milliseconds(ms));
+            cb(nullptr);
+        }
+    }
+
+    cb_t cb;
+    std::thread t;
+    std::atomic<bool> active;
+    uint32_t ms;
+
+};

+ 9 - 0
components/mdns/host_test/components/freertos_linux/CMakeLists.txt

@@ -0,0 +1,9 @@
+idf_component_register(SRCS freertos_linux.c queue_unique_ptr.cpp
+                       INCLUDE_DIRS include
+                       REQUIRES esp_system_protocols_linux)
+
+set(THREADS_PREFER_PTHREAD_FLAG ON)
+find_package(Threads REQUIRED)
+target_link_libraries(${COMPONENT_LIB}  PRIVATE Threads::Threads)
+
+target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)

+ 7 - 0
components/mdns/host_test/components/freertos_linux/Kconfig

@@ -0,0 +1,7 @@
+menu "FreeRTOS"
+
+    config FREERTOS_NO_AFFINITY
+        hex
+        default 0x7FFFFFFF
+
+endmenu

+ 192 - 0
components/mdns/host_test/components/freertos_linux/freertos_linux.c

@@ -0,0 +1,192 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <unistd.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include <pthread.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+void * create_q(void);
+
+void destroy_q(void* q);
+
+bool send_q(void* q, uint8_t *data, size_t len);
+
+bool recv_q(void* q, uint8_t *data, size_t len, uint32_t ms);
+
+static uint64_t s_semaphore_data = 0;
+
+struct queue_handle {
+    size_t item_size;
+    void * q;
+};
+
+QueueHandle_t xQueueCreate( uint32_t uxQueueLength, uint32_t uxItemSize )
+{
+    struct queue_handle * h = calloc(1, sizeof(struct queue_handle));
+    h->item_size = uxItemSize;
+    h->q = create_q();
+    return (QueueHandle_t)h;
+}
+
+uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait)
+{
+    struct queue_handle * h = xQueue;
+    return send_q(h->q, (uint8_t*)pvItemToQueue, h->item_size) ? pdTRUE : pdFAIL;
+}
+
+uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait)
+{
+    struct queue_handle * h = xQueue;
+    return recv_q(h->q, (uint8_t*)pvBuffer, h->item_size, xTicksToWait) ? pdTRUE : pdFAIL;
+}
+
+BaseType_t xSemaphoreGive( QueueHandle_t xQueue)
+{
+    return xQueueSend(xQueue, &s_semaphore_data, portMAX_DELAY);
+}
+
+BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
+{
+    return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY);
+}
+
+void vQueueDelete( QueueHandle_t xQueue )
+{
+    struct queue_handle * h = xQueue;
+    if (h->q) {
+        destroy_q(h->q);
+    }
+    free(xQueue);
+}
+
+QueueHandle_t xSemaphoreCreateBinary(void)
+{
+    QueueHandle_t sempaphore =  xQueueCreate(1, 1);
+    return sempaphore;
+}
+
+QueueHandle_t xSemaphoreCreateMutex(void)
+{
+    QueueHandle_t sempaphore =  xQueueCreate(1, 1);
+    if (sempaphore) {
+        xSemaphoreGive(sempaphore);
+    }
+    return sempaphore;
+}
+
+void vTaskDelete(TaskHandle_t *task)
+{
+    if (task == NULL) {
+        pthread_exit(0);
+    }
+    void *thread_rval = NULL;
+    pthread_join((pthread_t)task, &thread_rval);
+}
+
+TickType_t xTaskGetTickCount( void )
+{
+    struct timespec spec;
+    clock_gettime(CLOCK_REALTIME, &spec);
+    return spec.tv_nsec / 1000000 + spec.tv_sec * 1000;
+}
+
+void vTaskDelay( const TickType_t xTicksToDelay )
+{
+    usleep(xTicksToDelay*1000);
+}
+
+void * pthread_task(void * params)
+{
+    struct {
+        void * const param;
+        TaskFunction_t task;
+        bool started;
+    } *pthread_params = params;
+
+    void * const param = pthread_params->param;
+    TaskFunction_t task = pthread_params->task;
+    pthread_params->started = true;
+
+    task(param);
+
+    return NULL;
+}
+
+BaseType_t xTaskCreatePinnedToCore(	TaskFunction_t pvTaskCode,
+                                       const char * const pcName,
+                                       const uint32_t usStackDepth,
+                                       void * const pvParameters,
+                                       UBaseType_t uxPriority,
+                                       TaskHandle_t * const pvCreatedTask,
+                                       const BaseType_t xCoreID)
+{
+    xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask);
+    return pdTRUE;
+}
+
+
+void xTaskCreate(TaskFunction_t pvTaskCode, const char * const pcName, const uint32_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pvCreatedTask)
+{
+    pthread_t new_thread = (pthread_t)NULL;
+    pthread_attr_t attr;
+    struct {
+        void * const param;
+        TaskFunction_t task;
+        bool started;
+    } pthread_params = { .param = pvParameters, .task = pvTaskCode};
+    int res = pthread_attr_init(&attr);
+    assert(res == 0);
+    res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+    assert(res == 0);
+    res = pthread_create(&new_thread, &attr, pthread_task, &pthread_params);
+    assert(res == 0);
+
+    if (pvCreatedTask) {
+        *pvCreatedTask = (void*)new_thread;
+    }
+
+    // just wait till the task started so we can unwind params from the stack
+    while (pthread_params.started == false) {
+        usleep(1000);
+    }
+}
+
+uint32_t esp_get_free_heap_size(void)
+{
+    return 0;
+}
+
+uint32_t esp_random(void)
+{
+    return rand();
+}
+
+void xTaskNotifyGive(TaskHandle_t task)
+{
+
+}
+
+BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time )
+{
+    return true;
+}
+
+TaskHandle_t xTaskGetCurrentTaskHandle(void)
+{
+    return NULL;
+}

+ 20 - 0
components/mdns/host_test/components/freertos_linux/include/esp_task.h

@@ -0,0 +1,20 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#define ESP_TASK_PRIO_MAX 25
+#define ESP_TASKD_EVENT_PRIO 5

+ 46 - 0
components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h

@@ -0,0 +1,46 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#define portTICK_PERIOD_MS 1
+#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
+
+typedef void * xSemaphoreHandle;
+typedef void * SemaphoreHandle_t;
+typedef void * xQueueHandle;
+typedef void * QueueHandle_t;
+typedef void * TaskHandle_t;
+typedef uint32_t TickType_t;
+typedef uint32_t portTickType;
+
+typedef void (*TaskFunction_t)( void * );
+typedef unsigned int	UBaseType_t;
+typedef int 			BaseType_t;
+
+#define pdFALSE			( ( BaseType_t ) 0 )
+#define pdTRUE			( ( BaseType_t ) 1 )
+
+#define pdPASS			( pdTRUE )
+#define pdFAIL			( pdFALSE )
+
+#define portTICK_RATE_MS portTICK_PERIOD_MS
+#define pdMS_TO_TICKS(tick)    (tick)
+
+uint32_t esp_get_free_heap_size(void);
+uint32_t esp_random(void);

+ 58 - 0
components/mdns/host_test/components/freertos_linux/include/freertos/task.h

@@ -0,0 +1,58 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include "freertos/FreeRTOS.h"
+
+#define xTaskHandle TaskHandle_t
+#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
+
+void vTaskDelay( const TickType_t xTicksToDelay );
+
+void xTaskNotifyGive(TaskHandle_t task);
+
+TaskHandle_t xTaskGetCurrentTaskHandle(void);
+
+BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time );
+
+BaseType_t xTaskCreatePinnedToCore(	TaskFunction_t pvTaskCode,
+                                       const char * const pcName,
+                                       const uint32_t usStackDepth,
+                                       void * const pvParameters,
+                                       UBaseType_t uxPriority,
+                                       TaskHandle_t * const pvCreatedTask,
+                                       const BaseType_t xCoreID);
+
+void xTaskCreate(TaskFunction_t pvTaskCode, const char * const pcName, const uint32_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pvCreatedTask);
+
+TickType_t xTaskGetTickCount( void );
+
+void vQueueDelete( QueueHandle_t xQueue );
+
+QueueHandle_t xSemaphoreCreateBinary(void);
+
+QueueHandle_t xSemaphoreCreateMutex(void);
+
+BaseType_t xSemaphoreGive( QueueHandle_t xQueue);
+
+BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask );
+
+void vTaskDelete(TaskHandle_t *task);
+
+QueueHandle_t xQueueCreate( uint32_t uxQueueLength,
+                            uint32_t uxItemSize );
+
+uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
+
+uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);

+ 51 - 0
components/mdns/host_test/components/freertos_linux/queue_unique_ptr.cpp

@@ -0,0 +1,51 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "queue_unique_ptr.hpp"
+#include <cstdint>
+#include <vector>
+#include <memory>
+#include <cstring>
+
+extern "C" void * create_q(void)
+{
+    auto * q = new QueueMock<std::vector<uint8_t>>();
+    return q;
+}
+
+extern "C" void destroy_q(void* q)
+{
+    auto * queue = static_cast<QueueMock<std::vector<uint8_t>> *>(q);
+    delete(queue);
+}
+
+extern "C" bool send_q(void* q, uint8_t *data, size_t len)
+{
+    auto v = std::make_unique<std::vector<uint8_t>>(len);
+    v->assign(data, data+len);
+    auto queue = static_cast<QueueMock<std::vector<uint8_t>> *>(q);
+    queue->send(std::move(v));
+    return true;
+}
+
+extern "C" bool recv_q(void* q, uint8_t *data, size_t len, uint32_t ms)
+{
+    auto queue = static_cast<QueueMock<std::vector<uint8_t>> *>(q);
+    auto v = queue->receive(ms);
+    if (v == nullptr) {
+        return false;
+    }
+    memcpy(data, (void *)v->data(), len);
+    return true;
+}

+ 55 - 0
components/mdns/host_test/components/freertos_linux/queue_unique_ptr.hpp

@@ -0,0 +1,55 @@
+// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <queue>
+#include <mutex>
+#include <condition_variable>
+#include <memory>
+#include <thread>
+#include <atomic>
+
+template <class T>
+class QueueMock
+{
+public:
+    QueueMock(void): q(), m(), c() {}
+    ~QueueMock(void) {}
+
+void send(std::unique_ptr<T> t)
+{
+    std::lock_guard<std::mutex> lock(m);
+    q.push(std::move(t));
+    c.notify_one();
+}
+
+std::unique_ptr<T> receive(uint32_t ms)
+{
+    std::unique_lock<std::mutex> lock(m);
+    while(q.empty()) {
+        if (c.wait_for(lock, std::chrono::milliseconds(ms)) == std::cv_status::timeout) {
+            return nullptr;
+        }
+    }
+    std::unique_ptr<T> val = std::move(q.front());
+    q.pop();
+    return val;
+}
+
+private:
+    std::queue<std::unique_ptr<T>> q;
+    mutable std::mutex m;
+    std::condition_variable c;
+};

+ 4 - 0
components/mdns/host_test/main/CMakeLists.txt

@@ -0,0 +1,4 @@
+idf_component_register(SRCS "main.c"
+                    INCLUDE_DIRS
+                    "."
+                    REQUIRES mdns)

+ 59 - 0
components/mdns/host_test/main/main.c

@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include "mdns.h"
+#include "esp_log.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+static const char *TAG = "mdns-test";
+
+static void query_mdns_host(const char * host_name)
+{
+    ESP_LOGI(TAG, "Query A: %s.local", host_name);
+
+    struct esp_ip4_addr addr;
+    addr.addr = 0;
+
+    esp_err_t err = mdns_query_a(host_name, 2000,  &addr);
+    if(err){
+        if(err == ESP_ERR_NOT_FOUND){
+            ESP_LOGW(TAG, "%x: Host was not found!", (err));
+            return;
+        }
+        ESP_LOGE(TAG, "Query Failed: %x", (err));
+        return;
+    }
+
+    ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr));
+}
+
+int main(int argc , char *argv[])
+{
+
+    setvbuf(stdout, NULL, _IONBF, 0);
+    const esp_netif_inherent_config_t base_cg = { .if_key = "WIFI_STA_DEF", .if_desc = "eth2" };
+    esp_netif_config_t cfg = { .base = &base_cg  };
+    esp_netif_t *sta = esp_netif_new(&cfg);
+
+    mdns_init();
+
+    mdns_hostname_set("myesp");
+    ESP_LOGI(TAG, "mdns hostname set to: [%s]", "myesp");
+    //set default mDNS instance name
+    mdns_instance_name_set("myesp-inst");
+    //structure with TXT records
+    mdns_txt_item_t serviceTxtData[3] = {
+            {"board","esp32"},
+            {"u","user"},
+            {"p","password"}
+    };
+    vTaskDelay(1000);
+    ESP_ERROR_CHECK(mdns_service_add("myesp-service2", "_http", "_tcp", 80, serviceTxtData, 3));
+    vTaskDelay(2000);
+
+    query_mdns_host("david-comp");
+    vTaskDelay(2000);
+    esp_netif_destroy(sta);
+    mdns_free();
+    ESP_LOGI(TAG, "Exit");
+    return 0;
+}

+ 2 - 0
components/mdns/private_include/mdns_private.h

@@ -14,8 +14,10 @@
 #ifndef MDNS_PRIVATE_H_
 #define MDNS_PRIVATE_H_
 
+#include "sdkconfig.h"
 #include "mdns.h"
 #include "esp_task.h"
+#include "esp_timer.h"
 
 //#define MDNS_ENABLE_DEBUG