mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-27 17:27:27 +02:00
Compare commits
13 Commits
modem-v0.1
...
mdns-v1.0.
Author | SHA1 | Date | |
---|---|---|---|
b9b4a75000 | |||
cc259aa035 | |||
91134f10ff | |||
fb8a2f0198 | |||
b87bef52e5 | |||
28813148b2 | |||
ae38f27997 | |||
d0c9070715 | |||
a8339e4618 | |||
12cfcb5aed | |||
2cfffb056e | |||
0247926219 | |||
f9b47900f2 |
27
.github/workflows/host-test.yml
vendored
27
.github/workflows/host-test.yml
vendored
@ -3,8 +3,8 @@ name: Host test
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
host_test:
|
||||
name: Build and Test on Host
|
||||
host_test_esp_modem:
|
||||
name: esp-modem Build and Test on Host
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:release-v4.3
|
||||
env:
|
||||
@ -38,3 +38,26 @@ jobs:
|
||||
if: always()
|
||||
with:
|
||||
files: esp-protocols/components/esp_modem/test/host_test/junit.xml
|
||||
|
||||
host_test_mdns:
|
||||
name: mdns Build and Test on Host
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:latest
|
||||
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
path: esp-protocols
|
||||
|
||||
- name: Build and Test
|
||||
shell: bash
|
||||
run: |
|
||||
apt-get update && apt-get install -y dnsutils gcc g++
|
||||
. ${IDF_PATH}/export.sh
|
||||
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/host_test
|
||||
idf.py build
|
||||
./build/mdns_host.elf &
|
||||
dig +short -p 5353 @224.0.0.251 myesp.local > ip.txt
|
||||
cat ip.txt | xargs dig +short -p 5353 @224.0.0.251 -x
|
||||
cat ip.txt
|
||||
|
72
.github/workflows/target-test.yml
vendored
72
.github/workflows/target-test.yml
vendored
@ -62,48 +62,30 @@ jobs:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32", "esp32s2", "esp32c3"]
|
||||
config: ["eth_custom_netif", "eth_def", "eth_no_ipv6", "eth_socket"]
|
||||
test: [ { app: example, path: "components/mdns/examples" }, { app: unit_test, path: "components/mdns/tests/unit_test" } ]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/mdns/examples
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }} for ${{ matrix.config }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
working-directory: ${{ matrix.test.path }}
|
||||
run: |
|
||||
${IDF_PATH}/install.sh --enable-pytest
|
||||
. ${IDF_PATH}/export.sh
|
||||
rm -rf sdkconfig sdkconfig.defaults build build_${{ matrix.config }}
|
||||
cat sdkconfig.ci.${{ matrix.config }} >> sdkconfig.defaults
|
||||
idf.py set-target ${{ matrix.idf_target }}
|
||||
idf.py build
|
||||
mv build build_${{ matrix.config }}
|
||||
- name: Merge binaries with IDF-${{ matrix.idf_ver }} for ${{ matrix.config }}
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
env:
|
||||
IDF_TARGET: ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
cd build_${{ matrix.config }}
|
||||
esptool.py --chip ${{ matrix.idf_target }} merge_bin --fill-flash-size 4MB -o flash_image.bin @flash_args
|
||||
python $IDF_PATH/tools/ci/ci_build_apps.py . --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
|
||||
for dir in `ls -d build_*`; do
|
||||
$GITHUB_WORKSPACE/ci/clean_build_artifacts.sh `pwd`/$dir
|
||||
zip -qur artifacts.zip $dir
|
||||
done
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: ${{ matrix.idf_target }} == "esp32"
|
||||
with:
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}
|
||||
path: |
|
||||
${{ env.TEST_DIR }}/build_${{ matrix.config }}/bootloader/bootloader.bin
|
||||
${{ env.TEST_DIR }}/build_${{ matrix.config }}/partition_table/partition-table.bin
|
||||
${{ env.TEST_DIR }}/build_${{ matrix.config }}/*.bin
|
||||
${{ env.TEST_DIR }}/build_${{ matrix.config }}/*.elf
|
||||
${{ env.TEST_DIR }}/build_${{ matrix.config }}/flasher_args.json
|
||||
${{ env.TEST_DIR }}/build_${{ matrix.config }}/config/sdkconfig.h
|
||||
${{ env.TEST_DIR }}/build_${{ matrix.config }}/config/sdkconfig.json
|
||||
name: mdns_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: ${{ matrix.test.path }}/artifacts.zip
|
||||
if-no-files-found: error
|
||||
|
||||
build_asio:
|
||||
@ -240,14 +222,12 @@ jobs:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32"]
|
||||
config: ["eth_custom_netif", "eth_def", "eth_no_ipv6", "eth_socket"]
|
||||
name: Run mDNS Example Test on target
|
||||
test: [ { app: example, path: "components/mdns/examples" }, { app: unit_test, path: "components/mdns/tests/unit_test" } ]
|
||||
name: Run mDNS target tests
|
||||
needs: build_mdns
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ESP32-ETHERNET-KIT
|
||||
env:
|
||||
TEST_DIR: components/mdns/examples
|
||||
# Skip running on forks since it won't have access to secrets
|
||||
if: github.repository == 'espressif/esp-protocols'
|
||||
steps:
|
||||
@ -256,28 +236,27 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}
|
||||
path: ${{ env.TEST_DIR }}/build_${{ matrix.config }}
|
||||
name: mdns_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: ${{ matrix.test.path }}/ci/
|
||||
- name: Install Python packages
|
||||
env:
|
||||
PIP_EXTRA_INDEX_URL: "https://www.piwheels.org/simple"
|
||||
run: |
|
||||
sudo apt-get install -y dnsutils
|
||||
- name: Download Example Test to target ${{ matrix.config }}
|
||||
run: |
|
||||
python -m esptool --chip ${{ matrix.idf_target }} write_flash 0x0 components/mdns/examples/build_${{ matrix.config }}/flash_image.bin
|
||||
- name: Run Example Test on target ${{ matrix.config }}
|
||||
working-directory: components/mdns/examples
|
||||
- name: Run ${{ matrix.test.app }} application on ${{ matrix.idf_target }}
|
||||
working-directory: ${{ matrix.test.path }}
|
||||
run: |
|
||||
unzip ci/artifacts.zip -d ci
|
||||
for dir in `ls -d ci/build_*`; do
|
||||
rm -rf build sdkconfig.defaults
|
||||
mv build_${{ matrix.config }} build
|
||||
cat sdkconfig.ci.${{ matrix.config }} >> sdkconfig.defaults
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}.xml --target=${{ matrix.idf_target }}
|
||||
mv $dir build
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=${{ matrix.idf_target }}
|
||||
done
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}
|
||||
path: ${{ env.TEST_DIR }}/*.xml
|
||||
name: results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml
|
||||
path: ${{ matrix.test.path }}/*.xml
|
||||
|
||||
run-target-asio:
|
||||
strategy:
|
||||
@ -348,7 +327,6 @@ jobs:
|
||||
idf.py set-target ${{ matrix.idf_target }}
|
||||
idf.py build
|
||||
$GITHUB_WORKSPACE/ci/clean_build_artifacts.sh ${GITHUB_WORKSPACE}/${TEST_DIR}/build
|
||||
ls build
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: modem_target_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
|
@ -4,4 +4,4 @@
|
||||
# - flasher args
|
||||
# - sdkconfigs (header and json)
|
||||
# (Ignoring the command failure as it refuses to delete nonempty dirs)
|
||||
find $1 ! -regex ".*/build/[^/]+.\(bin\|elf\)" -a ! -regex ".*\(bootloader\|partition-table\).bin" -a ! -name "flasher_args.json" -a ! -regex ".*/build/config/sdkconfig.\(h\|json\)" -delete || true
|
||||
find $1 ! -regex ".*/build[^/]*/[^/]+.\(bin\|elf\)" -a ! -regex ".*\(bootloader\|partition-table\).bin" -a ! -name "flasher_args.json" -a ! -regex ".*/build[^/]*/config/sdkconfig.\(h\|json\)" -delete || true
|
||||
|
@ -115,6 +115,7 @@ struct esp_websocket_client {
|
||||
int auto_reconnect;
|
||||
bool run;
|
||||
bool wait_for_pong_resp;
|
||||
bool selected_for_destroying;
|
||||
EventGroupHandle_t status_bits;
|
||||
SemaphoreHandle_t lock;
|
||||
char *rx_buffer;
|
||||
@ -342,6 +343,26 @@ static esp_err_t esp_websocket_client_destroy_config(esp_websocket_client_handle
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void destroy_and_free_resources(esp_websocket_client_handle_t client)
|
||||
{
|
||||
if (client->event_handle) {
|
||||
esp_event_loop_delete(client->event_handle);
|
||||
}
|
||||
if (client->if_name) {
|
||||
free(client->if_name);
|
||||
}
|
||||
esp_websocket_client_destroy_config(client);
|
||||
esp_transport_list_destroy(client->transport_list);
|
||||
vQueueDelete(client->lock);
|
||||
free(client->tx_buffer);
|
||||
free(client->rx_buffer);
|
||||
if (client->status_bits) {
|
||||
vEventGroupDelete(client->status_bits);
|
||||
}
|
||||
free(client);
|
||||
client = NULL;
|
||||
}
|
||||
|
||||
static esp_err_t set_websocket_transport_optional_settings(esp_websocket_client_handle_t client, const char *scheme)
|
||||
{
|
||||
esp_transport_handle_t trans = esp_transport_list_get_transport(client->transport_list, scheme);
|
||||
@ -527,6 +548,7 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
|
||||
client->reconnect_tick_ms = _tick_get_ms();
|
||||
client->ping_tick_ms = _tick_get_ms();
|
||||
client->wait_for_pong_resp = false;
|
||||
client->selected_for_destroying = false;
|
||||
|
||||
int buffer_size = config->buffer_size;
|
||||
if (buffer_size <= 0) {
|
||||
@ -563,22 +585,16 @@ esp_err_t esp_websocket_client_destroy(esp_websocket_client_handle_t client)
|
||||
if (client->run) {
|
||||
esp_websocket_client_stop(client);
|
||||
}
|
||||
if (client->event_handle) {
|
||||
esp_event_loop_delete(client->event_handle);
|
||||
destroy_and_free_resources(client);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_websocket_client_destroy_on_exit(esp_websocket_client_handle_t client)
|
||||
{
|
||||
if (client == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (client->if_name) {
|
||||
free(client->if_name);
|
||||
}
|
||||
esp_websocket_client_destroy_config(client);
|
||||
esp_transport_list_destroy(client->transport_list);
|
||||
vQueueDelete(client->lock);
|
||||
free(client->tx_buffer);
|
||||
free(client->rx_buffer);
|
||||
if (client->status_bits) {
|
||||
vEventGroupDelete(client->status_bits);
|
||||
}
|
||||
free(client);
|
||||
client = NULL;
|
||||
client->selected_for_destroying = true;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -833,6 +849,9 @@ static void esp_websocket_client_task(void *pv)
|
||||
esp_transport_close(client->transport);
|
||||
xEventGroupSetBits(client->status_bits, STOPPED_BIT);
|
||||
client->state = WEBSOCKET_STATE_UNKNOW;
|
||||
if (client->selected_for_destroying == true) {
|
||||
destroy_and_free_resources(client);
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
|
@ -166,6 +166,18 @@ esp_err_t esp_websocket_client_stop(esp_websocket_client_handle_t client);
|
||||
*/
|
||||
esp_err_t esp_websocket_client_destroy(esp_websocket_client_handle_t client);
|
||||
|
||||
/**
|
||||
* @brief If this API called, WebSocket client will destroy and free all resources at the end of event loop.
|
||||
*
|
||||
* Notes:
|
||||
* - After event loop finished, client handle would be dangling and should never be used
|
||||
*
|
||||
* @param[in] client The client
|
||||
*
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t esp_websocket_client_destroy_on_exit(esp_websocket_client_handle_t client);
|
||||
|
||||
/**
|
||||
* @brief Write binary data to the WebSocket connection (data send with WS OPCODE=02, i.e. binary)
|
||||
*
|
||||
|
@ -6,7 +6,7 @@ endif()
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
if(${target} STREQUAL "linux")
|
||||
set(dependencies esp_system_protocols_linux)
|
||||
set(dependencies esp_event esp_netif_linux esp_timer_linux esp_system)
|
||||
set(srcs "mdns.c" ${MDNS_NETWORKING})
|
||||
else()
|
||||
set(dependencies lwip console esp_netif)
|
||||
@ -22,6 +22,11 @@ idf_component_register(
|
||||
PRIV_REQUIRES ${private_dependencies})
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
if(${target} STREQUAL "linux")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE "-lbsd")
|
||||
endif()
|
||||
|
||||
|
||||
if(CONFIG_ETH_ENABLED)
|
||||
idf_component_optional_requires(PRIVATE esp_eth)
|
||||
endif()
|
||||
|
@ -64,17 +64,6 @@ menu "mDNS"
|
||||
Configures timeout for adding a new mDNS service. Adding a service
|
||||
fails if could not be completed within this time.
|
||||
|
||||
config MDNS_STRICT_MODE
|
||||
bool "mDNS strict mode"
|
||||
default "n"
|
||||
help
|
||||
Configures strict mode. Set this to 1 for the mDNS library to strictly follow the RFC6762:
|
||||
Currently the only strict feature: Do not repeat original questions in response packets
|
||||
(defined in RFC6762 sec. 6).
|
||||
Default configuration is 0, i.e. non-strict mode, since some implementations,
|
||||
such as lwIP mDNS resolver (used by standard POSIX API like getaddrinfo, gethostbyname)
|
||||
could not correctly resolve advertised names.
|
||||
|
||||
config MDNS_TIMER_PERIOD_MS
|
||||
int "mDNS timer period (ms)"
|
||||
range 10 10000
|
||||
@ -92,6 +81,27 @@ menu "mDNS"
|
||||
This option creates a new thread to serve receiving packets (TODO).
|
||||
This option uses additional N sockets, where N is number of interfaces.
|
||||
|
||||
config MDNS_SKIP_SUPPRESSING_OWN_QUERIES
|
||||
bool "Skip suppressing our own packets"
|
||||
default n
|
||||
help
|
||||
Enable only if the querier and the responder share the same IP address.
|
||||
This usually happens in test mode, where we may run multiple instances of
|
||||
responders/queriers on the same interface.
|
||||
|
||||
config MDNS_ENABLE_DEBUG_PRINTS
|
||||
bool "Enable debug prints of mDNS packets"
|
||||
default n
|
||||
help
|
||||
Enable for the library to log received and sent mDNS packets to stdout.
|
||||
|
||||
config MDNS_RESPOND_REVERSE_QUERIES
|
||||
bool "Enable responding to IPv4 reverse queries"
|
||||
default n
|
||||
help
|
||||
Enables support for IPv4 reverse lookup. If enabled, the mDNS library
|
||||
response to PTR queries of "A.B.C.D.in-addr.arpa" type.
|
||||
|
||||
config MDNS_MULTIPLE_INSTANCE
|
||||
bool "Multiple instances under the same service type"
|
||||
default y
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@ -279,6 +279,13 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(mdns_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_ENABLE_IP4));
|
||||
ESP_ERROR_CHECK(mdns_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_ANNOUNCE_IP4));
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MDNS_RESPOND_REVERSE_QUERIES)
|
||||
while (mdns_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_IP4_REVERSE_LOOKUP) != ESP_OK) {
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
}
|
||||
#endif
|
||||
|
||||
initialise_button();
|
||||
xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import re
|
||||
import select
|
||||
@ -8,8 +8,11 @@ import subprocess
|
||||
import time
|
||||
from threading import Event, Thread
|
||||
|
||||
import dpkt
|
||||
import dpkt.dns
|
||||
try:
|
||||
import dpkt
|
||||
import dpkt.dns
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def get_dns_query_for_esp(esp_host):
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: "1.0.7"
|
||||
version: "1.0.8"
|
||||
description: mDNS
|
||||
dependencies:
|
||||
idf:
|
||||
|
@ -34,6 +34,8 @@ typedef enum {
|
||||
MDNS_EVENT_ANNOUNCE_IP6 = 1 << 4,
|
||||
MDNS_EVENT_DISABLE_IP4 = 1 << 5,
|
||||
MDNS_EVENT_DISABLE_IP6 = 1 << 6,
|
||||
MDNS_EVENT_IP4_REVERSE_LOOKUP = 1 << 7,
|
||||
MDNS_EVENT_IP6_REVERSE_LOOKUP = 1 << 8,
|
||||
} mdns_event_actions_t;
|
||||
|
||||
/**
|
||||
|
@ -17,10 +17,13 @@
|
||||
#include "mdns_networking.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_random.h"
|
||||
#if CONFIG_ETH_ENABLED
|
||||
|
||||
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
|
||||
#include "esp_eth.h"
|
||||
#endif
|
||||
#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP
|
||||
#include "esp_wifi.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MDNS_ENABLE_DEBUG
|
||||
@ -435,7 +438,10 @@ static const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *star
|
||||
&& (strcasecmp(buf, MDNS_DEFAULT_DOMAIN) != 0)
|
||||
&& (strcasecmp(buf, "arpa") != 0)
|
||||
&& (strcasecmp(buf, "ip6") != 0)
|
||||
&& (strcasecmp(buf, "in-addr") != 0)) {
|
||||
#ifndef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
|
||||
&& (strcasecmp(buf, "in-addr") != 0)
|
||||
#endif
|
||||
) {
|
||||
strlcat(name->host, ".", sizeof(name->host));
|
||||
strlcat(name->host, buf, sizeof(name->host));
|
||||
} else if (strcasecmp(buf, MDNS_SUB_STR) == 0) {
|
||||
@ -639,6 +645,60 @@ static inline int append_one_txt_record_entry(uint8_t *packet, uint16_t *index,
|
||||
return len + 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
|
||||
static inline int append_single_str(uint8_t *packet, uint16_t *index, const char *str, int len)
|
||||
{
|
||||
if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
if (!_mdns_append_u8(packet, index, len)) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(packet + *index, str, len);
|
||||
*index += len;
|
||||
return *index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief appends FQDN to a packet from hostname separated by dots. This API works the same way as
|
||||
* _mdns_append_fqdn(), but refrains from DNS compression (as it's mainly used for IP addresses (many short items),
|
||||
* where we gain very little (or compression even gets counter-productive mainly for IPv6 addresses)
|
||||
*
|
||||
* @param packet MDNS packet
|
||||
* @param index offset in the packet
|
||||
* @param name name representing FQDN in '.' separated parts
|
||||
* @param last true if appending the last part (domain, typically "arpa")
|
||||
*
|
||||
* @return length of added data: 0 on error or length on success
|
||||
*/
|
||||
static uint16_t append_fqdn_dots(uint8_t *packet, uint16_t *index, const char *name, bool last)
|
||||
{
|
||||
int len = strlen(name);
|
||||
char *host = (char *)name;
|
||||
char *end = host;
|
||||
char *start = host;
|
||||
do {
|
||||
end = memchr(start, '.', len);
|
||||
end = end ? end : host + len;
|
||||
int part_len = end - start;
|
||||
if (!append_single_str(packet, index, start, part_len)) {
|
||||
return 0;
|
||||
}
|
||||
start = ++end;
|
||||
} while (end < name + len);
|
||||
|
||||
if (!append_single_str(packet, index, "arpa", sizeof("arpa") - 1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//empty string so terminate
|
||||
if (!_mdns_append_u8(packet, index, 0)) {
|
||||
return 0;
|
||||
}
|
||||
return *index;
|
||||
}
|
||||
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
|
||||
|
||||
/**
|
||||
* @brief appends FQDN to a packet, incrementing the index and
|
||||
* compressing the output if previous occurrence of the string (or part of it) has been found
|
||||
@ -680,7 +740,7 @@ search_next:
|
||||
const uint8_t *content = _mdns_read_fqdn(packet, len_location, &name, buf, packet_len);
|
||||
if (!content) {
|
||||
//not a readable fqdn?
|
||||
return 0;
|
||||
goto search_next; // could be our unfinished fqdn, continue searching
|
||||
}
|
||||
if (name.parts == count) {
|
||||
uint8_t i;
|
||||
@ -1100,25 +1160,34 @@ static uint16_t _mdns_append_aaaa_record(uint8_t *packet, uint16_t *index, const
|
||||
*/
|
||||
static uint16_t _mdns_append_question(uint8_t *packet, uint16_t *index, mdns_out_question_t *q)
|
||||
{
|
||||
const char *str[4];
|
||||
uint8_t str_index = 0;
|
||||
uint8_t part_length;
|
||||
if (q->host) {
|
||||
str[str_index++] = q->host;
|
||||
}
|
||||
if (q->service) {
|
||||
str[str_index++] = q->service;
|
||||
}
|
||||
if (q->proto) {
|
||||
str[str_index++] = q->proto;
|
||||
}
|
||||
if (q->domain) {
|
||||
str[str_index++] = q->domain;
|
||||
}
|
||||
|
||||
part_length = _mdns_append_fqdn(packet, index, str, str_index, MDNS_MAX_PACKET_SIZE);
|
||||
if (!part_length) {
|
||||
return 0;
|
||||
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
|
||||
if (q->host && strstr(q->host, "in-addr")) {
|
||||
part_length = append_fqdn_dots(packet, index, q->host, false);
|
||||
if (!part_length) {
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
|
||||
{
|
||||
const char *str[4];
|
||||
uint8_t str_index = 0;
|
||||
if (q->host) {
|
||||
str[str_index++] = q->host;
|
||||
}
|
||||
if (q->service) {
|
||||
str[str_index++] = q->service;
|
||||
}
|
||||
if (q->proto) {
|
||||
str[str_index++] = q->proto;
|
||||
}
|
||||
if (q->domain) {
|
||||
str[str_index++] = q->domain;
|
||||
}
|
||||
part_length = _mdns_append_fqdn(packet, index, str, str_index, MDNS_MAX_PACKET_SIZE);
|
||||
if (!part_length) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
part_length += _mdns_append_u16(packet, index, q->type);
|
||||
@ -1200,6 +1269,37 @@ static uint8_t _mdns_append_host_answer(uint8_t *packet, uint16_t *index, mdns_h
|
||||
return num_records;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
|
||||
/**
|
||||
* @brief Appends reverse lookup PTR record
|
||||
*/
|
||||
static uint8_t _mdns_append_reverse_ptr_record(uint8_t *packet, uint16_t *index, const char *name)
|
||||
{
|
||||
if (strstr(name, "in-addr") == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!append_fqdn_dots(packet, index, name, false)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, 10 /* TTL set to 10s*/ )) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t data_len_location = *index - 2; /* store the position of size (2=16bis) of this record */
|
||||
const char *str[2] = { _mdns_self_host.hostname, MDNS_DEFAULT_DOMAIN };
|
||||
|
||||
int part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE);
|
||||
if (!part_length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_mdns_set_u16(packet, data_len_location, part_length);
|
||||
return 1; /* appending only 1 record */
|
||||
}
|
||||
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
|
||||
|
||||
/**
|
||||
* @brief Append PTR answers to packet
|
||||
*
|
||||
@ -1238,6 +1338,10 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an
|
||||
if (answer->type == MDNS_TYPE_PTR) {
|
||||
if (answer->service) {
|
||||
return _mdns_append_service_ptr_answers(packet, index, answer->service, answer->flush, answer->bye);
|
||||
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
|
||||
} else if (answer->host && answer->host->hostname && strstr(answer->host->hostname, "in-addr")) {
|
||||
return _mdns_append_reverse_ptr_record(packet, index, answer->host->hostname) > 0;
|
||||
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
|
||||
} else {
|
||||
return _mdns_append_ptr_record(packet, index,
|
||||
answer->custom_instance, answer->custom_service, answer->custom_proto,
|
||||
@ -1723,14 +1827,24 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_
|
||||
_mdns_free_tx_packet(packet);
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
|
||||
} else if (q->type == MDNS_TYPE_PTR) {
|
||||
mdns_host_item_t *host = mdns_get_host_item(q->host);
|
||||
if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, NULL, host, send_flush, false)) {
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
|
||||
} else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, NULL, send_flush, false)) {
|
||||
_mdns_free_tx_packet(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MDNS_REPEAT_QUERY_IN_RESPONSE
|
||||
if (parsed_packet->src_port != MDNS_SERVICE_PORT && // Repeat the queries only for "One-Shot mDNS queries"
|
||||
(q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA)) {
|
||||
(q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA
|
||||
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
|
||||
|| q->type == MDNS_TYPE_PTR
|
||||
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
|
||||
)) {
|
||||
mdns_out_question_t *out_question = malloc(sizeof(mdns_out_question_t));
|
||||
if (out_question == NULL) {
|
||||
HOOK_MALLOC_FAILED;
|
||||
@ -1751,7 +1865,6 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_
|
||||
out_question->own_dynamic_memory = true;
|
||||
queueToEnd(mdns_out_question_t, packet->questions, out_question);
|
||||
}
|
||||
#endif // MDNS_REPEAT_QUERY_IN_RESPONSE
|
||||
if (q->unicast) {
|
||||
unicast = true;
|
||||
}
|
||||
@ -2950,7 +3063,11 @@ static bool _mdns_name_is_discovery(mdns_name_t *name, uint16_t type)
|
||||
static bool _mdns_name_is_ours(mdns_name_t *name)
|
||||
{
|
||||
//domain have to be "local"
|
||||
if (_str_null_or_empty(name->domain) || strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN)) {
|
||||
if (_str_null_or_empty(name->domain) || ( strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN)
|
||||
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
|
||||
&& strcasecmp(name->domain, "arpa")
|
||||
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
|
||||
) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3310,6 +3427,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet)
|
||||
mdns_debug_packet(data, len);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES
|
||||
// Check if the packet wasn't sent by us
|
||||
if (packet->ip_protocol == MDNS_IP_PROTOCOL_V4) {
|
||||
esp_netif_ip_info_t if_ip_info;
|
||||
@ -3326,6 +3444,7 @@ void mdns_parse_packet(mdns_rx_packet_t *packet)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check for the minimum size of mdns packet
|
||||
if (len <= MDNS_HEAD_ADDITIONAL_OFFSET) {
|
||||
@ -3873,6 +3992,22 @@ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action)
|
||||
if (action & MDNS_EVENT_ANNOUNCE_IP6) {
|
||||
_mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V6, NULL, 0, true);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES
|
||||
if (action & MDNS_EVENT_IP4_REVERSE_LOOKUP) {
|
||||
esp_netif_ip_info_t if_ip_info;
|
||||
if (esp_netif_get_ip_info(_mdns_get_esp_netif(mdns_if), &if_ip_info) == ESP_OK) {
|
||||
esp_ip4_addr_t *ip = &if_ip_info.ip;
|
||||
char *reverse_query_name = NULL;
|
||||
if (asprintf(&reverse_query_name, "%d.%d.%d.%d.in-addr",
|
||||
esp_ip4_addr4_16(ip), esp_ip4_addr3_16(ip),
|
||||
esp_ip4_addr2_16(ip), esp_ip4_addr1_16(ip)) > 0 && reverse_query_name) {
|
||||
ESP_LOGD(TAG, "Registered reverse query: %s.arpa", reverse_query_name);
|
||||
_mdns_delegate_hostname_add(reverse_query_name, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3893,6 +4028,7 @@ static inline void post_mdns_announce_pcb(mdns_predef_if_t preset_if, mdns_ip_pr
|
||||
mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(preset_if), protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_ANNOUNCE_IP4 : MDNS_EVENT_ANNOUNCE_IP6);
|
||||
}
|
||||
|
||||
#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH
|
||||
void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
@ -3970,6 +4106,7 @@ void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH */
|
||||
|
||||
/*
|
||||
* MDNS Search
|
||||
@ -5398,7 +5535,7 @@ esp_err_t mdns_instance_name_set(const char *instance)
|
||||
if (!_mdns_server) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (_str_null_or_empty(instance) || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) {
|
||||
if (_str_null_or_empty(instance) || _mdns_server->hostname == NULL || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
char *new_instance = strndup(instance, MDNS_NAME_BUF_LEN - 1);
|
||||
@ -6067,19 +6204,19 @@ void mdns_debug_packet(const uint8_t *data, size_t len)
|
||||
_mdns_dbg_printf("Packet[%u]: ", t);
|
||||
|
||||
header.id = _mdns_read_u16(data, MDNS_HEAD_ID_OFFSET);
|
||||
header.flags.value = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET);
|
||||
header.flags = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET);
|
||||
header.questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET);
|
||||
header.answers = _mdns_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET);
|
||||
header.servers = _mdns_read_u16(data, MDNS_HEAD_SERVERS_OFFSET);
|
||||
header.additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET);
|
||||
|
||||
_mdns_dbg_printf("%s",
|
||||
(header.flags.value == MDNS_FLAGS_QR_AUTHORITATIVE) ? "AUTHORITATIVE\n" :
|
||||
(header.flags.value == MDNS_FLAGS_DISTRIBUTED) ? "DISTRIBUTED\n" :
|
||||
(header.flags.value == 0) ? "\n" : " "
|
||||
(header.flags == MDNS_FLAGS_QR_AUTHORITATIVE) ? "AUTHORITATIVE\n" :
|
||||
(header.flags == MDNS_FLAGS_DISTRIBUTED) ? "DISTRIBUTED\n" :
|
||||
(header.flags == 0) ? "\n" : " "
|
||||
);
|
||||
if (header.flags.value && header.flags.value != MDNS_FLAGS_QR_AUTHORITATIVE) {
|
||||
_mdns_dbg_printf("0x%04X\n", header.flags.value);
|
||||
if (header.flags && header.flags != MDNS_FLAGS_QR_AUTHORITATIVE) {
|
||||
_mdns_dbg_printf("0x%04X\n", header.flags);
|
||||
}
|
||||
|
||||
if (header.questions) {
|
||||
|
@ -14,34 +14,13 @@
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
//#define MDNS_ENABLE_DEBUG
|
||||
|
||||
#ifdef MDNS_ENABLE_DEBUG
|
||||
#ifdef CONFIG_MDNS_ENABLE_DEBUG_PRINTS
|
||||
#define MDNS_ENABLE_DEBUG
|
||||
#define _mdns_dbg_printf(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/** mDNS strict mode: Set this to 1 for the mDNS library to strictly follow the RFC6762:
|
||||
* Strict features:
|
||||
* - to do not set original questions in response packets per RFC6762, sec 6
|
||||
*
|
||||
* The actual configuration is 0, i.e. non-strict mode, since some implementations,
|
||||
* such as lwIP mdns resolver (used by standard POSIX API like getaddrinfo, gethostbyname)
|
||||
* could not correctly resolve advertised names.
|
||||
*/
|
||||
#ifndef CONFIG_MDNS_STRICT_MODE
|
||||
#define MDNS_STRICT_MODE 0
|
||||
#else
|
||||
#define MDNS_STRICT_MODE 1
|
||||
#endif
|
||||
|
||||
#if !MDNS_STRICT_MODE
|
||||
/* mDNS responders sometimes repeat queries in responses
|
||||
* but according to RFC6762, sec 6: Responses MUST NOT contain
|
||||
* any item in question field */
|
||||
#define MDNS_REPEAT_QUERY_IN_RESPONSE 1
|
||||
#endif
|
||||
|
||||
/** Number of predefined interfaces */
|
||||
#ifndef CONFIG_MDNS_PREDEF_NETIF_STA
|
||||
#define CONFIG_MDNS_PREDEF_NETIF_STA 0
|
||||
|
@ -1,5 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
set(COMPONENTS main)
|
||||
set(COMPONENTS main esp_netif_linux)
|
||||
project(mdns_host)
|
||||
|
@ -1,7 +1,10 @@
|
||||
# Setup dummy network interfaces
|
||||
|
||||
Note: Set two addresses so we could use one as source and another as destination
|
||||
```
|
||||
sudo ip link add eth2 type dummy
|
||||
sudo ip addr add 192.168.1.200/24 dev eth2
|
||||
sudo ip addr add 192.168.1.201/24 dev eth2
|
||||
sudo ip link set eth2 up
|
||||
sudo ifconfig eth2 multicast
|
||||
```
|
||||
@ -12,6 +15,11 @@ sudo ifconfig eth2 multicast
|
||||
dig +short -b 192.168.1.200 -p 5353 @224.0.0.251 myesp.local
|
||||
```
|
||||
|
||||
or a reverse query:
|
||||
```
|
||||
dig +short -b 192.168.2.200 -p 5353 @224.0.0.251 -x 192.168.1.200
|
||||
```
|
||||
|
||||
# Run avahi to browse services
|
||||
|
||||
Avahi needs the netif to have the "multicast" flag set
|
||||
|
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS esp_event_mock.c
|
||||
INCLUDE_DIRS include)
|
@ -8,16 +8,7 @@
|
||||
#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;
|
||||
#include "bsd/string.h"
|
||||
|
||||
esp_err_t esp_event_handler_register(const char *event_base, int32_t event_id, void *event_handler, void *event_handler_arg);
|
||||
|
@ -11,3 +11,9 @@ typedef enum {
|
||||
WIFI_EVENT_AP_START, /**< ESP32 soft-AP start */
|
||||
WIFI_EVENT_AP_STOP, /**< ESP32 soft-AP stop */
|
||||
} mdns_used_event_t;
|
||||
|
||||
#define ESP_EVENT_DECLARE_BASE(x)
|
||||
#define ESP_EVENT_ANY_ID (-1)
|
||||
|
||||
typedef void *esp_event_base_t;
|
||||
typedef void *system_event_t;
|
@ -1,3 +0,0 @@
|
||||
idf_component_register(SRCS esp_event_mock.c
|
||||
INCLUDE_DIRS include
|
||||
REQUIRES esp_system_protocols_linux)
|
@ -1,3 +1,3 @@
|
||||
idf_component_register(SRCS esp_netif_linux.c
|
||||
INCLUDE_DIRS include
|
||||
REQUIRES esp_system_protocols_linux)
|
||||
INCLUDE_DIRS include $ENV{IDF_PATH}/components/esp_netif/include
|
||||
REQUIRES esp_event)
|
||||
|
@ -50,9 +50,7 @@ esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_
|
||||
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;
|
||||
|
@ -1,3 +0,0 @@
|
||||
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)
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#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");
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
size_t strlcat(char *dest, const char *src, size_t size);
|
@ -1,70 +0,0 @@
|
||||
/* $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 */
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
idf_component_register(SRCS esp_timer_linux.c timer_task.cpp
|
||||
INCLUDE_DIRS include
|
||||
REQUIRES esp_system_protocols_linux freertos_linux)
|
||||
REQUIRES esp_event)
|
||||
|
||||
set_target_properties(${COMPONENT_LIB} PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
|
@ -16,7 +16,7 @@ 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(cb_t cb): cb(cb), active(false), ms(INT32_MAX) {}
|
||||
~TimerTaskMock(void)
|
||||
{
|
||||
active = false;
|
||||
@ -27,6 +27,7 @@ public:
|
||||
{
|
||||
ms = m;
|
||||
active = true;
|
||||
t = std::thread(run_static, this);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1,6 +1,5 @@
|
||||
idf_component_register(SRCS freertos_linux.c queue_unique_ptr.cpp
|
||||
INCLUDE_DIRS include
|
||||
REQUIRES esp_system_protocols_linux)
|
||||
INCLUDE_DIRS include)
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
@ -158,16 +158,6 @@ void xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t esp_get_free_heap_size(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t esp_random(void)
|
||||
{
|
||||
return rand();
|
||||
}
|
||||
|
||||
void xTaskNotifyGive(TaskHandle_t task)
|
||||
{
|
||||
|
@ -32,3 +32,4 @@ typedef int BaseType_t;
|
||||
|
||||
uint32_t esp_get_free_heap_size(void);
|
||||
uint32_t esp_random(void);
|
||||
void vTaskSuspendAll(void);
|
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
//
|
||||
// Created by david on 1/13/23.
|
||||
//
|
||||
|
||||
#ifndef _QUEUE_H_
|
||||
#define _QUEUE_H_
|
||||
|
||||
#endif //_QUEUE_H_
|
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
//
|
||||
// Created by david on 1/13/23.
|
||||
//
|
||||
|
||||
#ifndef _SEMAPHR_H_
|
||||
#define _SEMAPHR_H_
|
||||
|
||||
#endif //_SEMAPHR_H_
|
15
components/mdns/tests/host_test/main/Kconfig.projbuild
Normal file
15
components/mdns/tests/host_test/main/Kconfig.projbuild
Normal file
@ -0,0 +1,15 @@
|
||||
menu "Test Configuration"
|
||||
|
||||
config TEST_HOSTNAME
|
||||
string "mDNS Hostname"
|
||||
default "esp32-mdns"
|
||||
help
|
||||
mDNS Hostname for example to use
|
||||
|
||||
config TEST_NETIF_NAME
|
||||
string "Network interface name"
|
||||
default "eth2"
|
||||
help
|
||||
Name/ID if the network interface on which we run the mDNS host test
|
||||
|
||||
endmenu
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@ -35,14 +35,16 @@ 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" };
|
||||
const esp_netif_inherent_config_t base_cg = { .if_key = "WIFI_STA_DEF", .if_desc = CONFIG_TEST_NETIF_NAME };
|
||||
esp_netif_config_t cfg = { .base = &base_cg };
|
||||
esp_netif_t *sta = esp_netif_new(&cfg);
|
||||
ESP_ERROR_CHECK(mdns_init());
|
||||
ESP_ERROR_CHECK(mdns_hostname_set(CONFIG_TEST_HOSTNAME));
|
||||
ESP_LOGI(TAG, "mdns hostname set to: [%s]", CONFIG_TEST_HOSTNAME);
|
||||
ESP_ERROR_CHECK(mdns_register_netif(sta));
|
||||
ESP_ERROR_CHECK(mdns_netif_action(sta, MDNS_EVENT_ENABLE_IP4 | MDNS_EVENT_IP4_REVERSE_LOOKUP));
|
||||
|
||||
mdns_init();
|
||||
|
||||
mdns_hostname_set("myesp");
|
||||
ESP_LOGI(TAG, "mdns hostname set to: [%s]", "myesp");
|
||||
#ifdef REGISTER_SERVICE
|
||||
//set default mDNS instance name
|
||||
mdns_instance_name_set("myesp-inst");
|
||||
//structure with TXT records
|
||||
@ -51,12 +53,12 @@ int main(int argc, char *argv[])
|
||||
{"u", "user"},
|
||||
{"p", "password"}
|
||||
};
|
||||
vTaskDelay(1000);
|
||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||
ESP_ERROR_CHECK(mdns_service_add("myesp-service2", "_http", "_tcp", 80, serviceTxtData, 3));
|
||||
vTaskDelay(2000);
|
||||
|
||||
query_mdns_host("david-comp");
|
||||
vTaskDelay(2000);
|
||||
#endif
|
||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||
query_mdns_host("david-work");
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
esp_netif_destroy(sta);
|
||||
mdns_free();
|
||||
ESP_LOGI(TAG, "Exit");
|
||||
|
9
components/mdns/tests/host_test/sdkconfig.defaults
Normal file
9
components/mdns/tests/host_test/sdkconfig.defaults
Normal file
@ -0,0 +1,9 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
CONFIG_MDNS_NETWORKING_SOCKET=y
|
||||
CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES=y
|
||||
CONFIG_TEST_NETIF_NAME="eth0"
|
||||
CONFIG_TEST_HOSTNAME="myesp"
|
||||
CONFIG_MDNS_PREDEF_NETIF_STA=n
|
||||
CONFIG_MDNS_PREDEF_NETIF_AP=n
|
||||
CONFIG_MDNS_ENABLE_DEBUG_PRINTS=y
|
||||
CONFIG_MDNS_RESPOND_REVERSE_QUERIES=y
|
@ -55,7 +55,6 @@
|
||||
#define INC_TASK_H
|
||||
|
||||
#define pdMS_TO_TICKS(a) a
|
||||
#define portTICK_PERIOD_MS 10
|
||||
#define xSemaphoreTake(s,d) true
|
||||
#define xTaskDelete(a)
|
||||
#define vTaskDelete(a) free(a)
|
||||
@ -87,10 +86,6 @@ typedef int BaseType_t;
|
||||
typedef uint32_t TickType_t;
|
||||
|
||||
|
||||
extern const char *WIFI_EVENT;
|
||||
extern const char *IP_EVENT;
|
||||
extern const char *ETH_EVENT;
|
||||
|
||||
struct udp_pcb {
|
||||
uint8_t dummy;
|
||||
};
|
||||
|
@ -1,2 +1,7 @@
|
||||
idf_component_register(SRC_DIRS "."
|
||||
PRIV_REQUIRES cmock test_utils mdns)
|
||||
# This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS ../.. "$ENV{IDF_PATH}/tools/unit-test-app/components")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(mdns_test)
|
||||
|
5
components/mdns/tests/unit_test/main/CMakeLists.txt
Normal file
5
components/mdns/tests/unit_test/main/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
idf_component_register(SRCS "test_mdns.c"
|
||||
REQUIRES test_utils
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES unity mdns)
|
@ -1,13 +1,16 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include "test_utils.h"
|
||||
|
||||
#include "mdns.h"
|
||||
#include "esp_event.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
#include "unity_fixture.h"
|
||||
#include "memory_checks.h"
|
||||
|
||||
#define MDNS_HOSTNAME "test-hostname"
|
||||
#define MDNS_DELEGATE_HOSTNAME "delegate-hostname"
|
||||
@ -16,6 +19,18 @@
|
||||
#define MDNS_SERVICE_PROTO "_tcp"
|
||||
#define MDNS_SERVICE_PORT 80
|
||||
|
||||
TEST_GROUP(mdns);
|
||||
|
||||
TEST_SETUP(mdns)
|
||||
{
|
||||
test_utils_record_free_mem();
|
||||
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
|
||||
}
|
||||
|
||||
TEST_TEAR_DOWN(mdns)
|
||||
{
|
||||
test_utils_finish_and_evaluate_leaks(32, 64);
|
||||
}
|
||||
|
||||
static void yield_to_all_priorities(void)
|
||||
{
|
||||
@ -27,7 +42,7 @@ static void yield_to_all_priorities(void)
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("mdns api to fail in invalid state", "[mdns][leaks=64]")
|
||||
TEST(mdns, api_fails_with_invalid_state)
|
||||
{
|
||||
TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_init() );
|
||||
TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME) );
|
||||
@ -35,7 +50,7 @@ TEST_CASE("mdns api to fail in invalid state", "[mdns][leaks=64]")
|
||||
TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0) );
|
||||
}
|
||||
|
||||
TEST_CASE("mdns init and deinit", "[mdns][leaks=64]")
|
||||
TEST(mdns, init_deinit)
|
||||
{
|
||||
test_case_uses_tcpip();
|
||||
TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default());
|
||||
@ -45,7 +60,7 @@ TEST_CASE("mdns init and deinit", "[mdns][leaks=64]")
|
||||
esp_event_loop_delete_default();
|
||||
}
|
||||
|
||||
TEST_CASE("mdns api return expected err-code and do not leak memory", "[mdns][leaks=64]")
|
||||
TEST(mdns, api_fails_with_expected_err)
|
||||
{
|
||||
mdns_txt_item_t serviceTxtData[CONFIG_MDNS_MAX_SERVICES] = { {NULL, NULL},
|
||||
};
|
||||
@ -91,7 +106,7 @@ TEST_CASE("mdns api return expected err-code and do not leak memory", "[mdns][le
|
||||
esp_event_loop_delete_default();
|
||||
}
|
||||
|
||||
TEST_CASE("mdns query api return expected err-code and do not leak memory", "[leaks=64]")
|
||||
TEST(mdns, query_api_fails_with_expected_err)
|
||||
{
|
||||
mdns_result_t *results = NULL;
|
||||
esp_ip6_addr_t addr6;
|
||||
@ -100,6 +115,14 @@ TEST_CASE("mdns query api return expected err-code and do not leak memory", "[le
|
||||
TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default());
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_init() );
|
||||
// check it is not possible to register a service or set an instance without configuring the hostname
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, mdns_instance_name_set(MDNS_INSTANCE));
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME));
|
||||
// hostname is set, now adding a service and instance should succeed
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0));
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_instance_name_set(MDNS_INSTANCE));
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_query_ptr(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 10, CONFIG_MDNS_MAX_SERVICES, &results) );
|
||||
mdns_query_results_free(results);
|
||||
|
||||
@ -118,3 +141,16 @@ TEST_CASE("mdns query api return expected err-code and do not leak memory", "[le
|
||||
mdns_free();
|
||||
esp_event_loop_delete_default();
|
||||
}
|
||||
|
||||
TEST_GROUP_RUNNER(mdns)
|
||||
{
|
||||
RUN_TEST_CASE(mdns, api_fails_with_invalid_state)
|
||||
RUN_TEST_CASE(mdns, api_fails_with_expected_err)
|
||||
RUN_TEST_CASE(mdns, query_api_fails_with_expected_err)
|
||||
RUN_TEST_CASE(mdns, init_deinit)
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
UNITY_MAIN(mdns);
|
||||
}
|
8
components/mdns/tests/unit_test/pytest_mdns.py
Normal file
8
components/mdns/tests/unit_test/pytest_mdns.py
Normal file
@ -0,0 +1,8 @@
|
||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
def test_lwip(dut: Dut) -> None:
|
||||
dut.expect_unity_test_output()
|
2
components/mdns/tests/unit_test/sdkconfig.defaults
Normal file
2
components/mdns/tests/unit_test/sdkconfig.defaults
Normal file
@ -0,0 +1,2 @@
|
||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n
|
Reference in New Issue
Block a user