mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-27 17:27:27 +02:00
Compare commits
53 Commits
mqtt_cxx-v
...
mdns-v1.4.
Author | SHA1 | Date | |
---|---|---|---|
73c48307a3 | |||
b9357b31b5 | |||
788f0513fa | |||
bcab28c1b8 | |||
60817dd384 | |||
2c1b16617e | |||
169405b534 | |||
643dc6d43b | |||
f9f234c440 | |||
3f97a8228b | |||
c62b920bb9 | |||
a927bf3a8d | |||
99d5fb27e9 | |||
8a690503ed | |||
7e5ac87d09 | |||
d4da9cb079 | |||
0660ece128 | |||
d7fa24bc20 | |||
9cf4163663 | |||
a8f13bc861 | |||
aecf6f80bf | |||
34d7c1b23b | |||
6766be6955 | |||
234f579bd8 | |||
1e8ede3396 | |||
f107dcd118 | |||
ee00e97b2b | |||
07b79abf62 | |||
c9a58d7350 | |||
6b9a6ce65b | |||
43de7e5c4d | |||
ce7f326af0 | |||
a91ead8ef5 | |||
e425a3c504 | |||
50d059af07 | |||
f198967c98 | |||
c41e8891ca | |||
b80c19d72c | |||
5964eadbf5 | |||
e583848695 | |||
cb1bc41386 | |||
8d91f5fd62 | |||
5ccc018a98 | |||
9d4d5d2d49 | |||
e2f0477a00 | |||
906e447193 | |||
15ae280bbe | |||
e6f9fe2385 | |||
3a6720ded6 | |||
333a68936a | |||
25d8423e6d | |||
bd9f062709 | |||
83ea2876fc |
@ -14,12 +14,17 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
include:
|
||||
- idf_ver: "latest"
|
||||
warning: "Warning: The smallest app partition is nearly full"
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
- name: Build with IDF-${{ matrix.idf_ver }}
|
||||
env:
|
||||
EXPECTED_WARNING: ${{ matrix.warning }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
|
23
.github/workflows/mdns__host-tests.yml
vendored
23
.github/workflows/mdns__host-tests.yml
vendored
@ -10,27 +10,30 @@ on:
|
||||
jobs:
|
||||
host_test_mdns:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
|
||||
name: Host test
|
||||
name: Host test build
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:release-v5.1
|
||||
container: espressif/idf:release-v5.3
|
||||
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: esp-protocols
|
||||
path: 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
|
||||
python -m pip install idf-build-apps dnspython pytest pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf
|
||||
cd $GITHUB_WORKSPACE/protocols
|
||||
# Build host tests app (with all configs and targets supported)
|
||||
python ./ci/build_apps.py components/mdns/tests/host_test/
|
||||
cd components/mdns/tests/host_test
|
||||
# First run the linux_app and send a quick A query and a reverse query
|
||||
./build_linux_app/mdns_host.elf &
|
||||
python dnsfixture.py A myesp.local --ip_only | xargs python dnsfixture.py X
|
||||
# Next we run the pytest (using the console app)
|
||||
pytest
|
||||
|
||||
build_afl_host_test_mdns:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
|
||||
|
4
.github/workflows/modem__target-test.yml
vendored
4
.github/workflows/modem__target-test.yml
vendored
@ -69,9 +69,11 @@ jobs:
|
||||
- modem
|
||||
env:
|
||||
TEST_DIR: components/esp_modem/${{ matrix.test.path }}
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
|
||||
run: |
|
||||
sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
|
@ -0,0 +1 @@
|
||||
idf_component_register()
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -12,8 +12,24 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "osal/osal_api.h"
|
||||
#include <semaphore.h>
|
||||
|
||||
typedef struct task_notifiers {
|
||||
sem_t sem;
|
||||
TaskHandle_t id;
|
||||
} task_notifiers_t;
|
||||
|
||||
typedef struct pthread_params {
|
||||
void *const param;
|
||||
TaskFunction_t task;
|
||||
bool started;
|
||||
TaskHandle_t handle;
|
||||
} pthread_params_t;
|
||||
|
||||
static uint64_t s_semaphore_data = 0;
|
||||
static task_notifiers_t *s_notifiers;
|
||||
static int s_threads = 0;
|
||||
pthread_mutex_t s_mutex;
|
||||
|
||||
typedef enum queue_type_tag {
|
||||
MUTEX_REC,
|
||||
@ -89,6 +105,7 @@ BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue)
|
||||
}
|
||||
return pdFALSE;
|
||||
}
|
||||
|
||||
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
|
||||
{
|
||||
struct generic_queue_handle *h = xQueue;
|
||||
@ -99,7 +116,6 @@ BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
|
||||
return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY);
|
||||
}
|
||||
|
||||
|
||||
BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
|
||||
{
|
||||
struct generic_queue_handle *h = xQueue;
|
||||
@ -110,9 +126,6 @@ BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
|
||||
return pdFALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void vQueueDelete( QueueHandle_t xQueue )
|
||||
{
|
||||
struct generic_queue_handle *h = xQueue;
|
||||
@ -128,8 +141,7 @@ void vQueueDelete( QueueHandle_t xQueue )
|
||||
|
||||
QueueHandle_t xSemaphoreCreateBinary(void)
|
||||
{
|
||||
QueueHandle_t sempaphore = xQueueCreate(1, 1);
|
||||
return sempaphore;
|
||||
return xQueueCreate(1, 1);
|
||||
}
|
||||
|
||||
QueueHandle_t xSemaphoreCreateMutex(void)
|
||||
@ -145,6 +157,13 @@ QueueHandle_t xSemaphoreCreateRecursiveMutex(void)
|
||||
|
||||
void vTaskDelete(TaskHandle_t *task)
|
||||
{
|
||||
for (int i = 0; i < s_threads; ++i) {
|
||||
if (task == s_notifiers[i].id) {
|
||||
sem_destroy(&s_notifiers[i].sem);
|
||||
s_notifiers[i].id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (task == NULL) {
|
||||
pthread_exit(0);
|
||||
}
|
||||
@ -171,14 +190,21 @@ void vTaskDelay( const TickType_t xTicksToDelay )
|
||||
|
||||
void *pthread_task(void *params)
|
||||
{
|
||||
struct {
|
||||
void *const param;
|
||||
TaskFunction_t task;
|
||||
bool started;
|
||||
} *pthread_params = params;
|
||||
pthread_params_t *pthread_params = params;
|
||||
|
||||
void *const param = pthread_params->param;
|
||||
TaskFunction_t task = pthread_params->task;
|
||||
|
||||
pthread_params->handle = xTaskGetCurrentTaskHandle();
|
||||
if (s_threads == 0) {
|
||||
pthread_mutex_init(&s_mutex, NULL);
|
||||
}
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_notifiers = realloc(s_notifiers, sizeof(struct task_notifiers) * (++s_threads));
|
||||
assert(s_notifiers);
|
||||
s_notifiers[s_threads - 1].id = pthread_params->handle;
|
||||
sem_init(&s_notifiers[s_threads - 1].sem, 0, 0);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
pthread_params->started = true;
|
||||
|
||||
task(param);
|
||||
@ -198,16 +224,12 @@ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
|
||||
BaseType_t 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};
|
||||
pthread_params_t pthread_params = { .param = pvParameters, .task = pvTaskCode};
|
||||
|
||||
int res = pthread_attr_init(&attr);
|
||||
assert(res == 0);
|
||||
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||
@ -215,20 +237,33 @@ BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, cons
|
||||
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);
|
||||
}
|
||||
if (pvCreatedTask) {
|
||||
*pvCreatedTask = pthread_params.handle;
|
||||
}
|
||||
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
void xTaskNotifyGive(TaskHandle_t task)
|
||||
{
|
||||
|
||||
int i = 0;
|
||||
while (true) {
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
if (task == s_notifiers[i].id) {
|
||||
sem_post(&s_notifiers[i].sem);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
if (++i == s_threads) {
|
||||
i = 0;
|
||||
}
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time )
|
||||
@ -238,7 +273,7 @@ BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear,
|
||||
|
||||
TaskHandle_t xTaskGetCurrentTaskHandle(void)
|
||||
{
|
||||
return NULL;
|
||||
return (TaskHandle_t)pthread_self();
|
||||
}
|
||||
|
||||
EventGroupHandle_t xEventGroupCreate( void )
|
||||
@ -270,3 +305,22 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits
|
||||
{
|
||||
return osal_signal_wait(xEventGroup, uxBitsToWaitFor, xWaitForAllBits, xTicksToWait);
|
||||
}
|
||||
|
||||
void ulTaskNotifyTake(bool clear_on_exit, uint32_t xTicksToWait)
|
||||
{
|
||||
TaskHandle_t task = xTaskGetCurrentTaskHandle();
|
||||
int i = 0;
|
||||
while (true) {
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
if (task == s_notifiers[i].id) {
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
sem_wait(&s_notifiers[i].sem);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
if (++i == s_threads) {
|
||||
i = 0;
|
||||
}
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
@ -0,0 +1,6 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#pragma once
|
@ -11,6 +11,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define tskNO_AFFINITY ( ( BaseType_t ) 0x7FFFFFFF )
|
||||
#define TaskHandle_t TaskHandle_t
|
||||
#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
|
||||
|
||||
@ -18,6 +19,8 @@ void vTaskDelay( const TickType_t xTicksToDelay );
|
||||
|
||||
void xTaskNotifyGive(TaskHandle_t task);
|
||||
|
||||
void ulTaskNotifyTake(bool stuff, uint32_t timeout);
|
||||
|
||||
TaskHandle_t xTaskGetCurrentTaskHandle(void);
|
||||
|
||||
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time );
|
||||
|
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(console): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py console_cmd_ping
|
||||
tag_format: console_cmd_ping-v$version
|
||||
version: 1.0.0
|
||||
version: 1.1.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## [1.1.0](https://github.com/espressif/esp-protocols/commits/console_cmd_ping-v1.1.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Added command getaddrinfo, set/get dnsserver to console_cmd_ping ([b80c19d7](https://github.com/espressif/esp-protocols/commit/b80c19d7))
|
||||
|
||||
## [1.0.0](https://github.com/espressif/esp-protocols/commits/console_cmd_ping-v1.0.0)
|
||||
|
||||
### Features
|
||||
|
@ -1,4 +1,10 @@
|
||||
idf_component_register(SRCS "console_ping.c"
|
||||
idf_component_register(SRCS "console_ping.c" "console_getaddrinfo.c" "console_getsetdnsserver.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_netif console
|
||||
WHOLE_ARCHIVE)
|
||||
PRIV_REQUIRES esp_netif console)
|
||||
|
||||
if(CONFIG_PING_CMD_AUTO_REGISTRATION)
|
||||
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_ping_register")
|
||||
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_getaddrinfo_register")
|
||||
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_setdnsserver_register")
|
||||
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_getdnsserver_register")
|
||||
endif()
|
||||
|
9
components/console_cmd_ping/Kconfig.projbuild
Normal file
9
components/console_cmd_ping/Kconfig.projbuild
Normal file
@ -0,0 +1,9 @@
|
||||
menu "Ping command Configuration"
|
||||
|
||||
config PING_CMD_AUTO_REGISTRATION
|
||||
bool "Enable Console command ping/dns Auto-registration"
|
||||
default y
|
||||
help
|
||||
Enabling this allows for the autoregistration of the ping and dns commands.
|
||||
|
||||
endmenu
|
@ -1,5 +1,5 @@
|
||||
# Console command ping
|
||||
The component provides a console where the 'ping' command can be executed.
|
||||
# Console command ping and DNS server configuration
|
||||
The component provides a console where the 'ping' command, 'getaddrinfo', and DNS server configuration commands can be executed.
|
||||
|
||||
## API
|
||||
|
||||
@ -27,8 +27,11 @@ The component provides a console where the 'ping' command can be executed.
|
||||
// Register all plugin command added to your project
|
||||
ESP_ERROR_CHECK(console_cmd_all_register());
|
||||
|
||||
// To register only ifconfig command skip calling console_cmd_all_register()
|
||||
// To register only ping/dns command skip calling console_cmd_all_register()
|
||||
ESP_ERROR_CHECK(console_cmd_ping_register());
|
||||
ESP_ERROR_CHECK(console_cmd_getaddrinfo_register());
|
||||
ESP_ERROR_CHECK(console_cmd_setdnsserver_register());
|
||||
ESP_ERROR_CHECK(console_cmd_getdnsserver_register());
|
||||
|
||||
ESP_ERROR_CHECK(console_cmd_start()); // Start console
|
||||
```
|
||||
@ -36,6 +39,8 @@ The component provides a console where the 'ping' command can be executed.
|
||||
### Adding a plugin command or component:
|
||||
To add a plugin command or any component from IDF component manager into your project, simply include an entry within the `idf_component.yml` file.
|
||||
|
||||
Note: **Auto-registration** of a specific plugin command can be disabled from menuconfig.
|
||||
|
||||
For more details refer [IDF Component Manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html)
|
||||
|
||||
|
||||
@ -52,4 +57,72 @@ ping [-W <t>] [-i <t>] [-s <n>] [-c <n>] [-Q <n>] [-T <n>] <host>
|
||||
-Q, --tos=<n> Set Type of Service related bits in IP datagrams
|
||||
-T, --ttl=<n> Set Time to Live related bits in IP datagrams
|
||||
<host> Host address
|
||||
|
||||
getaddrinfo [-f <AF>] [-F <FLAGS>]... [-p <port>] <hostname>
|
||||
Usage: getaddrinfo [options] <hostname> [service]
|
||||
-f, --family=<AF> Address family (AF_INET, AF_INET6, AF_UNSPEC).
|
||||
-F, --flags=<FLAGS> Special flags (AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST, AI_V4MAPPED, AI_ALL).
|
||||
-p, --port=<port> String containing a numeric port number.
|
||||
<hostname> Host address
|
||||
|
||||
setdnsserver <main> [backup] [fallback]
|
||||
Usage: setdnsserver <main> [backup] [fallback]
|
||||
<main> The main DNS server IP address.
|
||||
backup The secondary DNS server IP address (optional).
|
||||
fallback The fallback DNS server IP address (optional).
|
||||
|
||||
getdnsserver
|
||||
Usage: getdnsserver
|
||||
```
|
||||
These commands allow you to configure and retrieve DNS server settings on your ESP32 device, in addition to the existing ping functionality.
|
||||
|
||||
## Usage
|
||||
### Using the setdnsserver command:
|
||||
1. To set the main DNS server:
|
||||
```
|
||||
setdnsserver 8.8.8.8
|
||||
```
|
||||
|
||||
2. To set the main and backup DNS servers:
|
||||
|
||||
```
|
||||
setdnsserver 8.8.8.8 fe80::b0be:83ff:fe77:dd64
|
||||
```
|
||||
|
||||
3. To set the main, backup, and fallback DNS servers:
|
||||
|
||||
```
|
||||
setdnsserver 8.8.8.8 fe80::b0be:83ff:fe77:dd64 www.xyz.com
|
||||
```
|
||||
|
||||
### Using the getdnsserver command:
|
||||
To get the current DNS server settings:
|
||||
```
|
||||
getdnsserver
|
||||
```
|
||||
|
||||
### Using the getaddrinfo command:
|
||||
1. To get address information for a hostname:
|
||||
|
||||
```
|
||||
getaddrinfo www.example.com
|
||||
```
|
||||
|
||||
2. To specify additional options:
|
||||
|
||||
```
|
||||
getaddrinfo -f AF_INET -F AI_PASSIVE www.example.com
|
||||
```
|
||||
|
||||
### Using the ping command:
|
||||
1. To ping a host:
|
||||
|
||||
```
|
||||
ping www.example.com
|
||||
```
|
||||
|
||||
2. To specify additional options, such as timeout, interval, packet size, etc.:
|
||||
|
||||
```
|
||||
ping -W 5 -i 1 -s 64 -c 4 -Q 0x10 -T 64 www.example.com
|
||||
```
|
||||
|
180
components/console_cmd_ping/console_getaddrinfo.c
Normal file
180
components/console_cmd_ping/console_getaddrinfo.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_log.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include <netdb.h>
|
||||
#include "console_ping.h"
|
||||
|
||||
|
||||
static const char *TAG = "console_getaddrinfo";
|
||||
|
||||
#if CONFIG_PING_CMD_AUTO_REGISTRATION
|
||||
/**
|
||||
* @brief Static registration of the getaddrinfo command plugin.
|
||||
*
|
||||
* This section registers the plugin description structure and places it into
|
||||
* the .console_cmd_desc section, as determined by the linker.lf file in the
|
||||
* 'plugins' component.
|
||||
*/
|
||||
static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc"), used)) PLUGIN = {
|
||||
.name = "console_cmd_getddrinfo",
|
||||
.plugin_regd_fn = &console_cmd_getaddrinfo_register
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Structure to hold arguments for the getaddrinfo command.
|
||||
*/
|
||||
static struct {
|
||||
struct arg_str *family;
|
||||
struct arg_str *flags;
|
||||
struct arg_str *port_nr;
|
||||
struct arg_str *hostname;
|
||||
struct arg_end *end;
|
||||
} getddrinfo_args;
|
||||
|
||||
/**
|
||||
* @brief Executes the getaddrinfo command.
|
||||
*
|
||||
* This function parses arguments, sets hints for address resolution, and calls
|
||||
* getaddrinfo to resolve the hostname. It then prints the resolved IP addresses
|
||||
* and associated information.
|
||||
*
|
||||
* @param argc Argument count
|
||||
* @param argv Argument vector
|
||||
*
|
||||
* @return int Returns 0 on success, 1 on error.
|
||||
*/
|
||||
static int do_getddrinfo_cmd(int argc, char **argv)
|
||||
{
|
||||
char ip_str[INET6_ADDRSTRLEN];
|
||||
struct addrinfo hint = {0};
|
||||
struct addrinfo *res = NULL, *res_tmp = NULL;
|
||||
const char *port_nr_str = NULL;
|
||||
int ret = 0;
|
||||
|
||||
int nerrors = arg_parse(argc, argv, (void **)&getddrinfo_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, getddrinfo_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set the address family */
|
||||
if (getddrinfo_args.family->count > 0) {
|
||||
if (strcmp(getddrinfo_args.family->sval[0], "AF_INET") == 0) {
|
||||
hint.ai_family = AF_INET;
|
||||
} else if (strcmp(getddrinfo_args.family->sval[0], "AF_INET6") == 0) {
|
||||
hint.ai_family = AF_INET6;
|
||||
} else if (strcmp(getddrinfo_args.family->sval[0], "AF_UNSPEC") == 0) {
|
||||
hint.ai_family = AF_UNSPEC;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unknown family");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the flags */
|
||||
if (getddrinfo_args.flags->count > 0) {
|
||||
for (int i = 0; i < getddrinfo_args.flags->count; i++) {
|
||||
if (strcmp(getddrinfo_args.flags->sval[i], "AI_PASSIVE") == 0) {
|
||||
hint.ai_flags |= AI_PASSIVE;
|
||||
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_CANONNAME") == 0) {
|
||||
hint.ai_flags |= AI_CANONNAME;
|
||||
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_NUMERICHOST") == 0) {
|
||||
hint.ai_flags |= AI_NUMERICHOST;
|
||||
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_V4MAPPED") == 0) {
|
||||
hint.ai_flags |= AI_V4MAPPED;
|
||||
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_ALL") == 0) {
|
||||
hint.ai_flags |= AI_ALL;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unknown flag: %s", getddrinfo_args.flags->sval[i]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getddrinfo_args.port_nr->count > 0) {
|
||||
port_nr_str = getddrinfo_args.port_nr->sval[0];
|
||||
}
|
||||
|
||||
/* Convert hostname to IP address */
|
||||
if (!strcmp(getddrinfo_args.hostname->sval[0], "NULL")) {
|
||||
ret = getaddrinfo(NULL, port_nr_str, &hint, &res);
|
||||
} else {
|
||||
ret = getaddrinfo(getddrinfo_args.hostname->sval[0], port_nr_str, &hint, &res);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
printf("getddrinfo: Failure host:%s(ERROR: %d)\n", getddrinfo_args.hostname->sval[0], ret);
|
||||
ESP_LOGE(TAG, "Failure host");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Iterate through the results from getaddrinfo */
|
||||
for (res_tmp = res; res_tmp != NULL; res_tmp = res_tmp->ai_next) {
|
||||
|
||||
if (res_tmp->ai_family == AF_INET) {
|
||||
inet_ntop(AF_INET, &((struct sockaddr_in *)res_tmp->ai_addr)->sin_addr, ip_str, INET_ADDRSTRLEN);
|
||||
printf("\tIP Address: %s\n", ip_str);
|
||||
printf("\tAddress Family: AF_INET\n");
|
||||
} else if (res_tmp->ai_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)res_tmp->ai_addr)->sin6_addr, ip_str, INET6_ADDRSTRLEN);
|
||||
printf("\tIP Address: %s\n", ip_str);
|
||||
printf("\tAddress Family: AF_INET6\n");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "ai_family Unknown: %d\n", res_tmp->ai_family);
|
||||
}
|
||||
|
||||
/* Print the protocol used */
|
||||
printf("\tProtocol: %d\n", res_tmp->ai_protocol);
|
||||
|
||||
/* Print the canonical name if available */
|
||||
if (res_tmp->ai_canonname) {
|
||||
printf("\tCanonical Name: %s\n", res_tmp->ai_canonname);
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Registers the getaddrinfo command.
|
||||
*
|
||||
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t console_cmd_getaddrinfo_register(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
getddrinfo_args.family = arg_str0("f", "family", "<AF>", "Address family (AF_INET, AF_INET6, AF_UNSPEC).");
|
||||
getddrinfo_args.flags = arg_strn("F", "flags", "<FLAGS>", 0, 5, "Special flags (AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST, AI_V4MAPPED, AI_ALL).");
|
||||
getddrinfo_args.port_nr = arg_str0("p", "port", "<port>", "String containing a numeric port number.");
|
||||
getddrinfo_args.hostname = arg_str1(NULL, NULL, "<hostname>", "Host address");
|
||||
getddrinfo_args.end = arg_end(1);
|
||||
const esp_console_cmd_t getddrinfo_cmd = {
|
||||
.command = "getaddrinfo",
|
||||
.help = "Usage: getaddrinfo [options] <hostname> [service]",
|
||||
.hint = NULL,
|
||||
.func = &do_getddrinfo_cmd,
|
||||
.argtable = &getddrinfo_args
|
||||
};
|
||||
|
||||
ret = esp_console_cmd_register(&getddrinfo_cmd);
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "Unable to register getddrinfo");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
279
components/console_cmd_ping/console_getsetdnsserver.c
Normal file
279
components/console_cmd_ping/console_getsetdnsserver.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_netif.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "esp_log.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include <netdb.h>
|
||||
#include "console_ping.h"
|
||||
|
||||
|
||||
static const char *TAG = "console_setdnsserver";
|
||||
|
||||
#if CONFIG_PING_CMD_AUTO_REGISTRATION
|
||||
static esp_err_t console_cmd_dnscmd_register(void);
|
||||
|
||||
/**
|
||||
* @brief Static registration of the getaddrinfo command plugin.
|
||||
*
|
||||
* This section registers the plugin description structure and places it into
|
||||
* the .console_cmd_desc section, as determined by the linker.lf file in the
|
||||
* 'plugins' component.
|
||||
*/
|
||||
static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc"), used)) PLUGIN = {
|
||||
.name = "console_cmd_dnscmd",
|
||||
.plugin_regd_fn = &console_cmd_dnscmd_register
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Registers the DNS commands (setdnsserver and getdnsserver) with the console.
|
||||
*
|
||||
* @return esp_err_t Returns ESP_OK.
|
||||
*/
|
||||
static esp_err_t console_cmd_dnscmd_register(void)
|
||||
{
|
||||
console_cmd_setdnsserver_register();
|
||||
console_cmd_getdnsserver_register();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Structure to hold arguments for the setdnsserver command.
|
||||
*/
|
||||
static struct {
|
||||
struct arg_str *main;
|
||||
struct arg_str *backup;
|
||||
struct arg_str *fallback;
|
||||
struct arg_end *end;
|
||||
} setdnsserver_args;
|
||||
|
||||
/**
|
||||
* @brief Sets the DNS server address for all network interfaces.
|
||||
*
|
||||
* This function iterates over all network interfaces available on the ESP32 device
|
||||
* and sets the DNS server address for the specified DNS type (main, backup, or fallback).
|
||||
* The DNS address is only set if a valid address is provided (non-zero and not equal to IPADDR_NONE).
|
||||
*
|
||||
* @param server IP address of the DNS server.
|
||||
* @param type Type of the DNS server (main, backup, fallback).
|
||||
*
|
||||
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
static esp_err_t set_dns_server(const char *server, esp_netif_dns_type_t type)
|
||||
{
|
||||
int ret = 0;
|
||||
struct addrinfo hint = {0};
|
||||
struct addrinfo *res = NULL, *res_tmp = NULL;
|
||||
esp_netif_t *esp_netif = NULL;
|
||||
esp_netif_dns_info_t dns;
|
||||
int addr_cnt = 0;
|
||||
|
||||
ret = getaddrinfo(server, NULL, &hint, &res);
|
||||
if (ret != 0) {
|
||||
printf("setdnsserver: Failure host:%s(ERROR: %d)\n", server, ret);
|
||||
ESP_LOGE(TAG, "Failure host");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (res_tmp = res; res_tmp != NULL; res_tmp = res_tmp->ai_next) {
|
||||
|
||||
if (addr_cnt == 0) {
|
||||
if (res_tmp->ai_family == AF_INET) {
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
|
||||
while ((esp_netif = esp_netif_next_unsafe(esp_netif)) != NULL) {
|
||||
#else
|
||||
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) {
|
||||
#endif
|
||||
struct sockaddr_in *ipv4 = (struct sockaddr_in *)res_tmp->ai_addr;
|
||||
dns.ip.u_addr.ip4.addr = ipv4->sin_addr.s_addr;
|
||||
dns.ip.type = IPADDR_TYPE_V4;
|
||||
ESP_ERROR_CHECK(esp_netif_set_dns_info(esp_netif, type, &dns));
|
||||
}
|
||||
} else if (res_tmp->ai_family == AF_INET6) {
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
|
||||
while ((esp_netif = esp_netif_next_unsafe(esp_netif)) != NULL) {
|
||||
#else
|
||||
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) {
|
||||
#endif
|
||||
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res_tmp->ai_addr;
|
||||
memcpy(dns.ip.u_addr.ip6.addr, &ipv6->sin6_addr, sizeof(dns.ip.u_addr.ip6.addr));
|
||||
dns.ip.type = IPADDR_TYPE_V6;
|
||||
ESP_ERROR_CHECK(esp_netif_set_dns_info(esp_netif, type, &dns));
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "ai_family Unknown: %d\n", res_tmp->ai_family);
|
||||
}
|
||||
}
|
||||
addr_cnt++;
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Command handler for setting DNS server addresses.
|
||||
*
|
||||
* @param argc Argument count.
|
||||
* @param argv Argument values.
|
||||
*
|
||||
* @return int: 0 on success, 1 on error.
|
||||
*/
|
||||
static int do_setdnsserver_cmd(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&setdnsserver_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, setdnsserver_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
set_dns_server(setdnsserver_args.main->sval[0], ESP_NETIF_DNS_MAIN);
|
||||
|
||||
if (setdnsserver_args.backup->count > 0) {
|
||||
set_dns_server(setdnsserver_args.backup->sval[0], ESP_NETIF_DNS_BACKUP);
|
||||
}
|
||||
|
||||
if (setdnsserver_args.fallback->count > 0) {
|
||||
set_dns_server(setdnsserver_args.fallback->sval[0], ESP_NETIF_DNS_FALLBACK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Registers the setdnsserver command.
|
||||
*
|
||||
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t console_cmd_setdnsserver_register(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
setdnsserver_args.main = arg_str1(NULL, NULL, "<main>", "The main DNS server IP address.");
|
||||
setdnsserver_args.backup = arg_str0(NULL, NULL, "backup", "The secondary DNS server IP address (optional).");
|
||||
setdnsserver_args.fallback = arg_str0(NULL, NULL, "fallback", "The fallback DNS server IP address (optional).");
|
||||
setdnsserver_args.end = arg_end(1);
|
||||
const esp_console_cmd_t setdnsserver_cmd = {
|
||||
.command = "setdnsserver",
|
||||
.help = "Usage: setdnsserver <main> [backup] [fallback]",
|
||||
.hint = NULL,
|
||||
.func = &do_setdnsserver_cmd,
|
||||
.argtable = &setdnsserver_args
|
||||
};
|
||||
|
||||
ret = esp_console_cmd_register(&setdnsserver_cmd);
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "Unable to register setdnsserver");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Structure to hold arguments for the getdnsserver command.
|
||||
*/
|
||||
static struct {
|
||||
struct arg_end *end;
|
||||
} getdnsserver_args;
|
||||
|
||||
/**
|
||||
* @brief Command handler for getting DNS server addresses.
|
||||
*
|
||||
* @param argc Argument count.
|
||||
* @param argv Argument values.
|
||||
*
|
||||
* @return int: 0 on success, 1 on error.
|
||||
*/
|
||||
static int do_getdnsserver_cmd(int argc, char **argv)
|
||||
{
|
||||
esp_netif_t *esp_netif = NULL;
|
||||
esp_netif_dns_info_t dns_info;
|
||||
char interface[10];
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
|
||||
int nerrors = arg_parse(argc, argv, (void **)&getdnsserver_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, getdnsserver_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
|
||||
while ((esp_netif = esp_netif_next_unsafe(esp_netif)) != NULL) {
|
||||
#else
|
||||
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) {
|
||||
#endif
|
||||
|
||||
/* Print Interface Name and Number */
|
||||
ret = esp_netif_get_netif_impl_name(esp_netif, interface);
|
||||
if ((ESP_FAIL == ret) || (NULL == esp_netif)) {
|
||||
ESP_LOGE(TAG, "No interface available");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Interface Name: %s\n", interface);
|
||||
ESP_ERROR_CHECK(esp_netif_get_dns_info(esp_netif, ESP_NETIF_DNS_MAIN, &dns_info));
|
||||
if (dns_info.ip.type == ESP_IPADDR_TYPE_V4) {
|
||||
printf("Main DNS server : " IPSTR "\n", IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
} else if (dns_info.ip.type == ESP_IPADDR_TYPE_V6) {
|
||||
printf("Main DNS server : " IPV6STR "\n", IPV62STR(dns_info.ip.u_addr.ip6));
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_get_dns_info(esp_netif, ESP_NETIF_DNS_BACKUP, &dns_info));
|
||||
if (dns_info.ip.type == ESP_IPADDR_TYPE_V4) {
|
||||
printf("Backup DNS server : " IPSTR "\n", IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
} else if (dns_info.ip.type == ESP_IPADDR_TYPE_V6) {
|
||||
printf("Backup DNS server : " IPV6STR "\n", IPV62STR(dns_info.ip.u_addr.ip6));
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_get_dns_info(esp_netif, ESP_NETIF_DNS_FALLBACK, &dns_info));
|
||||
if (dns_info.ip.type == ESP_IPADDR_TYPE_V4) {
|
||||
printf("Fallback DNS server : " IPSTR "\n", IP2STR(&dns_info.ip.u_addr.ip4));
|
||||
} else if (dns_info.ip.type == ESP_IPADDR_TYPE_V6) {
|
||||
printf("Fallback DNS server : " IPV6STR "\n", IPV62STR(dns_info.ip.u_addr.ip6));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Registers the getdnsserver command.
|
||||
*
|
||||
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
|
||||
*/
|
||||
esp_err_t console_cmd_getdnsserver_register(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
getdnsserver_args.end = arg_end(1);
|
||||
const esp_console_cmd_t getdnsserver_cmd = {
|
||||
.command = "getdnsserver",
|
||||
.help = "Usage: getdnsserver",
|
||||
.hint = NULL,
|
||||
.func = &do_getdnsserver_cmd,
|
||||
.argtable = &getdnsserver_args
|
||||
};
|
||||
|
||||
ret = esp_console_cmd_register(&getdnsserver_cmd);
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "Unable to register getdnsserver");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -20,7 +20,7 @@
|
||||
static const char *TAG = "console_ping";
|
||||
SemaphoreHandle_t sync_semaphore;
|
||||
|
||||
|
||||
#if CONFIG_PING_CMD_AUTO_REGISTRATION
|
||||
/**
|
||||
* Static registration of this plugin is achieved by defining the plugin description
|
||||
* structure and placing it into .console_cmd_desc section.
|
||||
@ -30,7 +30,7 @@ static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc
|
||||
.name = "console_cmd_ping",
|
||||
.plugin_regd_fn = &console_cmd_ping_register
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
@ -75,9 +75,13 @@ static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args)
|
||||
loss = 0;
|
||||
}
|
||||
if (IP_IS_V4(&target_addr)) {
|
||||
#if CONFIG_LWIP_IPV4
|
||||
printf("\n--- %s ping statistics ---\n", inet_ntoa(*ip_2_ip4(&target_addr)));
|
||||
#endif
|
||||
} else {
|
||||
#if CONFIG_LWIP_IPV6
|
||||
printf("\n--- %s ping statistics ---\n", inet6_ntoa(*ip_2_ip6(&target_addr)));
|
||||
#endif
|
||||
}
|
||||
printf("%" PRIu32 " packets transmitted, %" PRIu32 " received, %" PRIu32 "%% packet loss, time %" PRIu32 "ms\n",
|
||||
transmitted, received, loss, total_time_ms);
|
||||
@ -150,11 +154,15 @@ static int do_ping_cmd(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
if (res->ai_family == AF_INET) {
|
||||
#if CONFIG_LWIP_IPV4
|
||||
struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr;
|
||||
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
|
||||
#endif
|
||||
} else {
|
||||
#if CONFIG_LWIP_IPV6
|
||||
struct in6_addr addr6 = ((struct sockaddr_in6 *) (res->ai_addr))->sin6_addr;
|
||||
inet6_addr_to_ip6addr(ip_2_ip6(&target_addr), &addr6);
|
||||
#endif
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -20,6 +20,30 @@ extern "C" {
|
||||
*/
|
||||
esp_err_t console_cmd_ping_register(void);
|
||||
|
||||
/**
|
||||
* @brief Registers the getddrinfo command.
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t
|
||||
*/
|
||||
esp_err_t console_cmd_getaddrinfo_register(void);
|
||||
|
||||
/**
|
||||
* @brief Registers the setdnsserver command.
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t
|
||||
*/
|
||||
esp_err_t console_cmd_setdnsserver_register(void);
|
||||
|
||||
/**
|
||||
* @brief Registers the setdnsserver command.
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t
|
||||
*/
|
||||
esp_err_t console_cmd_getdnsserver_register(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 1.0.0
|
||||
version: 1.1.0
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/console_cmd_ping
|
||||
description: The component provides a console where the 'ping' command can be executed.
|
||||
dependencies:
|
||||
|
@ -95,7 +95,9 @@ typedef struct {
|
||||
size_t client_key_len;
|
||||
bool use_global_ca_store;
|
||||
bool skip_cert_common_name_check;
|
||||
const char *cert_common_name;
|
||||
esp_err_t (*crt_bundle_attach)(void *conf);
|
||||
esp_transport_handle_t ext_transport;
|
||||
} websocket_config_storage_t;
|
||||
|
||||
typedef enum {
|
||||
@ -204,6 +206,8 @@ static esp_err_t esp_websocket_client_dispatch_event(esp_websocket_client_handle
|
||||
event_data.error_handle.esp_tls_last_esp_err = esp_tls_get_and_clear_last_error(esp_transport_get_error_handle(client->transport),
|
||||
&client->error_handle.esp_tls_stack_err,
|
||||
&client->error_handle.esp_tls_cert_verify_flags);
|
||||
event_data.error_handle.esp_tls_stack_err = client->error_handle.esp_tls_stack_err;
|
||||
event_data.error_handle.esp_tls_cert_verify_flags = client->error_handle.esp_tls_cert_verify_flags;
|
||||
event_data.error_handle.esp_transport_sock_errno = esp_transport_get_errno(client->transport);
|
||||
}
|
||||
event_data.error_handle.error_type = client->error_handle.error_type;
|
||||
@ -500,6 +504,10 @@ static esp_err_t esp_websocket_client_create_transport(esp_websocket_client_hand
|
||||
if (client->keep_alive_cfg.keep_alive_enable) {
|
||||
esp_transport_ssl_set_keep_alive(ssl, &client->keep_alive_cfg);
|
||||
}
|
||||
if (client->if_name) {
|
||||
esp_transport_ssl_set_interface_name(ssl, client->if_name);
|
||||
}
|
||||
|
||||
if (client->config->use_global_ca_store == true) {
|
||||
esp_transport_ssl_enable_global_ca_store(ssl);
|
||||
} else if (client->config->cert) {
|
||||
@ -533,6 +541,13 @@ static esp_err_t esp_websocket_client_create_transport(esp_websocket_client_hand
|
||||
if (client->config->skip_cert_common_name_check) {
|
||||
esp_transport_ssl_skip_common_name_check(ssl);
|
||||
}
|
||||
if (client->config->cert_common_name) {
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
|
||||
esp_transport_ssl_set_common_name(ssl, client->config->cert_common_name);
|
||||
#else
|
||||
ESP_LOGE(TAG, "cert_common_name requires ESP-IDF 5.1.0 or later");
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_transport_handle_t wss = esp_transport_ws_init(ssl);
|
||||
ESP_WS_CLIENT_MEM_CHECK(TAG, wss, return ESP_ERR_NO_MEM);
|
||||
@ -668,6 +683,11 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
|
||||
}
|
||||
|
||||
// configure ssl related parameters
|
||||
if (config->cert_common_name != NULL && config->skip_cert_common_name_check) {
|
||||
ESP_LOGE(TAG, "Both cert_common_name and skip_cert_common_name_check are set, only one of them can be set");
|
||||
goto _websocket_init_fail;
|
||||
}
|
||||
|
||||
client->config->use_global_ca_store = config->use_global_ca_store;
|
||||
client->config->cert = config->cert_pem;
|
||||
client->config->cert_len = config->cert_len;
|
||||
@ -676,7 +696,9 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
|
||||
client->config->client_key = config->client_key;
|
||||
client->config->client_key_len = config->client_key_len;
|
||||
client->config->skip_cert_common_name_check = config->skip_cert_common_name_check;
|
||||
client->config->cert_common_name = config->cert_common_name;
|
||||
client->config->crt_bundle_attach = config->crt_bundle_attach;
|
||||
client->config->ext_transport = config->ext_transport;
|
||||
|
||||
if (config->uri) {
|
||||
if (esp_websocket_client_set_uri(client, config->uri) != ESP_OK) {
|
||||
@ -935,7 +957,9 @@ static void esp_websocket_client_task(void *pv)
|
||||
client->run = true;
|
||||
|
||||
//get transport by scheme
|
||||
client->transport = esp_transport_list_get_transport(client->transport_list, client->config->scheme);
|
||||
if (client->transport == NULL && client->config->ext_transport == NULL) {
|
||||
client->transport = esp_transport_list_get_transport(client->transport_list, client->config->scheme);
|
||||
}
|
||||
|
||||
if (client->transport == NULL) {
|
||||
ESP_LOGE(TAG, "There are no transports valid, stop websocket client");
|
||||
@ -948,6 +972,7 @@ static void esp_websocket_client_task(void *pv)
|
||||
|
||||
client->state = WEBSOCKET_STATE_INIT;
|
||||
xEventGroupClearBits(client->status_bits, STOPPED_BIT | CLOSE_FRAME_SENT_BIT);
|
||||
esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_BEGIN, NULL, 0);
|
||||
int read_select = 0;
|
||||
while (client->run) {
|
||||
if (xSemaphoreTakeRecursive(client->lock, lock_timeout) != pdPASS) {
|
||||
@ -1082,6 +1107,7 @@ static void esp_websocket_client_task(void *pv)
|
||||
}
|
||||
}
|
||||
|
||||
esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_FINISH, NULL, 0);
|
||||
esp_transport_close(client->transport);
|
||||
xEventGroupSetBits(client->status_bits, STOPPED_BIT);
|
||||
client->state = WEBSOCKET_STATE_UNKNOW;
|
||||
@ -1100,9 +1126,13 @@ esp_err_t esp_websocket_client_start(esp_websocket_client_handle_t client)
|
||||
ESP_LOGE(TAG, "The client has started");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (esp_websocket_client_create_transport(client) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to create websocket transport");
|
||||
return ESP_FAIL;
|
||||
|
||||
client->transport = client->config->ext_transport;
|
||||
if (!client->transport) {
|
||||
if (esp_websocket_client_create_transport(client) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to create websocket transport");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (xTaskCreate(esp_websocket_client_task, client->config->task_name ? client->config->task_name : "websocket_task",
|
||||
@ -1111,6 +1141,7 @@ esp_err_t esp_websocket_client_start(esp_websocket_client_handle_t client)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
xEventGroupClearBits(client->status_bits, STOPPED_BIT | CLOSE_FRAME_SENT_BIT);
|
||||
ESP_LOGI(TAG, "Started");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -1278,6 +1309,43 @@ esp_err_t esp_websocket_client_set_ping_interval_sec(esp_websocket_client_handle
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int esp_websocket_client_get_reconnect_timeout(esp_websocket_client_handle_t client)
|
||||
{
|
||||
if (client == NULL) {
|
||||
ESP_LOGW(TAG, "Client was not initialized");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!client->config->auto_reconnect) {
|
||||
ESP_LOGW(TAG, "Automatic reconnect is disabled");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return client->wait_timeout_ms;
|
||||
}
|
||||
|
||||
esp_err_t esp_websocket_client_set_reconnect_timeout(esp_websocket_client_handle_t client, int reconnect_timeout_ms)
|
||||
{
|
||||
if (client == NULL) {
|
||||
ESP_LOGW(TAG, "Client was not initialized");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (reconnect_timeout_ms <= 0) {
|
||||
ESP_LOGW(TAG, "Invalid reconnect timeout");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!client->config->auto_reconnect) {
|
||||
ESP_LOGW(TAG, "Automatic reconnect is disabled");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
client->wait_timeout_ms = reconnect_timeout_ms;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_websocket_register_events(esp_websocket_client_handle_t client,
|
||||
esp_websocket_event_id_t event,
|
||||
esp_event_handler_t event_handler,
|
||||
|
@ -6,7 +6,6 @@ set(common_component_dir ../../../../common_components)
|
||||
set(EXTRA_COMPONENT_DIRS
|
||||
../..
|
||||
"${common_component_dir}/linux_compat/esp_timer"
|
||||
"${common_component_dir}/linux_compat"
|
||||
"${common_component_dir}/linux_compat/freertos"
|
||||
$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs
|
||||
$ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
|
||||
|
@ -1,6 +1,4 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
idf_component_register(SRCS "websocket_linux.c"
|
||||
REQUIRES esp_websocket_client protocol_examples_common)
|
||||
|
||||
if(CONFIG_GCOV_ENABLED)
|
||||
|
@ -3,20 +3,13 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include <esp_log.h>
|
||||
#include "nvs_flash.h"
|
||||
#include "protocol_examples_common.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
#include "esp_websocket_client.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
|
||||
static const char *TAG = "websocket";
|
||||
@ -32,6 +25,9 @@ static void websocket_event_handler(void *handler_args, esp_event_base_t base, i
|
||||
{
|
||||
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case WEBSOCKET_EVENT_BEGIN:
|
||||
ESP_LOGI(TAG, "WEBSOCKET_EVENT_BEGIN");
|
||||
break;
|
||||
case WEBSOCKET_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "WEBSOCKET_EVENT_CONNECTED");
|
||||
break;
|
||||
@ -66,6 +62,9 @@ static void websocket_event_handler(void *handler_args, esp_event_base_t base, i
|
||||
log_error_if_nonzero("captured as transport's socket errno", data->error_handle.esp_transport_sock_errno);
|
||||
}
|
||||
break;
|
||||
case WEBSOCKET_EVENT_FINISH:
|
||||
ESP_LOGI(TAG, "WEBSOCKET_EVENT_FINISH");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -10,12 +10,6 @@ set(EMBED_FILES "") # Initialize an empty list for files to embed
|
||||
"certs/client_key.pem")
|
||||
#endif()
|
||||
|
||||
# For testing purpose we are using CA of wss://echo.websocket.events
|
||||
#if(CONFIG_WS_OVER_TLS_SERVER_AUTH)
|
||||
list(APPEND EMBED_FILES
|
||||
"certs/ca_certificate_public_domain.pem")
|
||||
#endif()
|
||||
|
||||
# Register the component with source files, include dirs, and any conditionally added embedded files
|
||||
idf_component_register(SRCS "${SRC_FILES}"
|
||||
INCLUDE_DIRS "${INCLUDE_DIRS}"
|
||||
|
@ -1,30 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
|
||||
WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||
RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
|
||||
R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
|
||||
sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
|
||||
NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
|
||||
Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
|
||||
/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
|
||||
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
|
||||
Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
|
||||
FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
|
||||
AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
|
||||
Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
|
||||
gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
|
||||
PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
|
||||
ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
|
||||
CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
|
||||
lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
|
||||
avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
|
||||
yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
|
||||
yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
|
||||
hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
|
||||
HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
|
||||
MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
|
||||
nLRbwHOoq7hHwg==
|
||||
-----END CERTIFICATE-----
|
@ -19,6 +19,7 @@
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_event.h"
|
||||
#include "protocol_examples_common.h"
|
||||
#include "esp_crt_bundle.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@ -73,6 +74,9 @@ static void websocket_event_handler(void *handler_args, esp_event_base_t base, i
|
||||
{
|
||||
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
||||
switch (event_id) {
|
||||
case WEBSOCKET_EVENT_BEGIN:
|
||||
ESP_LOGI(TAG, "WEBSOCKET_EVENT_BEGIN");
|
||||
break;
|
||||
case WEBSOCKET_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "WEBSOCKET_EVENT_CONNECTED");
|
||||
break;
|
||||
@ -121,6 +125,9 @@ static void websocket_event_handler(void *handler_args, esp_event_base_t base, i
|
||||
log_error_if_nonzero("captured as transport's socket errno", data->error_handle.esp_transport_sock_errno);
|
||||
}
|
||||
break;
|
||||
case WEBSOCKET_EVENT_FINISH:
|
||||
ESP_LOGI(TAG, "WEBSOCKET_EVENT_FINISH");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,8 +166,12 @@ static void websocket_app_start(void)
|
||||
websocket_cfg.client_key = key_start;
|
||||
websocket_cfg.client_key_len = key_end - key_start;
|
||||
#elif CONFIG_WS_OVER_TLS_SERVER_AUTH
|
||||
extern const char cacert_start[] asm("_binary_ca_certificate_public_domain_pem_start"); // CA cert of wss://echo.websocket.event, modify it if using another server
|
||||
websocket_cfg.cert_pem = cacert_start;
|
||||
// Using certificate bundle as default server certificate source
|
||||
websocket_cfg.crt_bundle_attach = esp_crt_bundle_attach;
|
||||
// If using a custom certificate it could be added to certificate bundle, added to the build similar to client certificates in this examples,
|
||||
// or read from NVS.
|
||||
/* extern const char cacert_start[] asm("ADDED_CERTIFICATE"); */
|
||||
/* websocket_cfg.cert_pem = cacert_start; */
|
||||
#endif
|
||||
|
||||
#if CONFIG_WS_OVER_TLS_SKIP_COMMON_NAME_CHECK
|
||||
|
@ -52,7 +52,7 @@ class Websocket(object):
|
||||
def run(self):
|
||||
if self.use_tls is True:
|
||||
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||
ssl_context.load_cert_chain(certfile='main/certs/server_cert.pem', keyfile='main/certs/server_key.pem')
|
||||
ssl_context.load_cert_chain(certfile='main/certs/server/server_cert.pem', keyfile='main/certs/server/server_key.pem')
|
||||
if self.client_verify is True:
|
||||
ssl_context.load_verify_locations(cafile='main/certs/ca_cert.pem')
|
||||
ssl_context.verify = ssl.CERT_REQUIRED
|
||||
|
@ -36,6 +36,8 @@ typedef enum {
|
||||
WEBSOCKET_EVENT_DATA, /*!< When receiving data from the server, possibly multiple portions of the packet */
|
||||
WEBSOCKET_EVENT_CLOSED, /*!< The connection has been closed cleanly */
|
||||
WEBSOCKET_EVENT_BEFORE_CONNECT, /*!< The event occurs before connecting */
|
||||
WEBSOCKET_EVENT_BEGIN, /*!< The event occurs once after thread creation, before event loop */
|
||||
WEBSOCKET_EVENT_FINISH, /*!< The event occurs once after event loop, before thread destruction */
|
||||
WEBSOCKET_EVENT_MAX
|
||||
} esp_websocket_event_id_t;
|
||||
|
||||
@ -118,6 +120,7 @@ typedef struct {
|
||||
bool disable_pingpong_discon; /*!< Disable auto-disconnect due to no PONG received within pingpong_timeout_sec */
|
||||
bool use_global_ca_store; /*!< Use a global ca_store for all the connections in which this bool is set. */
|
||||
esp_err_t (*crt_bundle_attach)(void *conf); /*!< Function pointer to esp_crt_bundle_attach. Enables the use of certification bundle for server verification, MBEDTLS_CERTIFICATE_BUNDLE must be enabled in menuconfig. Include esp_crt_bundle.h, and use `esp_crt_bundle_attach` here to include bundled CA certificates. */
|
||||
const char *cert_common_name; /*!< Expected common name of the server certificate */
|
||||
bool skip_cert_common_name_check;/*!< Skip any validation of server certificate CN field */
|
||||
bool keep_alive_enable; /*!< Enable keep-alive timeout */
|
||||
int keep_alive_idle; /*!< Keep-alive idle time. Default is 5 (second) */
|
||||
@ -127,6 +130,7 @@ typedef struct {
|
||||
int network_timeout_ms; /*!< Abort network operation if it is not completed after this value, in milliseconds (defaults to 10s) */
|
||||
size_t ping_interval_sec; /*!< Websocket ping interval, defaults to 10 seconds if not set */
|
||||
struct ifreq *if_name; /*!< The name of interface for data to go through. Use the default interface without setting */
|
||||
esp_transport_handle_t ext_transport; /*!< External WebSocket tcp_transport handle to the client; or if null, the client will create its own transport handle. */
|
||||
} esp_websocket_client_config_t;
|
||||
|
||||
/**
|
||||
@ -416,6 +420,29 @@ size_t esp_websocket_client_get_ping_interval_sec(esp_websocket_client_handle_t
|
||||
*/
|
||||
esp_err_t esp_websocket_client_set_ping_interval_sec(esp_websocket_client_handle_t client, size_t ping_interval_sec);
|
||||
|
||||
/**
|
||||
* @brief Get the next reconnect timeout for client. Returns -1 when client is not initialized or automatic reconnect is disabled.
|
||||
*
|
||||
* @param[in] client The client
|
||||
*
|
||||
* @return Reconnect timeout in msec
|
||||
*/
|
||||
int esp_websocket_client_get_reconnect_timeout(esp_websocket_client_handle_t client);
|
||||
|
||||
/**
|
||||
* @brief Set next reconnect timeout for client.
|
||||
*
|
||||
* Notes:
|
||||
* - Changing this value when reconnection delay is already active does not immediately affect the active delay and may have unexpected result.
|
||||
* - Good place to change this value is when handling WEBSOCKET_EVENT_DISCONNECTED or WEBSOCKET_EVENT_ERROR events.
|
||||
*
|
||||
* @param[in] client The client
|
||||
* @param[in] reconnect_timeout_ms The new timeout
|
||||
*
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t esp_websocket_client_set_reconnect_timeout(esp_websocket_client_handle_t client, int reconnect_timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Register the Websocket Events
|
||||
*
|
||||
|
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(mdns): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py mdns
|
||||
tag_format: mdns-v$version
|
||||
version: 1.3.2
|
||||
version: 1.4.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,39 @@
|
||||
# Changelog
|
||||
|
||||
## [1.4.0](https://github.com/espressif/esp-protocols/commits/mdns-v1.4.0)
|
||||
|
||||
### Major changes
|
||||
|
||||
- Fixed mdns API issues when add/remove/update records from multiple threads ([Fix services API races to directly add/remove services](https://github.com/espressif/esp-protocols/commit/8a690503))
|
||||
|
||||
### Features
|
||||
|
||||
- Unit tests for add/remove/update deleg/selfhosted services ([0660ece1](https://github.com/espressif/esp-protocols/commit/0660ece1))
|
||||
- Add console command for mdns browsing ([1e8ede33](https://github.com/espressif/esp-protocols/commit/1e8ede33))
|
||||
- Console test: set instance for service ([f107dcd1](https://github.com/espressif/esp-protocols/commit/f107dcd1))
|
||||
- Console test: add subtype for service ([ee00e97b](https://github.com/espressif/esp-protocols/commit/ee00e97b))
|
||||
- Console test: set port for (delegated) srvs ([07b79abf](https://github.com/espressif/esp-protocols/commit/07b79abf))
|
||||
- Console test: add/remove TXT recs for delegated srvs ([c9a58d73](https://github.com/espressif/esp-protocols/commit/c9a58d73))
|
||||
- Console test for changing TXT records ([6b9a6ce6](https://github.com/espressif/esp-protocols/commit/6b9a6ce6))
|
||||
- Console test for add/remove delegated service APIs ([43de7e5c](https://github.com/espressif/esp-protocols/commit/43de7e5c))
|
||||
- Console test for add/remove delegated host APIs ([ce7f326a](https://github.com/espressif/esp-protocols/commit/ce7f326a))
|
||||
- Console test for lookup service APIs ([a91ead8e](https://github.com/espressif/esp-protocols/commit/a91ead8e))
|
||||
- Add linux console functional tests ([50d059af](https://github.com/espressif/esp-protocols/commit/50d059af))
|
||||
- check if the txt items is changed when browsing ([e2f0477a](https://github.com/espressif/esp-protocols/commit/e2f0477a))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix mdns_delegate_hostname_add() to block until done ([2c1b1661](https://github.com/espressif/esp-protocols/commit/2c1b1661))
|
||||
- Fix API races when removing all services ([169405b5](https://github.com/espressif/esp-protocols/commit/169405b5))
|
||||
- Fix API races setting instance name for services ([643dc6d4](https://github.com/espressif/esp-protocols/commit/643dc6d4))
|
||||
- Fix API races while adding subtypes for services ([f9f234c4](https://github.com/espressif/esp-protocols/commit/f9f234c4))
|
||||
- Fix API races removing txt item for services ([3f97a822](https://github.com/espressif/esp-protocols/commit/3f97a822))
|
||||
- Fix API races adding txt item for services ([c62b920b](https://github.com/espressif/esp-protocols/commit/c62b920b))
|
||||
- Fix API races while setting txt for services ([a927bf3a](https://github.com/espressif/esp-protocols/commit/a927bf3a))
|
||||
- Fix API races while setting port for services ([99d5fb27](https://github.com/espressif/esp-protocols/commit/99d5fb27))
|
||||
- Fix services API races to directly add/remove services ([8a690503](https://github.com/espressif/esp-protocols/commit/8a690503))
|
||||
- Fix mdns mdns_lookup_service() to handle empty TXT ([d4da9cb0](https://github.com/espressif/esp-protocols/commit/d4da9cb0))
|
||||
|
||||
## [1.3.2](https://github.com/espressif/esp-protocols/commits/mdns-v1.3.2)
|
||||
|
||||
### Features
|
||||
|
@ -12,8 +12,9 @@ endif()
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
if(${target} STREQUAL "linux")
|
||||
set(dependencies esp_netif_linux esp_timer esp_system)
|
||||
set(srcs "mdns.c" ${MDNS_NETWORKING})
|
||||
set(dependencies esp_netif_linux esp_event)
|
||||
set(private_dependencies esp_timer console esp_system)
|
||||
set(srcs "mdns.c" ${MDNS_NETWORKING} ${MDNS_CONSOLE})
|
||||
else()
|
||||
set(dependencies lwip console esp_netif)
|
||||
set(private_dependencies esp_timer esp_wifi)
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: "1.3.2"
|
||||
version: "1.4.0"
|
||||
description: mDNS
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/mdns
|
||||
dependencies:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -9,6 +9,7 @@
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "mdns.h"
|
||||
#include "mdns_private.h"
|
||||
#include "inttypes.h"
|
||||
|
||||
static const char *ip_protocol_str[] = {"V4", "V6", "MAX"};
|
||||
|
||||
@ -18,7 +19,10 @@ static void mdns_print_results(mdns_result_t *results)
|
||||
mdns_ip_addr_t *a = NULL;
|
||||
int i = 1;
|
||||
while (r) {
|
||||
printf("%d: Interface: %s, Type: %s\n", i++, esp_netif_get_ifkey(r->esp_netif), ip_protocol_str[r->ip_protocol]);
|
||||
if (r->esp_netif) {
|
||||
printf("%d: Interface: %s, Type: %s, TTL: %" PRIu32 "\n", i++, esp_netif_get_ifkey(r->esp_netif),
|
||||
ip_protocol_str[r->ip_protocol], r->ttl);
|
||||
}
|
||||
if (r->instance_name) {
|
||||
printf(" PTR : %s\n", r->instance_name);
|
||||
}
|
||||
@ -26,7 +30,7 @@ static void mdns_print_results(mdns_result_t *results)
|
||||
printf(" SRV : %s.local:%u\n", r->hostname, r->port);
|
||||
}
|
||||
if (r->txt_count) {
|
||||
printf(" TXT : [%u] ", r->txt_count);
|
||||
printf(" TXT : [%u] ", (int)r->txt_count);
|
||||
for (size_t t = 0; t < r->txt_count; t++) {
|
||||
printf("%s=%s; ", r->txt[t].key, r->txt[t].value);
|
||||
}
|
||||
@ -516,7 +520,7 @@ static int cmd_mdns_init(int argc, char **argv)
|
||||
printf("MDNS: Hostname: %s\n", mdns_init_args.hostname->sval[0]);
|
||||
}
|
||||
|
||||
if (mdns_init_args.instance->sval[0]) {
|
||||
if (mdns_init_args.instance->count) {
|
||||
ESP_ERROR_CHECK( mdns_instance_name_set(mdns_init_args.instance->sval[0]) );
|
||||
printf("MDNS: Instance: %s\n", mdns_init_args.instance->sval[0]);
|
||||
}
|
||||
@ -693,6 +697,7 @@ static struct {
|
||||
struct arg_str *proto;
|
||||
struct arg_int *port;
|
||||
struct arg_str *instance;
|
||||
struct arg_str *host;
|
||||
struct arg_str *txt;
|
||||
struct arg_end *end;
|
||||
} mdns_add_args;
|
||||
@ -714,6 +719,11 @@ static int cmd_mdns_service_add(int argc, char **argv)
|
||||
instance = mdns_add_args.instance->sval[0];
|
||||
printf("MDNS: Service Instance: %s\n", instance);
|
||||
}
|
||||
const char *host = NULL;
|
||||
if (mdns_add_args.host->count && mdns_add_args.host->sval[0]) {
|
||||
host = mdns_add_args.host->sval[0];
|
||||
printf("MDNS: Service for delegated host: %s\n", host);
|
||||
}
|
||||
mdns_txt_item_t *items = NULL;
|
||||
if (mdns_add_args.txt->count) {
|
||||
items = _convert_items(mdns_add_args.txt->sval, mdns_add_args.txt->count);
|
||||
@ -724,7 +734,8 @@ static int cmd_mdns_service_add(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK( mdns_service_add(instance, mdns_add_args.service->sval[0], mdns_add_args.proto->sval[0], mdns_add_args.port->ival[0], items, mdns_add_args.txt->count) );
|
||||
ESP_ERROR_CHECK( mdns_service_add_for_host(instance, mdns_add_args.service->sval[0], mdns_add_args.proto->sval[0],
|
||||
host, mdns_add_args.port->ival[0], items, mdns_add_args.txt->count) );
|
||||
free(items);
|
||||
return 0;
|
||||
}
|
||||
@ -735,6 +746,7 @@ static void register_mdns_service_add(void)
|
||||
mdns_add_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
||||
mdns_add_args.port = arg_int1(NULL, NULL, "<port>", "Service Port");
|
||||
mdns_add_args.instance = arg_str0("i", "instance", "<instance>", "Instance name");
|
||||
mdns_add_args.host = arg_str0("h", "host", "<hostname>", "Service for this (delegated) host");
|
||||
mdns_add_args.txt = arg_strn(NULL, NULL, "item", 0, 30, "TXT Items (name=value)");
|
||||
mdns_add_args.end = arg_end(2);
|
||||
|
||||
@ -750,8 +762,10 @@ static void register_mdns_service_add(void)
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_str *instance;
|
||||
struct arg_str *service;
|
||||
struct arg_str *proto;
|
||||
struct arg_str *host;
|
||||
struct arg_end *end;
|
||||
} mdns_remove_args;
|
||||
|
||||
@ -768,7 +782,16 @@ static int cmd_mdns_service_remove(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK( mdns_service_remove(mdns_remove_args.service->sval[0], mdns_remove_args.proto->sval[0]) );
|
||||
const char *instance = NULL;
|
||||
if (mdns_remove_args.instance->count && mdns_remove_args.instance->sval[0]) {
|
||||
instance = mdns_remove_args.instance->sval[0];
|
||||
}
|
||||
const char *host = NULL;
|
||||
if (mdns_remove_args.host->count && mdns_remove_args.host->sval[0]) {
|
||||
host = mdns_remove_args.host->sval[0];
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK( mdns_service_remove_for_host(instance, mdns_remove_args.service->sval[0], mdns_remove_args.proto->sval[0], host) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -776,7 +799,9 @@ static void register_mdns_service_remove(void)
|
||||
{
|
||||
mdns_remove_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
||||
mdns_remove_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
||||
mdns_remove_args.end = arg_end(2);
|
||||
mdns_remove_args.host = arg_str0("h", "host", "<hostname>", "Service for this (delegated) host");
|
||||
mdns_remove_args.instance = arg_str0("i", "instance", "<instance>", "Instance name");
|
||||
mdns_remove_args.end = arg_end(4);
|
||||
|
||||
const esp_console_cmd_t cmd_remove = {
|
||||
.command = "mdns_service_remove",
|
||||
@ -793,6 +818,8 @@ static struct {
|
||||
struct arg_str *service;
|
||||
struct arg_str *proto;
|
||||
struct arg_str *instance;
|
||||
struct arg_str *host;
|
||||
struct arg_str *old_instance;
|
||||
struct arg_end *end;
|
||||
} mdns_service_instance_set_args;
|
||||
|
||||
@ -808,8 +835,20 @@ static int cmd_mdns_service_instance_set(int argc, char **argv)
|
||||
printf("ERROR: Bad arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
const char *host = NULL;
|
||||
if (mdns_service_instance_set_args.host->count && mdns_service_instance_set_args.host->sval[0]) {
|
||||
host = mdns_service_instance_set_args.host->sval[0];
|
||||
}
|
||||
const char *old_instance = NULL;
|
||||
if (mdns_service_instance_set_args.old_instance->count && mdns_service_instance_set_args.old_instance->sval[0]) {
|
||||
old_instance = mdns_service_instance_set_args.old_instance->sval[0];
|
||||
}
|
||||
esp_err_t err = mdns_service_instance_name_set_for_host(old_instance, mdns_service_instance_set_args.service->sval[0], mdns_service_instance_set_args.proto->sval[0], host, mdns_service_instance_set_args.instance->sval[0]);
|
||||
if (err != ESP_OK) {
|
||||
printf("mdns_service_instance_name_set_for_host() failed with %s\n", esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK( mdns_service_instance_name_set(mdns_service_instance_set_args.service->sval[0], mdns_service_instance_set_args.proto->sval[0], mdns_service_instance_set_args.instance->sval[0]) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -818,7 +857,9 @@ static void register_mdns_service_instance_set(void)
|
||||
mdns_service_instance_set_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
||||
mdns_service_instance_set_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
||||
mdns_service_instance_set_args.instance = arg_str1(NULL, NULL, "<instance>", "Instance name");
|
||||
mdns_service_instance_set_args.end = arg_end(2);
|
||||
mdns_service_instance_set_args.host = arg_str0("h", "host", "<hostname>", "Service for this (delegated) host");
|
||||
mdns_service_instance_set_args.old_instance = arg_str0("i", "old_instance", "<old_instance>", "Instance name before update");
|
||||
mdns_service_instance_set_args.end = arg_end(4);
|
||||
|
||||
const esp_console_cmd_t cmd_add = {
|
||||
.command = "mdns_service_instance_set",
|
||||
@ -835,6 +876,8 @@ static struct {
|
||||
struct arg_str *service;
|
||||
struct arg_str *proto;
|
||||
struct arg_int *port;
|
||||
struct arg_str *host;
|
||||
struct arg_str *instance;
|
||||
struct arg_end *end;
|
||||
} mdns_service_port_set_args;
|
||||
|
||||
@ -851,7 +894,19 @@ static int cmd_mdns_service_port_set(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK( mdns_service_port_set(mdns_service_port_set_args.service->sval[0], mdns_service_port_set_args.proto->sval[0], mdns_service_port_set_args.port->ival[0]) );
|
||||
const char *host = NULL;
|
||||
if (mdns_service_port_set_args.host->count && mdns_service_port_set_args.host->sval[0]) {
|
||||
host = mdns_service_port_set_args.host->sval[0];
|
||||
}
|
||||
const char *instance = NULL;
|
||||
if (mdns_service_port_set_args.instance->count && mdns_service_port_set_args.instance->sval[0]) {
|
||||
instance = mdns_service_port_set_args.instance->sval[0];
|
||||
}
|
||||
esp_err_t err = mdns_service_port_set_for_host(instance, mdns_service_port_set_args.service->sval[0], mdns_service_port_set_args.proto->sval[0], host, mdns_service_port_set_args.port->ival[0]);
|
||||
if (err != ESP_OK) {
|
||||
printf("mdns_service_port_set_for_host() failed with %s\n", esp_err_to_name(err));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -860,6 +915,8 @@ static void register_mdns_service_port_set(void)
|
||||
mdns_service_port_set_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
||||
mdns_service_port_set_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
||||
mdns_service_port_set_args.port = arg_int1(NULL, NULL, "<port>", "Service Port");
|
||||
mdns_service_port_set_args.host = arg_str0("h", "host", "<hostname>", "Service for this (delegated) host");
|
||||
mdns_service_port_set_args.instance = arg_str0("i", "instance", "<instance>", "Instance name");
|
||||
mdns_service_port_set_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t cmd_add = {
|
||||
@ -876,6 +933,8 @@ static void register_mdns_service_port_set(void)
|
||||
static struct {
|
||||
struct arg_str *service;
|
||||
struct arg_str *proto;
|
||||
struct arg_str *instance;
|
||||
struct arg_str *host;
|
||||
struct arg_str *txt;
|
||||
struct arg_end *end;
|
||||
} mdns_txt_replace_args;
|
||||
@ -893,7 +952,16 @@ static int cmd_mdns_service_txt_replace(int argc, char **argv)
|
||||
printf("ERROR: Bad arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *instance = NULL;
|
||||
if (mdns_txt_replace_args.instance->count && mdns_txt_replace_args.instance->sval[0]) {
|
||||
instance = mdns_txt_replace_args.instance->sval[0];
|
||||
printf("MDNS: Service Instance: %s\n", instance);
|
||||
}
|
||||
const char *host = NULL;
|
||||
if (mdns_txt_replace_args.host->count && mdns_txt_replace_args.host->sval[0]) {
|
||||
host = mdns_txt_replace_args.host->sval[0];
|
||||
printf("MDNS: Service for delegated host: %s\n", host);
|
||||
}
|
||||
if (mdns_txt_replace_args.txt->count) {
|
||||
items = _convert_items(mdns_txt_replace_args.txt->sval, mdns_txt_replace_args.txt->count);
|
||||
if (!items) {
|
||||
@ -902,7 +970,7 @@ static int cmd_mdns_service_txt_replace(int argc, char **argv)
|
||||
|
||||
}
|
||||
}
|
||||
ESP_ERROR_CHECK( mdns_service_txt_set(mdns_txt_replace_args.service->sval[0], mdns_txt_replace_args.proto->sval[0], items, mdns_txt_replace_args.txt->count) );
|
||||
ESP_ERROR_CHECK( mdns_service_txt_set_for_host(instance, mdns_txt_replace_args.service->sval[0], mdns_txt_replace_args.proto->sval[0], host, items, mdns_txt_replace_args.txt->count) );
|
||||
free(items);
|
||||
return 0;
|
||||
}
|
||||
@ -911,8 +979,10 @@ static void register_mdns_service_txt_replace(void)
|
||||
{
|
||||
mdns_txt_replace_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
||||
mdns_txt_replace_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
||||
mdns_txt_replace_args.instance = arg_str0("i", "instance", "<instance>", "Instance name");
|
||||
mdns_txt_replace_args.host = arg_str0("h", "host", "<hostname>", "Service for this (delegated) host");
|
||||
mdns_txt_replace_args.txt = arg_strn(NULL, NULL, "item", 0, 30, "TXT Items (name=value)");
|
||||
mdns_txt_replace_args.end = arg_end(2);
|
||||
mdns_txt_replace_args.end = arg_end(5);
|
||||
|
||||
const esp_console_cmd_t cmd_txt_set = {
|
||||
.command = "mdns_service_txt_replace",
|
||||
@ -928,6 +998,8 @@ static void register_mdns_service_txt_replace(void)
|
||||
static struct {
|
||||
struct arg_str *service;
|
||||
struct arg_str *proto;
|
||||
struct arg_str *instance;
|
||||
struct arg_str *host;
|
||||
struct arg_str *var;
|
||||
struct arg_str *value;
|
||||
struct arg_end *end;
|
||||
@ -945,8 +1017,18 @@ static int cmd_mdns_service_txt_set(int argc, char **argv)
|
||||
printf("ERROR: Bad arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
const char *instance = NULL;
|
||||
if (mdns_txt_set_args.instance->count && mdns_txt_set_args.instance->sval[0]) {
|
||||
instance = mdns_txt_set_args.instance->sval[0];
|
||||
printf("MDNS: Service Instance: %s\n", instance);
|
||||
}
|
||||
const char *host = NULL;
|
||||
if (mdns_txt_set_args.host->count && mdns_txt_set_args.host->sval[0]) {
|
||||
host = mdns_txt_set_args.host->sval[0];
|
||||
printf("MDNS: Service for delegated host: %s\n", host);
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK( mdns_service_txt_item_set(mdns_txt_set_args.service->sval[0], mdns_txt_set_args.proto->sval[0], mdns_txt_set_args.var->sval[0], mdns_txt_set_args.value->sval[0]) );
|
||||
ESP_ERROR_CHECK( mdns_service_txt_item_set_for_host(instance, mdns_txt_set_args.service->sval[0], mdns_txt_set_args.proto->sval[0], host, mdns_txt_set_args.var->sval[0], mdns_txt_set_args.value->sval[0]) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -956,7 +1038,9 @@ static void register_mdns_service_txt_set(void)
|
||||
mdns_txt_set_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
||||
mdns_txt_set_args.var = arg_str1(NULL, NULL, "<var>", "Item Name");
|
||||
mdns_txt_set_args.value = arg_str1(NULL, NULL, "<value>", "Item Value");
|
||||
mdns_txt_set_args.end = arg_end(2);
|
||||
mdns_txt_set_args.instance = arg_str0("i", "instance", "<instance>", "Instance name");
|
||||
mdns_txt_set_args.host = arg_str0("h", "host", "<hostname>", "Service for this (delegated) host");
|
||||
mdns_txt_set_args.end = arg_end(6);
|
||||
|
||||
const esp_console_cmd_t cmd_txt_set = {
|
||||
.command = "mdns_service_txt_set",
|
||||
@ -973,6 +1057,8 @@ static struct {
|
||||
struct arg_str *service;
|
||||
struct arg_str *proto;
|
||||
struct arg_str *var;
|
||||
struct arg_str *instance;
|
||||
struct arg_str *host;
|
||||
struct arg_end *end;
|
||||
} mdns_txt_remove_args;
|
||||
|
||||
@ -988,8 +1074,15 @@ static int cmd_mdns_service_txt_remove(int argc, char **argv)
|
||||
printf("ERROR: Bad arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK( mdns_service_txt_item_remove(mdns_txt_remove_args.service->sval[0], mdns_txt_remove_args.proto->sval[0], mdns_txt_remove_args.var->sval[0]) );
|
||||
const char *instance = NULL;
|
||||
if (mdns_txt_remove_args.instance->count && mdns_txt_remove_args.instance->sval[0]) {
|
||||
instance = mdns_txt_remove_args.instance->sval[0];
|
||||
}
|
||||
const char *host = NULL;
|
||||
if (mdns_txt_remove_args.host->count && mdns_txt_remove_args.host->sval[0]) {
|
||||
host = mdns_txt_remove_args.host->sval[0];
|
||||
}
|
||||
ESP_ERROR_CHECK( mdns_service_txt_item_remove_for_host(instance, mdns_txt_remove_args.service->sval[0], mdns_txt_remove_args.proto->sval[0], host, mdns_txt_remove_args.var->sval[0]) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -998,6 +1091,8 @@ static void register_mdns_service_txt_remove(void)
|
||||
mdns_txt_remove_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
||||
mdns_txt_remove_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
||||
mdns_txt_remove_args.var = arg_str1(NULL, NULL, "<var>", "Item Name");
|
||||
mdns_txt_remove_args.instance = arg_str0("i", "instance", "<instance>", "Instance name");
|
||||
mdns_txt_remove_args.host = arg_str0("h", "host", "<hostname>", "Service for this (delegated) host");
|
||||
mdns_txt_remove_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t cmd_txt_remove = {
|
||||
@ -1030,6 +1125,294 @@ static void register_mdns_service_remove_all(void)
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_free) );
|
||||
}
|
||||
|
||||
#define MDNS_MAX_LOOKUP_RESULTS CONFIG_MDNS_MAX_SERVICES
|
||||
|
||||
static struct {
|
||||
struct arg_str *instance;
|
||||
struct arg_str *service;
|
||||
struct arg_str *proto;
|
||||
struct arg_lit *delegated;
|
||||
struct arg_end *end;
|
||||
} mdns_lookup_service_args;
|
||||
|
||||
static esp_err_t lookup_service(const char *instance, const char *service, const char *proto, size_t max_results,
|
||||
mdns_result_t **result, bool delegated)
|
||||
{
|
||||
if (delegated) {
|
||||
return mdns_lookup_delegated_service(instance, service, proto, max_results, result);
|
||||
}
|
||||
return mdns_lookup_selfhosted_service(instance, service, proto, max_results, result);
|
||||
}
|
||||
|
||||
static int cmd_mdns_lookup_service(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **) &mdns_lookup_service_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, mdns_lookup_service_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!mdns_lookup_service_args.instance->sval[0] || !mdns_lookup_service_args.service->sval[0] || !mdns_lookup_service_args.proto->sval[0]) {
|
||||
printf("ERROR: Bad arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
mdns_result_t *results = NULL;
|
||||
esp_err_t err = lookup_service(mdns_lookup_service_args.instance->count ? mdns_lookup_service_args.instance->sval[0] : NULL,
|
||||
mdns_lookup_service_args.service->sval[0], mdns_lookup_service_args.proto->sval[0],
|
||||
MDNS_MAX_LOOKUP_RESULTS, &results, mdns_lookup_service_args.delegated->count);
|
||||
if (err) {
|
||||
printf("Service lookup failed\n");
|
||||
return 1;
|
||||
}
|
||||
if (!results) {
|
||||
printf("No results found!\n");
|
||||
return 0;
|
||||
}
|
||||
mdns_print_results(results);
|
||||
mdns_query_results_free(results);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_mdns_lookup_service(void)
|
||||
{
|
||||
mdns_lookup_service_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
||||
mdns_lookup_service_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
||||
mdns_lookup_service_args.instance = arg_str0("i", "instance", "<instance>", "Instance name");
|
||||
mdns_lookup_service_args.delegated = arg_lit0("d", "delegated", "Lookup delegated services");
|
||||
mdns_lookup_service_args.end = arg_end(4);
|
||||
|
||||
const esp_console_cmd_t cmd_lookup_service = {
|
||||
.command = "mdns_service_lookup",
|
||||
.help = "Lookup registered service",
|
||||
.hint = NULL,
|
||||
.func = &cmd_mdns_lookup_service,
|
||||
.argtable = &mdns_lookup_service_args
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_lookup_service) );
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_str *hostname;
|
||||
struct arg_str *address;
|
||||
struct arg_end *end;
|
||||
} mdns_delegate_host_args;
|
||||
|
||||
static int cmd_mdns_delegate_host(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **) &mdns_delegate_host_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, mdns_delegate_host_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!mdns_delegate_host_args.hostname->sval[0] || !mdns_delegate_host_args.address->sval[0]) {
|
||||
printf("ERROR: Bad arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
mdns_ip_addr_t addr = { .next = NULL};
|
||||
esp_netif_str_to_ip4(mdns_delegate_host_args.address->sval[0], &addr.addr.u_addr.ip4);
|
||||
addr.addr.type = ESP_IPADDR_TYPE_V4;
|
||||
|
||||
esp_err_t err = mdns_delegate_hostname_add(mdns_delegate_host_args.hostname->sval[0], &addr);
|
||||
if (err) {
|
||||
printf("mdns_delegate_hostname_add() failed\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_mdns_delegate_host(void)
|
||||
{
|
||||
mdns_delegate_host_args.hostname = arg_str1(NULL, NULL, "<hostname>", "Delegated hostname");
|
||||
mdns_delegate_host_args.address = arg_str1(NULL, NULL, "<address>", "Delegated hosts address");
|
||||
mdns_delegate_host_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t cmd_delegate_host = {
|
||||
.command = "mdns_delegate_host",
|
||||
.help = "Add delegated hostname",
|
||||
.hint = NULL,
|
||||
.func = &cmd_mdns_delegate_host,
|
||||
.argtable = &mdns_delegate_host_args
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_delegate_host) );
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_str *hostname;
|
||||
struct arg_end *end;
|
||||
} mdns_undelegate_host_args;
|
||||
|
||||
static int cmd_mdns_undelegate_host(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **) &mdns_undelegate_host_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, mdns_undelegate_host_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!mdns_undelegate_host_args.hostname->sval[0]) {
|
||||
printf("ERROR: Bad arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mdns_delegate_hostname_remove(mdns_undelegate_host_args.hostname->sval[0]) != ESP_OK) {
|
||||
printf("mdns_delegate_hostname_remove() failed\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_mdns_undelegate_host(void)
|
||||
{
|
||||
mdns_undelegate_host_args.hostname = arg_str1(NULL, NULL, "<hostname>", "Delegated hostname");
|
||||
mdns_undelegate_host_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t cmd_undelegate_host = {
|
||||
.command = "mdns_undelegate_host",
|
||||
.help = "Remove delegated hostname",
|
||||
.hint = NULL,
|
||||
.func = &cmd_mdns_undelegate_host,
|
||||
.argtable = &mdns_undelegate_host_args
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_undelegate_host) );
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_str *service;
|
||||
struct arg_str *proto;
|
||||
struct arg_str *sub;
|
||||
struct arg_str *instance;
|
||||
struct arg_str *host;
|
||||
struct arg_end *end;
|
||||
} mdns_service_subtype_args;
|
||||
|
||||
static int cmd_mdns_service_subtype(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **) &mdns_service_subtype_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, mdns_service_subtype_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!mdns_service_subtype_args.service->sval[0] || !mdns_service_subtype_args.proto->sval[0] || !mdns_service_subtype_args.sub->sval[0]) {
|
||||
printf("ERROR: Bad arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
const char *instance = NULL;
|
||||
if (mdns_service_subtype_args.instance->count && mdns_service_subtype_args.instance->sval[0]) {
|
||||
instance = mdns_service_subtype_args.instance->sval[0];
|
||||
}
|
||||
const char *host = NULL;
|
||||
if (mdns_service_subtype_args.host->count && mdns_service_subtype_args.host->sval[0]) {
|
||||
host = mdns_service_subtype_args.host->sval[0];
|
||||
}
|
||||
ESP_ERROR_CHECK( mdns_service_subtype_add_for_host(instance, mdns_service_subtype_args.service->sval[0], mdns_service_subtype_args.proto->sval[0], host, mdns_service_subtype_args.sub->sval[0]) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_mdns_service_subtype_set(void)
|
||||
{
|
||||
mdns_service_subtype_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
||||
mdns_service_subtype_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
||||
mdns_service_subtype_args.sub = arg_str1(NULL, NULL, "<sub>", "Subtype");
|
||||
mdns_service_subtype_args.instance = arg_str0("i", "instance", "<instance>", "Instance name");
|
||||
mdns_service_subtype_args.host = arg_str0("h", "host", "<hostname>", "Service for this (delegated) host");
|
||||
mdns_service_subtype_args.end = arg_end(5);
|
||||
|
||||
const esp_console_cmd_t cmd_service_sub = {
|
||||
.command = "mdns_service_subtype",
|
||||
.help = "Adds subtype for service",
|
||||
.hint = NULL,
|
||||
.func = &cmd_mdns_service_subtype,
|
||||
.argtable = &mdns_service_subtype_args
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_service_sub) );
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_str *service;
|
||||
struct arg_str *proto;
|
||||
struct arg_end *end;
|
||||
} mdns_browse_args;
|
||||
|
||||
static void mdns_browse_notifier(mdns_result_t *result)
|
||||
{
|
||||
if (result) {
|
||||
mdns_print_results(result);
|
||||
}
|
||||
}
|
||||
|
||||
static int cmd_mdns_browse(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **) &mdns_browse_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, mdns_browse_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!mdns_browse_args.service->sval[0] || !mdns_browse_args.proto->sval[0]) {
|
||||
printf("ERROR: Bad arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
mdns_browse_t *handle = mdns_browse_new(mdns_browse_args.service->sval[0], mdns_browse_args.proto->sval[0], mdns_browse_notifier);
|
||||
return handle ? 0 : 1;
|
||||
}
|
||||
|
||||
static void register_mdns_browse(void)
|
||||
{
|
||||
mdns_browse_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
||||
mdns_browse_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
||||
mdns_browse_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t cmd_browse = {
|
||||
.command = "mdns_browse",
|
||||
.help = "Start browsing",
|
||||
.hint = NULL,
|
||||
.func = &cmd_mdns_browse,
|
||||
.argtable = &mdns_browse_args
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_browse) );
|
||||
}
|
||||
|
||||
static int cmd_mdns_browse_del(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **) &mdns_browse_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, mdns_browse_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!mdns_browse_args.service->sval[0] || !mdns_browse_args.proto->sval[0]) {
|
||||
printf("ERROR: Bad arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
esp_err_t err = mdns_browse_delete(mdns_browse_args.service->sval[0], mdns_browse_args.proto->sval[0]);
|
||||
return err == ESP_OK ? 0 : 1;
|
||||
}
|
||||
|
||||
static void register_mdns_browse_del(void)
|
||||
{
|
||||
mdns_browse_args.service = arg_str1(NULL, NULL, "<service>", "MDNS Service");
|
||||
mdns_browse_args.proto = arg_str1(NULL, NULL, "<proto>", "IP Protocol");
|
||||
mdns_browse_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t cmd_browse_del = {
|
||||
.command = "mdns_browse_del",
|
||||
.help = "Stop browsing",
|
||||
.hint = NULL,
|
||||
.func = &cmd_mdns_browse_del,
|
||||
.argtable = &mdns_browse_args
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_browse_del) );
|
||||
}
|
||||
|
||||
void mdns_console_register(void)
|
||||
{
|
||||
register_mdns_init();
|
||||
@ -1045,6 +1428,14 @@ void mdns_console_register(void)
|
||||
register_mdns_service_txt_remove();
|
||||
register_mdns_service_remove_all();
|
||||
|
||||
register_mdns_lookup_service();
|
||||
register_mdns_delegate_host();
|
||||
register_mdns_undelegate_host();
|
||||
register_mdns_service_subtype_set();
|
||||
|
||||
register_mdns_browse();
|
||||
register_mdns_browse_del();
|
||||
|
||||
#ifdef CONFIG_LWIP_IPV4
|
||||
register_mdns_query_a();
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -187,15 +187,6 @@ typedef enum {
|
||||
ACTION_SYSTEM_EVENT,
|
||||
ACTION_HOSTNAME_SET,
|
||||
ACTION_INSTANCE_SET,
|
||||
ACTION_SERVICE_ADD,
|
||||
ACTION_SERVICE_DEL,
|
||||
ACTION_SERVICE_INSTANCE_SET,
|
||||
ACTION_SERVICE_PORT_SET,
|
||||
ACTION_SERVICE_TXT_REPLACE,
|
||||
ACTION_SERVICE_TXT_SET,
|
||||
ACTION_SERVICE_TXT_DEL,
|
||||
ACTION_SERVICE_SUBTYPE_ADD,
|
||||
ACTION_SERVICES_CLEAR,
|
||||
ACTION_SEARCH_ADD,
|
||||
ACTION_SEARCH_SEND,
|
||||
ACTION_SEARCH_END,
|
||||
@ -446,41 +437,6 @@ typedef struct {
|
||||
mdns_if_t interface;
|
||||
mdns_event_actions_t event_action;
|
||||
} sys_event;
|
||||
struct {
|
||||
mdns_srv_item_t *service;
|
||||
} srv_add;
|
||||
struct {
|
||||
char *instance;
|
||||
char *service;
|
||||
char *proto;
|
||||
char *hostname;
|
||||
} srv_del;
|
||||
struct {
|
||||
mdns_srv_item_t *service;
|
||||
char *instance;
|
||||
} srv_instance;
|
||||
struct {
|
||||
mdns_srv_item_t *service;
|
||||
uint16_t port;
|
||||
} srv_port;
|
||||
struct {
|
||||
mdns_srv_item_t *service;
|
||||
mdns_txt_linked_item_t *txt;
|
||||
} srv_txt_replace;
|
||||
struct {
|
||||
mdns_srv_item_t *service;
|
||||
char *key;
|
||||
char *value;
|
||||
uint8_t value_len;
|
||||
} srv_txt_set;
|
||||
struct {
|
||||
mdns_srv_item_t *service;
|
||||
char *key;
|
||||
} srv_txt_del;
|
||||
struct {
|
||||
mdns_srv_item_t *service;
|
||||
char *subtype;
|
||||
} srv_subtype_add;
|
||||
struct {
|
||||
mdns_search_once_t *search;
|
||||
} search_add;
|
||||
|
@ -1,11 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../.." "../../../../common_components/linux_compat")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
set(COMPONENTS main esp_netif_linux)
|
||||
if(${IDF_TARGET} STREQUAL "linux")
|
||||
set(EXTRA_COMPONENT_DIRS "../../../../common_components/linux_compat")
|
||||
set(COMPONENTS main)
|
||||
endif()
|
||||
|
||||
project(mdns_host)
|
||||
|
||||
# Enable sanitizers for mdns implementation
|
||||
# Enable sanitizers only without console (we'd see some leaks on argtable when console exits)
|
||||
if(NOT CONFIG_TEST_CONSOLE AND CONFIG_IDF_TARGET_LINUX)
|
||||
idf_component_get_property(mdns mdns COMPONENT_LIB)
|
||||
target_link_options(${mdns} INTERFACE -fsanitize=address -fsanitize=undefined)
|
||||
endif()
|
||||
|
@ -1,2 +1,8 @@
|
||||
idf_component_register(SRCS esp_netif_linux.c
|
||||
INCLUDE_DIRS include $ENV{IDF_PATH}/components/esp_netif/include)
|
||||
idf_build_get_property(idf_target IDF_TARGET)
|
||||
if(${IDF_TARGET} STREQUAL "linux")
|
||||
idf_component_register(SRCS esp_netif_linux.c
|
||||
INCLUDE_DIRS include $ENV{IDF_PATH}/components/esp_netif/include
|
||||
REQUIRES esp_event)
|
||||
else()
|
||||
idf_component_register()
|
||||
endif()
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -15,9 +15,12 @@
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if.h>
|
||||
#include "esp_netif_types.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define MAX_NETIFS 4
|
||||
|
||||
static const char *TAG = "esp_netif_linux";
|
||||
|
||||
static esp_netif_t *s_netif_list[MAX_NETIFS] = { 0 };
|
||||
|
||||
struct esp_netif_obj {
|
||||
@ -50,6 +53,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) {
|
||||
ESP_LOGD(TAG, "AF_INET4: %s: %s\n", tmp->ifa_name, addr);
|
||||
memcpy(&ip_info->ip.addr, &pAddr->sin_addr, 4);
|
||||
}
|
||||
}
|
||||
@ -103,7 +107,7 @@ esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if
|
||||
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);
|
||||
ESP_LOGD(TAG, "AF_INET6: %s: %s\n", tmp->ifa_name, addr);
|
||||
memcpy(if_ip6->addr, &pAddr->sin6_addr, 4 * 4);
|
||||
break;
|
||||
}
|
||||
@ -173,3 +177,21 @@ void esp_netif_destroy(esp_netif_t *esp_netif)
|
||||
}
|
||||
free(esp_netif);
|
||||
}
|
||||
|
||||
const char *esp_netif_get_ifkey(esp_netif_t *esp_netif)
|
||||
{
|
||||
return esp_netif->if_key;
|
||||
}
|
||||
|
||||
esp_err_t esp_netif_str_to_ip4(const char *src, esp_ip4_addr_t *dst)
|
||||
{
|
||||
if (src == NULL || dst == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
struct in_addr addr;
|
||||
if (inet_pton(AF_INET, src, &addr) != 1) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
dst->addr = addr.s_addr;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
130
components/mdns/tests/host_test/dnsfixture.py
Normal file
130
components/mdns/tests/host_test/dnsfixture.py
Normal file
@ -0,0 +1,130 @@
|
||||
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import logging
|
||||
import re
|
||||
import socket
|
||||
import sys
|
||||
|
||||
import dns.message
|
||||
import dns.query
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.resolver
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DnsPythonWrapper:
|
||||
def __init__(self, server='224.0.0.251', port=5353, retries=3):
|
||||
self.server = server
|
||||
self.port = port
|
||||
self.retries = retries
|
||||
|
||||
def send_and_receive_query(self, query, timeout=3):
|
||||
logger.info(f'Sending DNS query to {self.server}:{self.port}')
|
||||
try:
|
||||
# Create a UDP socket
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
|
||||
sock.settimeout(timeout)
|
||||
|
||||
# Send the DNS query
|
||||
query_data = query.to_wire()
|
||||
sock.sendto(query_data, (self.server, self.port))
|
||||
|
||||
# Receive the DNS response
|
||||
response_data, _ = sock.recvfrom(512) # 512 bytes is the typical size for a DNS response
|
||||
|
||||
# Parse the response
|
||||
response = dns.message.from_wire(response_data)
|
||||
|
||||
return response
|
||||
|
||||
except socket.timeout as e:
|
||||
logger.warning(f'DNS query timed out: {e}')
|
||||
return None
|
||||
except dns.exception.DNSException as e:
|
||||
logger.error(f'DNS query failed: {e}')
|
||||
return None
|
||||
|
||||
def run_query(self, name, query_type='PTR', timeout=3):
|
||||
logger.info(f'Running DNS query for {name} with type {query_type}')
|
||||
query = dns.message.make_query(name, dns.rdatatype.from_text(query_type), dns.rdataclass.IN)
|
||||
|
||||
# Print the DNS question section
|
||||
logger.info(f'DNS question section: {query.question}')
|
||||
|
||||
# Send and receive the DNS query
|
||||
response = None
|
||||
for attempt in range(1, self.retries + 1):
|
||||
logger.info(f'Attempt {attempt}/{self.retries}')
|
||||
response = self.send_and_receive_query(query, timeout)
|
||||
if response:
|
||||
break
|
||||
|
||||
if response:
|
||||
logger.info(f'DNS query response:\n{response}')
|
||||
else:
|
||||
logger.warning('No response received or response was invalid.')
|
||||
|
||||
return response
|
||||
|
||||
def parse_answer_section(self, response, query_type):
|
||||
answers = []
|
||||
if response:
|
||||
for answer in response.answer:
|
||||
if dns.rdatatype.to_text(answer.rdtype) == query_type:
|
||||
for item in answer.items:
|
||||
full_answer = (
|
||||
f'{answer.name} {answer.ttl} '
|
||||
f'{dns.rdataclass.to_text(answer.rdclass)} '
|
||||
f'{dns.rdatatype.to_text(answer.rdtype)} '
|
||||
f'{item.to_text()}'
|
||||
)
|
||||
answers.append(full_answer)
|
||||
return answers
|
||||
|
||||
def check_record(self, name, query_type, expected=True, expect=None):
|
||||
output = self.run_query(name, query_type=query_type)
|
||||
answers = self.parse_answer_section(output, query_type)
|
||||
logger.info(f'answers: {answers}')
|
||||
if expect is None:
|
||||
expect = name
|
||||
if expected:
|
||||
assert any(expect in answer for answer in answers), f"Expected record '{expect}' not found in answer section"
|
||||
else:
|
||||
assert not any(expect in answer for answer in answers), f"Unexpected record '{expect}' found in answer section"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 3:
|
||||
print('Usage: python dns_fixture.py <query_type> <name>')
|
||||
sys.exit(1)
|
||||
|
||||
query_type = sys.argv[1]
|
||||
name = sys.argv[2]
|
||||
ip_only = len(sys.argv) > 3 and sys.argv[3] == '--ip_only'
|
||||
if ip_only:
|
||||
logger.setLevel(logging.WARNING)
|
||||
|
||||
dns_wrapper = DnsPythonWrapper()
|
||||
if query_type == 'X' and '.' in name:
|
||||
# Sends an IPv4 reverse query
|
||||
reversed_ip = '.'.join(reversed(name.split('.')))
|
||||
name = f'{reversed_ip}.in-addr.arpa'
|
||||
query_type = 'PTR'
|
||||
response = dns_wrapper.run_query(name, query_type=query_type)
|
||||
answers = dns_wrapper.parse_answer_section(response, query_type)
|
||||
|
||||
if answers:
|
||||
for answer in answers:
|
||||
logger.info(f'DNS query response: {answer}')
|
||||
if ip_only:
|
||||
ipv4_pattern = re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b')
|
||||
ipv4_addresses = ipv4_pattern.findall(answer)
|
||||
if ipv4_addresses:
|
||||
print(f"{', '.join(ipv4_addresses)}")
|
||||
else:
|
||||
logger.info(f'No response for {name} with query type {query_type}')
|
||||
exit(9) # Same as dig timeout
|
@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
REQUIRES mdns)
|
||||
REQUIRES mdns console nvs_flash)
|
||||
|
@ -12,4 +12,10 @@ menu "Test Configuration"
|
||||
help
|
||||
Name/ID if the network interface on which we run the mDNS host test
|
||||
|
||||
config TEST_CONSOLE
|
||||
bool "Start console"
|
||||
default n
|
||||
help
|
||||
Test uses esp_console for interactive testing.
|
||||
|
||||
endmenu
|
||||
|
7
components/mdns/tests/host_test/main/idf_component.yml
Normal file
7
components/mdns/tests/host_test/main/idf_component.yml
Normal file
@ -0,0 +1,7 @@
|
||||
dependencies:
|
||||
idf: ">=5.0"
|
||||
espressif/mdns:
|
||||
version: "^1.0.0"
|
||||
override_path: "../../.."
|
||||
protocol_examples_common:
|
||||
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
|
@ -1,16 +1,30 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "mdns.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_console.h"
|
||||
#include "mdns.h"
|
||||
#include "mdns_console.h"
|
||||
|
||||
static const char *TAG = "mdns-test";
|
||||
|
||||
static void mdns_test_app(esp_netif_t *interface);
|
||||
|
||||
#ifdef CONFIG_TEST_CONSOLE
|
||||
static EventGroupHandle_t s_exit_signal = NULL;
|
||||
|
||||
static int exit_console(int argc, char **argv)
|
||||
{
|
||||
xEventGroupSetBits(s_exit_signal, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
static void query_mdns_host(const char *host_name)
|
||||
{
|
||||
ESP_LOGI(TAG, "Query A: %s.local", host_name);
|
||||
@ -30,37 +44,83 @@ static void query_mdns_host(const char *host_name)
|
||||
|
||||
ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr));
|
||||
}
|
||||
#endif // TEST_CONSOLE
|
||||
|
||||
#ifndef CONFIG_IDF_TARGET_LINUX
|
||||
#include "protocol_examples_common.h"
|
||||
#include "esp_event.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
/**
|
||||
* @brief This is an entry point for the real target device,
|
||||
* need to init few components and connect to a network interface
|
||||
*/
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
ESP_ERROR_CHECK(example_connect());
|
||||
|
||||
mdns_test_app(EXAMPLE_INTERFACE);
|
||||
|
||||
ESP_ERROR_CHECK(example_disconnect());
|
||||
}
|
||||
#else
|
||||
|
||||
/**
|
||||
* @brief This is an entry point for the linux target (simulator on host)
|
||||
* need to create a dummy WiFi station and use it as mdns network interface
|
||||
*/
|
||||
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 = CONFIG_TEST_NETIF_NAME };
|
||||
esp_netif_config_t cfg = { .base = &base_cg };
|
||||
esp_netif_t *sta = esp_netif_new(&cfg);
|
||||
|
||||
mdns_test_app(sta);
|
||||
|
||||
esp_netif_destroy(sta);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void mdns_test_app(esp_netif_t *interface)
|
||||
{
|
||||
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_EVENT_IP6_REVERSE_LOOKUP));
|
||||
ESP_ERROR_CHECK(mdns_register_netif(interface));
|
||||
ESP_ERROR_CHECK(mdns_netif_action(interface, MDNS_EVENT_ENABLE_IP4 /*| MDNS_EVENT_ENABLE_IP6 */ | MDNS_EVENT_IP4_REVERSE_LOOKUP | MDNS_EVENT_IP6_REVERSE_LOOKUP));
|
||||
|
||||
#ifdef REGISTER_SERVICE
|
||||
//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"}
|
||||
#ifdef CONFIG_TEST_CONSOLE
|
||||
esp_console_repl_t *repl = NULL;
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
s_exit_signal = xEventGroupCreate();
|
||||
|
||||
repl_config.prompt = "mdns>";
|
||||
// init console REPL environment
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
|
||||
|
||||
const esp_console_cmd_t cmd_exit = {
|
||||
.command = "exit",
|
||||
.help = "exit mDNS console application",
|
||||
.hint = NULL,
|
||||
.func = exit_console,
|
||||
.argtable = NULL
|
||||
};
|
||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||
ESP_ERROR_CHECK(mdns_service_add("myesp-service2", "_http", "_tcp", 80, serviceTxtData, 3));
|
||||
#endif
|
||||
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_exit) );
|
||||
mdns_console_register();
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(repl));
|
||||
xEventGroupWaitBits(s_exit_signal, 1, pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
repl->del(repl);
|
||||
#else
|
||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||
query_mdns_host("david-work");
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
esp_netif_destroy(sta);
|
||||
#endif
|
||||
mdns_free();
|
||||
ESP_LOGI(TAG, "Exit");
|
||||
return 0;
|
||||
}
|
||||
|
180
components/mdns/tests/host_test/pytest_mdns.py
Normal file
180
components/mdns/tests/host_test/pytest_mdns.py
Normal file
@ -0,0 +1,180 @@
|
||||
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import logging
|
||||
|
||||
import pexpect
|
||||
import pytest
|
||||
from dnsfixture import DnsPythonWrapper
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
ipv6_enabled = False
|
||||
|
||||
|
||||
class MdnsConsole:
|
||||
def __init__(self, command):
|
||||
self.process = pexpect.spawn(command, encoding='utf-8')
|
||||
self.process.logfile = open('mdns_interaction.log', 'w') # Log all interactions
|
||||
self.process.expect('mdns> ', timeout=10)
|
||||
|
||||
def send_input(self, input_data):
|
||||
logger.info(f'Sending to stdin: {input_data}')
|
||||
self.process.sendline(input_data)
|
||||
|
||||
def get_output(self, expected_data):
|
||||
logger.info(f'Expecting: {expected_data}')
|
||||
self.process.expect(expected_data, timeout=10)
|
||||
output = self.process.before.strip()
|
||||
logger.info(f'Received from stdout: {output}')
|
||||
return output
|
||||
|
||||
def terminate(self):
|
||||
self.send_input('exit')
|
||||
self.get_output('Exit')
|
||||
self.process.wait()
|
||||
self.process.close()
|
||||
assert self.process.exitstatus == 0
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def mdns_console():
|
||||
app = MdnsConsole('./build_linux_console/mdns_host.elf')
|
||||
yield app
|
||||
app.terminate()
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def dig_app():
|
||||
return DnsPythonWrapper()
|
||||
|
||||
|
||||
def test_mdns_init(mdns_console, dig_app):
|
||||
mdns_console.send_input('mdns_init -h hostname')
|
||||
mdns_console.get_output('MDNS: Hostname: hostname')
|
||||
dig_app.check_record('hostname.local', query_type='A', expected=True)
|
||||
if ipv6_enabled:
|
||||
dig_app.check_record('hostname.local', query_type='AAAA', expected=True)
|
||||
|
||||
|
||||
def test_add_service(mdns_console, dig_app):
|
||||
mdns_console.send_input('mdns_service_add _http _tcp 80 -i test_service')
|
||||
mdns_console.get_output('MDNS: Service Instance: test_service')
|
||||
mdns_console.send_input('mdns_service_lookup _http _tcp')
|
||||
mdns_console.get_output('PTR : test_service')
|
||||
dig_app.check_record('_http._tcp.local', query_type='PTR', expected=True)
|
||||
|
||||
|
||||
def test_remove_service(mdns_console, dig_app):
|
||||
mdns_console.send_input('mdns_service_remove _http _tcp')
|
||||
mdns_console.send_input('mdns_service_lookup _http _tcp')
|
||||
mdns_console.get_output('No results found!')
|
||||
dig_app.check_record('_http._tcp.local', query_type='PTR', expected=False)
|
||||
|
||||
|
||||
def test_delegate_host(mdns_console, dig_app):
|
||||
mdns_console.send_input('mdns_delegate_host delegated 1.2.3.4')
|
||||
dig_app.check_record('delegated.local', query_type='A', expected=True)
|
||||
|
||||
|
||||
def test_undelegate_host(mdns_console, dig_app):
|
||||
mdns_console.send_input('mdns_undelegate_host delegated')
|
||||
dig_app.check_record('delegated.local', query_type='A', expected=False)
|
||||
|
||||
|
||||
def test_add_delegated_service(mdns_console, dig_app):
|
||||
mdns_console.send_input('mdns_delegate_host delegated 1.2.3.4')
|
||||
dig_app.check_record('delegated.local', query_type='A', expected=True)
|
||||
mdns_console.send_input('mdns_service_add _test _tcp 80 -i local')
|
||||
mdns_console.get_output('MDNS: Service Instance: local')
|
||||
mdns_console.send_input('mdns_service_add _test2 _tcp 80 -i extern -h delegated')
|
||||
mdns_console.get_output('MDNS: Service Instance: extern')
|
||||
mdns_console.send_input('mdns_service_lookup _test _tcp')
|
||||
mdns_console.get_output('PTR : local')
|
||||
mdns_console.send_input('mdns_service_lookup _test2 _tcp -d')
|
||||
mdns_console.get_output('PTR : extern')
|
||||
dig_app.check_record('_test2._tcp.local', query_type='PTR', expected=True)
|
||||
dig_app.check_record('extern._test2._tcp.local', query_type='SRV', expected=True)
|
||||
|
||||
|
||||
def test_remove_delegated_service(mdns_console, dig_app):
|
||||
mdns_console.send_input('mdns_service_remove _test2 _tcp -h delegated')
|
||||
mdns_console.send_input('mdns_service_lookup _test2 _tcp -d')
|
||||
mdns_console.get_output('No results found!')
|
||||
dig_app.check_record('_test2._tcp.local', query_type='PTR', expected=False)
|
||||
# add the delegated service again, would be used in the TXT test
|
||||
mdns_console.send_input('mdns_service_add _test2 _tcp 80 -i extern -h delegated')
|
||||
mdns_console.get_output('MDNS: Service Instance: extern')
|
||||
|
||||
|
||||
def check_txt_for_service(instance, service, proto, mdns_console, dig_app, host=None, with_inst=False):
|
||||
for_host_arg = f'-h {host}' if host is not None else ''
|
||||
for_inst_arg = f'-i {instance}' if with_inst else ''
|
||||
mdns_console.send_input(f'mdns_service_txt_set {service} {proto} {for_host_arg} {for_inst_arg} key1 value1')
|
||||
dig_app.check_record(f'{instance}.{service}.{proto}.local', query_type='SRV', expected=True)
|
||||
dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=True, expect='key1=value1')
|
||||
mdns_console.send_input(f'mdns_service_txt_set {service} {proto} {for_host_arg} {for_inst_arg} key2 value2')
|
||||
dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=True, expect='key2=value2')
|
||||
mdns_console.send_input(f'mdns_service_txt_remove {service} {proto} {for_host_arg} {for_inst_arg} key2')
|
||||
dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=False, expect='key2=value2')
|
||||
dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=True, expect='key1=value1')
|
||||
mdns_console.send_input(f'mdns_service_txt_replace {service} {proto} {for_host_arg} {for_inst_arg} key3=value3 key4=value4')
|
||||
dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=False, expect='key1=value1')
|
||||
dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=True, expect='key3=value3')
|
||||
dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=True, expect='key4=value4')
|
||||
|
||||
|
||||
def test_update_txt(mdns_console, dig_app):
|
||||
check_txt_for_service('local', '_test', '_tcp', mdns_console=mdns_console, dig_app=dig_app)
|
||||
check_txt_for_service('local', '_test', '_tcp', mdns_console=mdns_console, dig_app=dig_app, with_inst=True)
|
||||
|
||||
|
||||
def test_update_delegated_txt(mdns_console, dig_app):
|
||||
check_txt_for_service('extern', '_test2', '_tcp', mdns_console=mdns_console, dig_app=dig_app, host='delegated')
|
||||
check_txt_for_service('extern', '_test2', '_tcp', mdns_console=mdns_console, dig_app=dig_app, host='delegated', with_inst=True)
|
||||
|
||||
|
||||
def test_service_port_set(mdns_console, dig_app):
|
||||
dig_app.check_record('local._test._tcp.local', query_type='SRV', expected=True, expect='80')
|
||||
mdns_console.send_input('mdns_service_port_set _test _tcp 81')
|
||||
dig_app.check_record('local._test._tcp.local', query_type='SRV', expected=True, expect='81')
|
||||
mdns_console.send_input('mdns_service_port_set _test2 _tcp -h delegated 82')
|
||||
dig_app.check_record('extern._test2._tcp.local', query_type='SRV', expected=True, expect='82')
|
||||
mdns_console.send_input('mdns_service_port_set _test2 _tcp -h delegated -i extern 83')
|
||||
dig_app.check_record('extern._test2._tcp.local', query_type='SRV', expected=True, expect='83')
|
||||
mdns_console.send_input('mdns_service_port_set _test2 _tcp -h delegated -i invalid_inst 84')
|
||||
mdns_console.get_output('ESP_ERR_NOT_FOUND')
|
||||
dig_app.check_record('extern._test2._tcp.local', query_type='SRV', expected=True, expect='83')
|
||||
|
||||
|
||||
def test_service_subtype(mdns_console, dig_app):
|
||||
dig_app.check_record('local._test._tcp.local', query_type='SRV', expected=True)
|
||||
mdns_console.send_input('mdns_service_subtype _test _tcp _subtest -i local')
|
||||
dig_app.check_record('_subtest._sub._test._tcp.local', query_type='PTR', expected=True)
|
||||
mdns_console.send_input('mdns_service_subtype _test2 _tcp _subtest2 -i extern -h delegated')
|
||||
dig_app.check_record('_subtest2._sub._test2._tcp.local', query_type='PTR', expected=True)
|
||||
|
||||
|
||||
def test_service_set_instance(mdns_console, dig_app):
|
||||
dig_app.check_record('local._test._tcp.local', query_type='SRV', expected=True)
|
||||
mdns_console.send_input('mdns_service_instance_set _test _tcp local2')
|
||||
dig_app.check_record('local2._test._tcp.local', query_type='SRV', expected=True)
|
||||
mdns_console.send_input('mdns_service_instance_set _test2 _tcp extern2 -h delegated')
|
||||
mdns_console.send_input('mdns_service_lookup _test2 _tcp -d')
|
||||
mdns_console.get_output('PTR : extern2')
|
||||
dig_app.check_record('extern2._test2._tcp.local', query_type='SRV', expected=True)
|
||||
mdns_console.send_input('mdns_service_instance_set _test2 _tcp extern3 -h delegated -i extern')
|
||||
mdns_console.get_output('ESP_ERR_NOT_FOUND')
|
||||
|
||||
|
||||
def test_service_remove_all(mdns_console, dig_app):
|
||||
mdns_console.send_input('mdns_service_remove_all')
|
||||
mdns_console.send_input('mdns_service_lookup _test2 _tcp -d')
|
||||
mdns_console.get_output('No results found!')
|
||||
mdns_console.send_input('mdns_service_lookup _test _tcp')
|
||||
mdns_console.get_output('No results found!')
|
||||
dig_app.check_record('_test._tcp.local', query_type='PTR', expected=False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pytest.main(['-s', 'test_mdns.py'])
|
4
components/mdns/tests/host_test/sdkconfig.ci.app
Normal file
4
components/mdns/tests/host_test/sdkconfig.ci.app
Normal file
@ -0,0 +1,4 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
CONFIG_TEST_HOSTNAME="myesp"
|
||||
CONFIG_MDNS_ENABLE_DEBUG_PRINTS=y
|
||||
CONFIG_MDNS_RESPOND_REVERSE_QUERIES=y
|
4
components/mdns/tests/host_test/sdkconfig.ci.console
Normal file
4
components/mdns/tests/host_test/sdkconfig.ci.console
Normal file
@ -0,0 +1,4 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
CONFIG_ESP_EVENT_POST_FROM_ISR=n
|
||||
CONFIG_MDNS_ENABLE_CONSOLE_CLI=y
|
||||
CONFIG_TEST_CONSOLE=y
|
1
components/mdns/tests/host_test/sdkconfig.ci.target
Normal file
1
components/mdns/tests/host_test/sdkconfig.ci.target
Normal file
@ -0,0 +1 @@
|
||||
CONFIG_IDF_TARGET="esp32"
|
@ -1,9 +1,6 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
CONFIG_TEST_NETIF_NAME="eth0"
|
||||
CONFIG_ESP_EVENT_POST_FROM_ISR=n
|
||||
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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@ -9,6 +9,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "esp32_mock.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
void *g_queue;
|
||||
int g_queue_send_shall_fail = 0;
|
||||
@ -111,3 +112,12 @@ BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear,
|
||||
{
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
void esp_log_write(esp_log_level_t level, const char *tag, const char *format, ...)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t esp_log_timestamp(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -45,11 +45,6 @@
|
||||
|
||||
#define portMAX_DELAY 0xFFFFFFFF
|
||||
#define portTICK_PERIOD_MS 1
|
||||
#define ESP_LOGW(a,b)
|
||||
#define ESP_LOGD(a,b)
|
||||
#define ESP_LOGE(a,b,c)
|
||||
#define ESP_LOGV(a,b,c,d)
|
||||
|
||||
#define LWIP_HDR_PBUF_H
|
||||
#define __ESP_RANDOM_H__
|
||||
#define INC_TASK_H
|
||||
|
@ -1,9 +1,10 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "mdns.h"
|
||||
#include "esp_event.h"
|
||||
#include "unity.h"
|
||||
@ -90,6 +91,7 @@ TEST(mdns, api_fails_with_expected_err)
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_item_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, "key1", "value1") );
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_item_remove(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, "key1") );
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_port_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 8080) );
|
||||
yield_to_all_priorities(); // to remove the service with the updated txt records
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO) );
|
||||
yield_to_all_priorities(); // Make sure that mdns task has executed to remove the service
|
||||
|
||||
@ -142,12 +144,153 @@ TEST(mdns, query_api_fails_with_expected_err)
|
||||
esp_event_loop_delete_default();
|
||||
}
|
||||
|
||||
TEST(mdns, add_remove_service)
|
||||
{
|
||||
mdns_result_t *results = NULL;
|
||||
test_case_uses_tcpip();
|
||||
TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default());
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_init() );
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME));
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0));
|
||||
yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, results);
|
||||
TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE, results->instance_name);
|
||||
TEST_ASSERT_EQUAL_STRING(MDNS_SERVICE_NAME, results->service_type);
|
||||
TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT, results->port);
|
||||
TEST_ASSERT_EQUAL(NULL, results->txt);
|
||||
mdns_query_results_free(results);
|
||||
|
||||
// Update service properties: port
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_port_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT + 1));
|
||||
yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, results);
|
||||
TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT + 1, results->port);
|
||||
mdns_query_results_free(results);
|
||||
|
||||
// Update service properties: instance
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_instance_name_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_INSTANCE "1" ));
|
||||
yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(MDNS_INSTANCE "1", MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, results);
|
||||
TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE "1", results->instance_name);
|
||||
mdns_query_results_free(results);
|
||||
|
||||
// Update service properties: txt
|
||||
mdns_txt_item_t txt_data[] = {
|
||||
{"key1", "esp32"},
|
||||
{"key2", "value"},
|
||||
{"key3", "value3"},
|
||||
};
|
||||
const size_t txt_data_cout = sizeof(txt_data) / sizeof(txt_data[0]);
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, txt_data, txt_data_cout));
|
||||
yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, results);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, results->txt);
|
||||
TEST_ASSERT_EQUAL(txt_data_cout, results->txt_count);
|
||||
// compare txt values by keys
|
||||
size_t matches = 0;
|
||||
for (int i = 0; i < results->txt_count; ++i) // iterates over the results we get from mdns_lookup()
|
||||
for (int j = 0; j < txt_data_cout; ++j) // iterates over our test records
|
||||
if (strcmp(results->txt[i].key, txt_data[j].key) == 0) { // we compare the value only if the key matches
|
||||
TEST_ASSERT_EQUAL_STRING(results->txt[i].value, txt_data[j].value);
|
||||
++matches;
|
||||
}
|
||||
TEST_ASSERT_EQUAL(txt_data_cout, matches); // checks that we went over all our txt items
|
||||
mdns_query_results_free(results);
|
||||
|
||||
// Now remove the service
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO));
|
||||
yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
|
||||
TEST_ASSERT_EQUAL(NULL, results);
|
||||
|
||||
mdns_free();
|
||||
esp_event_loop_delete_default();
|
||||
}
|
||||
|
||||
TEST(mdns, add_remove_deleg_service)
|
||||
{
|
||||
mdns_ip_addr_t addr;
|
||||
addr.addr.type = ESP_IPADDR_TYPE_V4;
|
||||
addr.addr.u_addr.ip4.addr = esp_ip4addr_aton("127.0.0.1");
|
||||
addr.next = NULL;
|
||||
mdns_result_t *results = NULL;
|
||||
test_case_uses_tcpip();
|
||||
TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default());
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_init() );
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME));
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_delegate_hostname_add(MDNS_DELEGATE_HOSTNAME, &addr) );
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add_for_host(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, MDNS_SERVICE_PORT, NULL, 0));
|
||||
yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, results);
|
||||
TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE, results->instance_name);
|
||||
TEST_ASSERT_EQUAL_STRING(MDNS_SERVICE_NAME, results->service_type);
|
||||
TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT, results->port);
|
||||
TEST_ASSERT_EQUAL(NULL, results->txt);
|
||||
mdns_query_results_free(results);
|
||||
|
||||
// Update service properties: port
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_port_set_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, MDNS_SERVICE_PORT + 1));
|
||||
yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, results);
|
||||
TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT + 1, results->port);
|
||||
mdns_query_results_free(results);
|
||||
|
||||
// Update service properties: instance
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_instance_name_set_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, MDNS_INSTANCE "1" ));
|
||||
yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(MDNS_INSTANCE "1", MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, results);
|
||||
TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE "1", results->instance_name);
|
||||
mdns_query_results_free(results);
|
||||
|
||||
// Update service properties: txt
|
||||
mdns_txt_item_t txt_data[] = {
|
||||
{"key1", "esp32"},
|
||||
{"key2", "value"},
|
||||
};
|
||||
const size_t txt_data_cout = sizeof(txt_data) / sizeof(txt_data[0]);
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_set_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, txt_data, txt_data_cout));
|
||||
yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, results);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, results->txt);
|
||||
TEST_ASSERT_EQUAL(txt_data_cout, results->txt_count);
|
||||
// compare txt values by keys
|
||||
size_t matches = 0;
|
||||
for (int i = 0; i < results->txt_count; ++i) // iterates over the results we get from mdns_lookup()
|
||||
for (int j = 0; j < txt_data_cout; ++j) // iterates over our test records
|
||||
if (strcmp(results->txt[i].key, txt_data[j].key) == 0) { // we compare the value only if the key matches
|
||||
TEST_ASSERT_EQUAL_STRING(results->txt[i].value, txt_data[j].value);
|
||||
++matches;
|
||||
}
|
||||
TEST_ASSERT_EQUAL(txt_data_cout, matches); // checks that we went over all our txt items
|
||||
mdns_query_results_free(results);
|
||||
|
||||
// Now remove the service
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME));
|
||||
yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
|
||||
TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
|
||||
TEST_ASSERT_EQUAL(NULL, results);
|
||||
|
||||
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)
|
||||
RUN_TEST_CASE(mdns, add_remove_service)
|
||||
RUN_TEST_CASE(mdns, add_remove_deleg_service)
|
||||
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
|
@ -91,10 +91,14 @@ For more options on :cpp:type:`esp_websocket_client_config_t`, please refer to A
|
||||
|
||||
Events
|
||||
------
|
||||
* `WEBSOCKET_EVENT_BEGIN': The client thread is running.
|
||||
* `WEBSOCKET_EVENT_BEFORE_CONNECT`: The client is about to connect.
|
||||
* `WEBSOCKET_EVENT_CONNECTED`: The client has successfully established a connection to the server. The client is now ready to send and receive data. Contains no event data.
|
||||
* `WEBSOCKET_EVENT_DISCONNECTED`: The client has aborted the connection due to the transport layer failing to read data, e.g. because the server is unavailable. Contains no event data.
|
||||
* `WEBSOCKET_EVENT_DATA`: The client has successfully received and parsed a WebSocket frame. The event data contains a pointer to the payload data, the length of the payload data as well as the opcode of the received frame. A message may be fragmented into multiple events if the length exceeds the buffer size. This event will also be posted for non-payload frames, e.g. pong or connection close frames.
|
||||
* `WEBSOCKET_EVENT_ERROR`: Not used in the current implementation of the client.
|
||||
* `WEBSOCKET_EVENT_ERROR`: The client has experienced an error. Examples include transport write or read failures.
|
||||
* `WEBSOCKET_EVENT_DISCONNECTED`: The client has aborted the connection due to the transport layer failing to read data, e.g. because the server is unavailable. Contains no event data.
|
||||
* `WEBSOCKET_EVENT_CLOSED`: The connection has been closed cleanly.
|
||||
* `WEBSOCKET_EVENT_FINISH': The client thread is about to exit.
|
||||
|
||||
If the client handle is needed in the event handler it can be accessed through the pointer passed to the event handler:
|
||||
|
||||
|
Reference in New Issue
Block a user