Compare commits

..

4 Commits

95 changed files with 768 additions and 2849 deletions

View File

@ -4,7 +4,7 @@ on:
pull_request:
push:
branches:
- master
- test_clang_tidy
jobs:
build:

View File

@ -14,17 +14,12 @@ 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

View File

@ -10,30 +10,27 @@ on:
jobs:
host_test_mdns:
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
name: Host test build
name: Host test
runs-on: ubuntu-22.04
container: espressif/idf:release-v5.3
container: espressif/idf:release-v5.1
steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4
with:
path: protocols
path: esp-protocols
- name: Build and Test
shell: bash
run: |
apt-get update && apt-get install -y dnsutils gcc g++
. ${IDF_PATH}/export.sh
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
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
build_afl_host_test_mdns:
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'

View File

@ -69,11 +69,9 @@ 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:

View File

@ -26,7 +26,7 @@ jobs:
- name: Set up Python environment
uses: actions/setup-python@master
with:
python-version: v3.8
python-version: v3.7
- name: Install python packages
run: |
pip install pre-commit

View File

@ -48,7 +48,7 @@ repos:
- id: check-copyright
args: ['--ignore', 'ci/check_copyright_ignore.txt', '--config', 'ci/check_copyright_config.yaml']
- repo: https://github.com/igrr/astyle_py.git
rev: v1.0.5
rev: c0013808882a15a0c0c2c1a9b5c903866c53a653
hooks:
- id: astyle_py
args: ['--style=otbs', '--attach-namespaces', '--attach-classes', '--indent=spaces=4', '--convert-tabs', '--align-pointer=name', '--align-reference=name', '--keep-one-line-statements', '--pad-header', '--pad-oper', '--exclude-list=ci/ignore_astyle.txt']

View File

@ -1 +0,0 @@
idf_component_register()

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -12,24 +12,8 @@
#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,
@ -105,7 +89,6 @@ BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue)
}
return pdFALSE;
}
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
{
struct generic_queue_handle *h = xQueue;
@ -116,6 +99,7 @@ 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;
@ -126,6 +110,9 @@ BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
return pdFALSE;
}
void vQueueDelete( QueueHandle_t xQueue )
{
struct generic_queue_handle *h = xQueue;
@ -141,7 +128,8 @@ void vQueueDelete( QueueHandle_t xQueue )
QueueHandle_t xSemaphoreCreateBinary(void)
{
return xQueueCreate(1, 1);
QueueHandle_t sempaphore = xQueueCreate(1, 1);
return sempaphore;
}
QueueHandle_t xSemaphoreCreateMutex(void)
@ -157,13 +145,6 @@ 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);
}
@ -190,21 +171,14 @@ void vTaskDelay( const TickType_t xTicksToDelay )
void *pthread_task(void *params)
{
pthread_params_t *pthread_params = params;
struct {
void *const param;
TaskFunction_t task;
bool started;
} *pthread_params = params;
void *const param = pthread_params->param;
TaskFunction_t task = pthread_params->task;
pthread_params->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);
@ -224,12 +198,16 @@ 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;
pthread_params_t pthread_params = { .param = pvParameters, .task = pvTaskCode};
struct {
void *const param;
TaskFunction_t task;
bool started;
} pthread_params = { .param = pvParameters, .task = pvTaskCode};
int res = pthread_attr_init(&attr);
assert(res == 0);
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
@ -237,33 +215,20 @@ 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 )
@ -273,7 +238,7 @@ BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear,
TaskHandle_t xTaskGetCurrentTaskHandle(void)
{
return (TaskHandle_t)pthread_self();
return NULL;
}
EventGroupHandle_t xEventGroupCreate( void )
@ -305,22 +270,3 @@ 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);
}
}

View File

@ -5,7 +5,6 @@
*/
#pragma once
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

View File

@ -1,6 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#pragma once

View File

@ -11,7 +11,6 @@
extern "C" {
#endif
#define tskNO_AFFINITY ( ( BaseType_t ) 0x7FFFFFFF )
#define TaskHandle_t TaskHandle_t
#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
@ -19,8 +18,6 @@ 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 );

View File

@ -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.1.0
version: 1.0.0
version_files:
- idf_component.yml

View File

@ -1,11 +1,5 @@
# 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

View File

@ -1,10 +1,4 @@
idf_component_register(SRCS "console_ping.c" "console_getaddrinfo.c" "console_getsetdnsserver.c"
idf_component_register(SRCS "console_ping.c"
INCLUDE_DIRS "."
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()
PRIV_REQUIRES esp_netif console
WHOLE_ARCHIVE)

View File

@ -1,9 +0,0 @@
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

View File

@ -1,5 +1,5 @@
# 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.
# Console command ping
The component provides a console where the 'ping' command can be executed.
## API
@ -27,11 +27,8 @@ The component provides a console where the 'ping' command, 'getaddrinfo', and DN
// Register all plugin command added to your project
ESP_ERROR_CHECK(console_cmd_all_register());
// To register only ping/dns command skip calling console_cmd_all_register()
// To register only ifconfig 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
```
@ -39,8 +36,6 @@ The component provides a console where the 'ping' command, 'getaddrinfo', and DN
### 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)
@ -57,72 +52,4 @@ 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
```

View File

@ -1,180 +0,0 @@
/*
* 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;
}

View File

@ -1,279 +0,0 @@
/*
* 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;
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023 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,13 +75,9 @@ 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);
@ -154,15 +150,11 @@ 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);
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -20,30 +20,6 @@ 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

View File

@ -1,4 +1,4 @@
version: 1.1.0
version: 1.0.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:

View File

@ -3,6 +3,6 @@ commitizen:
bump_message: 'bump(console): $current_version -> $new_version'
pre_bump_hooks: python ../../ci/changelog.py console_cmd_wifi
tag_format: console_cmd_wifi-v$version
version: 1.1.0
version: 1.0.1
version_files:
- idf_component.yml

View File

@ -1,11 +1,5 @@
# Changelog
## [1.1.0](https://github.com/espressif/esp-protocols/commits/console_cmd_wifi-v1.1.0)
### Features
- Added support to join pre-configured network ([bdbf16c1](https://github.com/espressif/esp-protocols/commit/bdbf16c1))
## [1.0.1](https://github.com/espressif/esp-protocols/commits/console_cmd_wifi-v1.0.1)
### Features

View File

@ -1,8 +1,4 @@
idf_component_register(SRCS "console_wifi.c"
INCLUDE_DIRS "include"
REQUIRES lwip
PRIV_REQUIRES esp_netif console esp_wifi esp_timer)
if(CONFIG_WIFI_CMD_AUTO_REGISTRATION)
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_wifi_register")
endif()
INCLUDE_DIRS "."
PRIV_REQUIRES esp_netif console esp_wifi
WHOLE_ARCHIVE)

View File

@ -1,22 +0,0 @@
menu "Wifi command Configuration"
config WIFI_CMD_AUTO_REGISTRATION
bool "Enable Console command wifi Auto-registration"
default y
help
Enabling this allows for the autoregistration of the wifi command.
config WIFI_CMD_NETWORK_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) to connect to.
config WIFI_CMD_NETWORK_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) to use.
Can be left blank if the network has no security set.
endmenu

View File

@ -33,16 +33,12 @@ The component offers a console with a command that enables runtime wifi configur
ESP_ERROR_CHECK(console_cmd_start()); // Start console
```
Note: Auto-registration of a specific plugin command can be disabled from menuconfig.
## Suported command:
### wifi:
```
wifi help: Prints the help text for all wifi commands
wifi show network/sta: Scans and displays all available wifi APs./ Shows the details of wifi station.
wifi sta join <network ssid> <password>: Station joins the given wifi network.
wifi sta join <network ssid>: Station joins the given unsecured wifi network.
wifi sta join: Station joins the pre-configured wifi network.
wifi sta leave: Station leaves the wifi network.
```
* ```wifi help```: Prints the help text for all wifi commands
* ```wifi show network```: Scans and displays upto 10 available wifi networks.
* ```wifi show sta```: Shows the details of wifi station.
* ```wifi sta join <network ssid> <password>```: Station joins the given wifi network.
* ```wifi sta join <network ssid>```: Station joins the given unsecured wifi network.
* ```wifi sta leave```: Station leaves the wifi network.

View File

@ -21,7 +21,6 @@
#define DEFAULT_SCAN_LIST_SIZE 10
#if CONFIG_WIFI_CMD_AUTO_REGISTRATION
/**
* Static registration of this plugin is achieved by defining the plugin description
* structure and placing it into .console_cmd_desc section.
@ -31,7 +30,6 @@ static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc
.name = "console_cmd_wifi",
.plugin_regd_fn = &console_cmd_wifi_register
};
#endif
typedef struct wifi_op_t {
char *name;
@ -57,9 +55,8 @@ static const int CONNECTED_BIT = BIT1;
static wifi_op_t cmd_list[] = {
{.name = "help", .operation = wifi_help_op, .arg_cnt = 2, .start_index = 1, .help = "wifi help: Prints the help text for all wifi commands"},
{.name = "show", .operation = wifi_show_op, .arg_cnt = 3, .start_index = 1, .help = "wifi show network/sta: Scans and displays all available wifi APs./ Shows the details of wifi station."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 5, .start_index = 2, .help = "wifi sta join <network ssid> <password>: Station joins the given wifi network."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 4, .start_index = 2, .help = "wifi sta join <network ssid>: Station joins the given unsecured wifi network."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 3, .start_index = 2, .help = "wifi sta join: Station joins the pre-configured wifi network."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 4, .start_index = 2, .help = "wifi sta join <network ssid> <password>: Station joins the given wifi network."},
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 5, .start_index = 2, .help = "wifi sta join <network ssid>: Station joins the given unsecured wifi network."},
{.name = "leave", .operation = wifi_sta_leave_op, .arg_cnt = 3, .start_index = 2, .help = "wifi sta leave: Station leaves the wifi network."},
};
@ -165,6 +162,7 @@ static esp_err_t wifi_show_op(wifi_op_t *self, int argc, char *argv[])
ESP_LOGI(TAG, "Showing Joind AP details:");
ESP_LOGI(TAG, "*************************");
ESP_LOGI(TAG, "SSID: %s", wifi_config.sta.ssid);
ESP_LOGI(TAG, "Password: %s", wifi_config.sta.password);
ESP_LOGI(TAG, "Channel: %d", wifi_config.sta.channel);
ESP_LOGI(TAG, "bssid: %02x:%02x:%02x:%02x:%02x:%02x", wifi_config.sta.bssid[0],
wifi_config.sta.bssid[1], wifi_config.sta.bssid[2], wifi_config.sta.bssid[3],
@ -186,13 +184,7 @@ static esp_err_t wifi_sta_join_op(wifi_op_t *self, int argc, char *argv[])
return ESP_FAIL;
}
if (self->arg_cnt == 3) {
strlcpy((char *) wifi_config.sta.ssid, CONFIG_WIFI_CMD_NETWORK_SSID, sizeof(wifi_config.sta.ssid));
strlcpy((char *) wifi_config.sta.password, CONFIG_WIFI_CMD_NETWORK_PASSWORD, sizeof(wifi_config.sta.password));
} else {
strlcpy((char *) wifi_config.sta.ssid, argv[self->start_index + 1], sizeof(wifi_config.sta.ssid));
}
strlcpy((char *) wifi_config.sta.ssid, argv[self->start_index + 1], sizeof(wifi_config.sta.ssid));
if (self->arg_cnt == 5) {
strlcpy((char *) wifi_config.sta.password, argv[self->start_index + 2], sizeof(wifi_config.sta.password));
}
@ -268,7 +260,7 @@ static esp_err_t do_cmd_wifi(int argc, char **argv)
*/
esp_err_t console_cmd_wifi_register(void)
{
esp_err_t ret = ESP_OK;
esp_err_t ret;
esp_console_cmd_t command = {
.command = "wifi",
.help = "Command for wifi configuration and monitoring\n For more info run 'wifi help'",

View File

@ -1,4 +1,4 @@
version: 1.1.0
version: 1.0.1
url: https://github.com/espressif/esp-protocols/tree/master/components/console_cmd_wifi
description: The component offers a console that enables runtime wifi configuration and monitoring.
dependencies:

View File

@ -3,6 +3,6 @@ commitizen:
bump_message: 'bump(eppp): $current_version -> $new_version'
pre_bump_hooks: python ../../ci/changelog.py eppp_link
tag_format: eppp-v$version
version: 0.2.0
version: 0.1.1
version_files:
- idf_component.yml

View File

@ -1,16 +1,5 @@
# Changelog
## [0.2.0](https://github.com/espressif/esp-protocols/commits/eppp-v0.2.0)
### Features
- Add support for SDIO transport ([085dd790](https://github.com/espressif/esp-protocols/commit/085dd790))
### Bug Fixes
- Fixed strict prototype API decl issue in SDIO ([eb09e426](https://github.com/espressif/esp-protocols/commit/eb09e426))
- Fix SIDO host to check/clear interrupts atomically ([402176c9](https://github.com/espressif/esp-protocols/commit/402176c9))
## [0.1.1](https://github.com/espressif/esp-protocols/commits/eppp-v0.1.1)
### Bug Fixes

View File

@ -1,3 +1,3 @@
idf_component_register(SRCS eppp_link.c eppp_sdio_slave.c eppp_sdio_host.c
idf_component_register(SRCS "eppp_link.c"
INCLUDE_DIRS "include"
PRIV_REQUIRES esp_netif esp_driver_spi esp_driver_gpio esp_timer driver)

View File

@ -21,13 +21,6 @@ menu "eppp_link"
bool "SPI"
help
Use SPI.
config EPPP_LINK_DEVICE_SDIO
bool "SDIO"
depends on SOC_SDMMC_HOST_SUPPORTED || SOC_SDIO_SLAVE_SUPPORTED
help
Use SDIO.
endchoice
config EPPP_LINK_CONN_MAX_RETRY
@ -41,30 +34,8 @@ menu "eppp_link"
config EPPP_LINK_PACKET_QUEUE_SIZE
int "Packet queue size"
default 64
depends on EPPP_LINK_DEVICE_SPI
help
Size of the Tx packet queue.
You can decrease the number for slower bit rates.
choice EPPP_LINK_SDIO_ROLE
prompt "Choose SDIO host or slave"
depends on EPPP_LINK_DEVICE_SDIO
default EPPP_LINK_DEVICE_SDIO_HOST if SOC_SDMMC_HOST_SUPPORTED
help
Select which either SDIO host or slave
config EPPP_LINK_DEVICE_SDIO_HOST
bool "Host"
depends on SOC_SDMMC_HOST_SUPPORTED
help
Use SDIO host.
config EPPP_LINK_DEVICE_SDIO_SLAVE
bool "SLAVE"
depends on SOC_SDIO_SLAVE_SUPPORTED
help
Use SDIO slave.
endchoice
endmenu

View File

@ -14,7 +14,7 @@ brings in the WiFi connectivity from the "SLAVE" microcontroller.
SLAVE micro HOST micro
\|/ +----------------+ +----------------+
| | | serial line | |
+---+ WiFi NAT PPPoS |=== UART / SPI / SDIO =====| PPPoS client |
+---+ WiFi NAT PPPoS |======== UART / SPI =======| PPPoS client |
| (server)| | |
+----------------+ +----------------+
```
@ -39,19 +39,14 @@ brings in the WiFi connectivity from the "SLAVE" microcontroller.
## Throughput
Tested with WiFi-NAPT example
Tested with WiFi-NAPT example, no IRAM optimizations
### UART @ 3Mbauds
* TCP - 2Mbits/s
* UDP - 2Mbits/s
### SPI @ 16MHz
### SPI @ 20MHz
* TCP - 5Mbits/s
* UDP - 8Mbits/s
### SDIO
* TCP - 9Mbits/s
* UDP - 11Mbits/s
* TCP - 6Mbits/s
* UDP - 10Mbits/s

View File

@ -12,7 +12,6 @@
#include "esp_event.h"
#include "esp_netif_ppp.h"
#include "eppp_link.h"
#include "esp_serial_slave_link/essl_sdio.h"
#if CONFIG_EPPP_LINK_DEVICE_SPI
#include "driver/spi_master.h"
@ -87,18 +86,7 @@ struct eppp_handle {
bool netif_stop;
};
typedef esp_err_t (*transmit_t)(void *h, void *buffer, size_t len);
#if CONFIG_EPPP_LINK_DEVICE_SDIO
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len);
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif);
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif);
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len);
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config);
esp_err_t eppp_sdio_slave_init(void);
void eppp_sdio_slave_deinit(void);
void eppp_sdio_host_deinit(void);
#else
static esp_err_t transmit(void *h, void *buffer, size_t len)
{
struct eppp_handle *handle = h;
@ -137,10 +125,9 @@ static esp_err_t transmit(void *h, void *buffer, size_t len)
#elif CONFIG_EPPP_LINK_DEVICE_UART
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_send", buffer, len, ESP_LOG_VERBOSE);
uart_write_bytes(handle->uart_port, buffer, len);
#endif // DEVICE UART or SPI
#endif
return ESP_OK;
}
#endif
static void netif_deinit(esp_netif_t *netif)
{
@ -222,11 +209,7 @@ static esp_netif_t *netif_init(eppp_type_t role, eppp_config_t *eppp_config)
esp_netif_driver_ifconfig_t driver_cfg = {
.handle = h,
#if CONFIG_EPPP_LINK_DEVICE_SDIO
.transmit = role == EPPP_CLIENT ? eppp_sdio_host_tx : eppp_sdio_slave_tx,
#else
.transmit = transmit,
#endif
};
const esp_netif_driver_ifconfig_t *ppp_driver_cfg = &driver_cfg;
@ -674,20 +657,6 @@ esp_err_t eppp_perform(esp_netif_t *netif)
}
return ESP_OK;
}
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
esp_err_t eppp_perform(esp_netif_t *netif)
{
struct eppp_handle *h = esp_netif_get_io_driver(netif);
if (h->stop) {
return ESP_ERR_TIMEOUT;
}
if (h->role == EPPP_SERVER) {
return eppp_sdio_slave_rx(netif);
} else {
return eppp_sdio_host_rx(netif);
}
}
#endif // CONFIG_EPPP_LINK_DEVICE_SPI / UART
@ -731,13 +700,6 @@ void eppp_deinit(esp_netif_t *netif)
}
#elif CONFIG_EPPP_LINK_DEVICE_UART
deinit_uart(esp_netif_get_io_driver(netif));
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
struct eppp_handle *h = esp_netif_get_io_driver(netif);
if (h->role == EPPP_CLIENT) {
eppp_sdio_host_deinit();
} else {
eppp_sdio_slave_deinit();
}
#endif
netif_deinit(netif);
}
@ -752,6 +714,7 @@ esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config)
esp_netif_t *netif = netif_init(role, config);
if (!netif) {
ESP_LOGE(TAG, "Failed to initialize PPP netif");
remove_handlers();
return NULL;
}
esp_netif_ppp_config_t netif_params;
@ -769,18 +732,6 @@ esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config)
}
#elif CONFIG_EPPP_LINK_DEVICE_UART
init_uart(esp_netif_get_io_driver(netif), config);
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
esp_err_t ret;
if (role == EPPP_SERVER) {
ret = eppp_sdio_slave_init();
} else {
ret = eppp_sdio_host_init(&config->sdio);
}
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize SDIO %d", ret);
return NULL;
}
#endif
return netif;
}
@ -803,12 +754,6 @@ esp_netif_t *eppp_open(eppp_type_t role, eppp_config_t *config, int connect_time
return NULL;
}
#endif
#if CONFIG_EPPP_LINK_DEVICE_SDIO
if (config->transport != EPPP_TRANSPORT_SDIO) {
ESP_LOGE(TAG, "Invalid transport: SDIO device must be enabled in Kconfig");
return NULL;
}
#endif
if (config->task.run_task == false) {
ESP_LOGE(TAG, "task.run_task == false is invalid in this API. Please use eppp_init()");

View File

@ -1,19 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#define MAX_SDIO_PAYLOAD 1500
#define SDIO_ALIGN(size) (((size) + 3U) & ~(3U))
#define SDIO_PAYLOAD SDIO_ALIGN(MAX_SDIO_PAYLOAD)
#define PPP_SOF 0x7E
// Interrupts and registers
#define SLAVE_INTR 0
#define SLAVE_REG_REQ 0
// Requests from host to slave
#define REQ_RESET 1
#define REQ_INIT 2

View File

@ -1,200 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "driver/sdio_slave.h"
#include "esp_serial_slave_link/essl_sdio.h"
#include "eppp_sdio.h"
#include "driver/sdmmc_host.h"
#include "sdmmc_cmd.h"
#include "esp_check.h"
#include "eppp_link.h"
#if CONFIG_EPPP_LINK_DEVICE_SDIO_HOST
// For blocking operations
#define TIMEOUT_MAX UINT32_MAX
// Short timeout for sending/receiving ESSL packets
#define PACKET_TIMEOUT_MS 50
static const char *TAG = "eppp_sdio_host";
static SemaphoreHandle_t s_essl_mutex = NULL;
static essl_handle_t s_essl = NULL;
static sdmmc_card_t *s_card = NULL;
static DRAM_DMA_ALIGNED_ATTR uint8_t send_buffer[SDIO_PAYLOAD];
static DMA_ATTR uint8_t rcv_buffer[SDIO_PAYLOAD];
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
{
if (s_essl == NULL || s_essl_mutex == NULL) {
// silently skip the Tx if the SDIO not fully initialized
return ESP_OK;
}
memcpy(send_buffer, buffer, len);
size_t send_len = SDIO_ALIGN(len);
if (send_len > len) {
// pad with SOF's
memset(&send_buffer[len], PPP_SOF, send_len - len);
}
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
esp_err_t ret = essl_send_packet(s_essl, send_buffer, send_len, PACKET_TIMEOUT_MS);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Slave not ready to receive packet %x", ret);
vTaskDelay(pdMS_TO_TICKS(1000));
ret = ESP_ERR_NO_MEM; // to inform the upper layers
}
ESP_LOG_BUFFER_HEXDUMP(TAG, send_buffer, send_len, ESP_LOG_VERBOSE);
xSemaphoreGive(s_essl_mutex);
return ret;
}
static esp_err_t request_slave_reset(void)
{
esp_err_t ret = ESP_OK;
ESP_LOGI(TAG, "send reset to slave...");
ESP_GOTO_ON_ERROR(essl_write_reg(s_essl, SLAVE_REG_REQ, REQ_RESET, NULL, TIMEOUT_MAX), err, TAG, "write-reg failed");
ESP_GOTO_ON_ERROR(essl_send_slave_intr(s_essl, BIT(SLAVE_INTR), TIMEOUT_MAX), err, TAG, "send-intr failed");
vTaskDelay(pdMS_TO_TICKS(PACKET_TIMEOUT_MS));
ESP_GOTO_ON_ERROR(essl_wait_for_ready(s_essl, TIMEOUT_MAX), err, TAG, "wait-for-ready failed");
ESP_LOGI(TAG, "slave io ready");
err:
return ret;
}
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *eppp_config)
{
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_ERROR(sdmmc_host_init(), err, TAG, "sdmmc host init failed");
// configure SDIO interface and slot
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
slot_config.width = eppp_config->width;
#ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
slot_config.clk = eppp_config->clk;
slot_config.cmd = eppp_config->cmd;
slot_config.d0 = eppp_config->d0;
slot_config.d1 = eppp_config->d1;
slot_config.d2 = eppp_config->d2;
slot_config.d3 = eppp_config->d3;
#endif
ESP_GOTO_ON_ERROR(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config), err, TAG, "init sdmmc host slot failed");
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
config.flags = SDMMC_HOST_FLAG_4BIT;
config.flags |= SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF;
config.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
s_card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
ESP_GOTO_ON_FALSE(s_card, ESP_ERR_NO_MEM, err, TAG, "card allocation failed");
ESP_GOTO_ON_ERROR(sdmmc_card_init(&config, s_card), err, TAG, "sdmmc card init failed");
essl_sdio_config_t ser_config = {
.card = s_card,
.recv_buffer_size = SDIO_PAYLOAD,
};
ESP_GOTO_ON_FALSE(essl_sdio_init_dev(&s_essl, &ser_config) == ESP_OK && s_essl, ESP_FAIL, err, TAG, "essl_sdio_init_dev failed");
ESP_GOTO_ON_ERROR(essl_init(s_essl, TIMEOUT_MAX), err, TAG, "essl-init failed");
ESP_GOTO_ON_ERROR(request_slave_reset(), err, TAG, "failed to reset the slave");
ESP_GOTO_ON_FALSE((s_essl_mutex = xSemaphoreCreateMutex()), ESP_ERR_NO_MEM, err, TAG, "failed to create semaphore");
return ret;
err:
essl_sdio_deinit_dev(s_essl);
s_essl = NULL;
return ret;
}
static esp_err_t get_intr(uint32_t *out_raw)
{
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_ERROR(essl_get_intr(s_essl, out_raw, NULL, 0), err, TAG, "essl-get-int failed");
ESP_GOTO_ON_ERROR(essl_clear_intr(s_essl, *out_raw, 0), err, TAG, "essl-clear-int failed");
ESP_LOGD(TAG, "intr: %08"PRIX32, *out_raw);
err:
return ret;
}
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
{
uint32_t intr;
esp_err_t err = essl_wait_int(s_essl, TIMEOUT_MAX);
if (err == ESP_ERR_TIMEOUT) {
return ESP_OK;
}
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
err = get_intr(&intr);
if (err == ESP_ERR_TIMEOUT) {
xSemaphoreGive(s_essl_mutex);
return ESP_OK;
}
if (err != ESP_OK) {
ESP_LOGE(TAG, "failed to check for interrupts %d", err);
xSemaphoreGive(s_essl_mutex);
return ESP_FAIL;
}
if (intr & ESSL_SDIO_DEF_ESP32.new_packet_intr_mask) {
esp_err_t ret;
do {
size_t size_read = SDIO_PAYLOAD;
ret = essl_get_packet(s_essl, rcv_buffer, SDIO_PAYLOAD, &size_read, PACKET_TIMEOUT_MS);
if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "interrupt but no data can be read");
break;
} else if (ret == ESP_OK) {
ESP_LOGD(TAG, "receive data, size: %d", size_read);
ESP_LOG_BUFFER_HEXDUMP(TAG, rcv_buffer, size_read, ESP_LOG_VERBOSE);
esp_netif_receive(netif, rcv_buffer, size_read, NULL);
break;
} else {
ESP_LOGE(TAG, "rx packet error: %08X", ret);
if (request_slave_reset() != ESP_OK) {
ESP_LOGE(TAG, "Failed to request slave reset %x", ret);
break;
}
}
} while (ret == ESP_ERR_NOT_FINISHED);
}
xSemaphoreGive(s_essl_mutex);
return ESP_OK;
}
void eppp_sdio_host_deinit(void)
{
essl_sdio_deinit_dev(s_essl);
sdmmc_host_deinit();
free(s_card);
s_card = NULL;
s_essl = NULL;
}
#else // SDMMC_HOST NOT-SUPPORTED
esp_err_t eppp_sdio_host_tx(void *handle, void *buffer, size_t len)
{
return ESP_ERR_NOT_SUPPORTED;
}
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
{
return ESP_ERR_NOT_SUPPORTED;
}
void eppp_sdio_host_deinit(void)
{
}
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config)
{
return ESP_ERR_NOT_SUPPORTED;
}
#endif // CONFIG_SOC_SDIO_SLAVE_SUPPORTED

View File

@ -1,174 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "driver/sdio_slave.h"
#include "eppp_sdio.h"
#include "esp_check.h"
#if CONFIG_EPPP_LINK_DEVICE_SDIO_SLAVE
#define BUFFER_NUM 4
#define BUFFER_SIZE SDIO_PAYLOAD
static const char *TAG = "eppp_sdio_slave";
static DMA_ATTR uint8_t sdio_slave_rx_buffer[BUFFER_NUM][BUFFER_SIZE];
static DMA_ATTR uint8_t sdio_slave_tx_buffer[SDIO_PAYLOAD];
static int s_slave_request = 0;
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
{
if (s_slave_request != REQ_INIT) {
// silently skip the Tx if the SDIO not fully initialized
return ESP_OK;
}
memcpy(sdio_slave_tx_buffer, buffer, len);
size_t send_len = SDIO_ALIGN(len);
if (send_len > len) {
// pad with SOF's if the size is not 4 bytes aligned
memset(&sdio_slave_tx_buffer[len], PPP_SOF, send_len - len);
}
ESP_LOG_BUFFER_HEXDUMP(TAG, sdio_slave_tx_buffer, send_len, ESP_LOG_VERBOSE);
esp_err_t ret = sdio_slave_transmit(sdio_slave_tx_buffer, send_len);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "sdio slave transmit error, ret : 0x%x", ret);
// to inform the upper layers
return ESP_ERR_NO_MEM;
}
return ESP_OK;
}
static esp_err_t slave_reset(void)
{
esp_err_t ret = ESP_OK;
ESP_LOGI(TAG, "SDIO slave reset");
sdio_slave_stop();
ESP_GOTO_ON_ERROR(sdio_slave_reset(), err, TAG, "slave reset failed");
ESP_GOTO_ON_ERROR(sdio_slave_start(), err, TAG, "slave start failed");
while (1) {
sdio_slave_buf_handle_t handle;
ret = sdio_slave_send_get_finished(&handle, 0);
if (ret == ESP_ERR_TIMEOUT) {
break;
}
ESP_GOTO_ON_ERROR(ret, err, TAG, "slave-get-finished failed");
ESP_GOTO_ON_ERROR(sdio_slave_recv_load_buf(handle), err, TAG, "slave-load-buf failed");
}
err:
return ret;
}
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
{
if (s_slave_request == REQ_RESET) {
ESP_LOGD(TAG, "request: %x", s_slave_request);
slave_reset();
s_slave_request = REQ_INIT;
}
sdio_slave_buf_handle_t handle;
size_t length;
uint8_t *ptr;
esp_err_t ret = sdio_slave_recv_packet(&handle, pdMS_TO_TICKS(1000));
if (ret == ESP_ERR_TIMEOUT) {
return ESP_OK;
}
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
again:
ptr = sdio_slave_recv_get_buf(handle, &length);
esp_netif_receive(netif, ptr, length, NULL);
if (sdio_slave_recv_load_buf(handle) != ESP_OK) {
ESP_LOGE(TAG, "Failed to recycle packet buffer");
return ESP_FAIL;
}
if (ret == ESP_ERR_NOT_FINISHED) {
ret = sdio_slave_recv_packet(&handle, 0);
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
goto again;
}
}
ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, length, ESP_LOG_VERBOSE);
return ESP_OK;
}
ESP_LOGE(TAG, "Error when receiving packet %d", ret);
return ESP_FAIL;
}
static void event_cb(uint8_t pos)
{
ESP_EARLY_LOGI(TAG, "SDIO event: %d", pos);
if (pos == SLAVE_INTR) {
s_slave_request = sdio_slave_read_reg(SLAVE_REG_REQ);
sdio_slave_write_reg(SLAVE_REG_REQ, 0);
}
}
esp_err_t eppp_sdio_slave_init(void)
{
sdio_slave_config_t config = {
.sending_mode = SDIO_SLAVE_SEND_PACKET,
.send_queue_size = BUFFER_NUM,
.recv_buffer_size = BUFFER_SIZE,
.event_cb = event_cb,
};
esp_err_t ret = sdio_slave_initialize(&config);
if (ret != ESP_OK) {
return ret;
}
for (int i = 0; i < BUFFER_NUM; i++) {
sdio_slave_buf_handle_t handle = sdio_slave_recv_register_buf(sdio_slave_rx_buffer[i]);
if (handle == NULL) {
sdio_slave_deinit();
return ESP_FAIL;
}
ret = sdio_slave_recv_load_buf(handle);
if (ret != ESP_OK) {
sdio_slave_deinit();
return ESP_FAIL;
}
}
sdio_slave_set_host_intena(SDIO_SLAVE_HOSTINT_SEND_NEW_PACKET); // only need one interrupt to notify of a new packet
ret = sdio_slave_start();
if (ret != ESP_OK) {
sdio_slave_deinit();
return ESP_FAIL;
}
return ESP_OK;
}
void eppp_sdio_slave_deinit(void)
{
sdio_slave_stop();
sdio_slave_deinit();
}
#else // SOC_SDIO_SLAVE NOT-SUPPORTED
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
{
return ESP_ERR_NOT_SUPPORTED;
}
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
{
return ESP_ERR_NOT_SUPPORTED;
}
void eppp_sdio_slave_deinit(void)
{
}
esp_err_t eppp_sdio_slave_init(void)
{
return ESP_ERR_NOT_SUPPORTED;
}
#endif // CONFIG_SOC_SDIO_SLAVE_SUPPORTED

View File

@ -104,13 +104,11 @@ void app_main(void)
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
#if CONFIG_EPPP_LINK_DEVICE_SPI
config.transport = EPPP_TRANSPORT_SPI;
#elif CONFIG_EPPP_LINK_DEVICE_UART
#else
config.transport = EPPP_TRANSPORT_UART;
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
#else
config.transport = EPPP_TRANSPORT_SDIO;
#endif
esp_netif_t *eppp_netif = eppp_connect(&config);
if (eppp_netif == NULL) {

View File

@ -128,21 +128,16 @@ void app_main(void)
ESP_ERROR_CHECK(ret);
init_network_interface(); // WiFi station if withing SoC capabilities (otherwise a placeholder)
// ESP_ERROR_CHECK(esp_netif_init());
// ESP_ERROR_CHECK(esp_event_loop_create_default());
eppp_config_t config = EPPP_DEFAULT_SERVER_CONFIG();
#if CONFIG_EPPP_LINK_DEVICE_SPI
config.transport = EPPP_TRANSPORT_SPI;
#elif CONFIG_EPPP_LINK_DEVICE_UART
#else
config.transport = EPPP_TRANSPORT_UART;
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
config.transport = EPPP_TRANSPORT_SDIO;
#endif // transport device
#endif
esp_netif_t *eppp_netif = eppp_listen(&config);
if (eppp_netif == NULL) {
ESP_LOGE(TAG, "Failed to setup connection");

View File

@ -1,6 +1,6 @@
version: 0.2.0
version: 0.1.1
url: https://github.com/espressif/esp-protocols/tree/master/components/eppp_link
description: The component provides a general purpose PPP connectivity, typically used as WiFi-PPP router
dependencies:
idf: '>=5.2'
espressif/esp_serial_slave_link: "^1.1.0"
idf:
version: '>=5.2'

View File

@ -28,16 +28,7 @@
.rx_io = 26, \
.queue_size = 16, \
.rx_buffer_size = 1024, \
}, \
.sdio = { \
.width = 4, \
.clk = 18, \
.cmd = 19, \
.d0 = 49, \
.d1 = 50, \
.d2 = 16, \
.d3 = 17, \
}, \
}, \
. task = { \
.run_task = true, \
.stack_size = 4096, \
@ -62,7 +53,6 @@ typedef enum eppp_type {
typedef enum eppp_transport {
EPPP_TRANSPORT_UART,
EPPP_TRANSPORT_SPI,
EPPP_TRANSPORT_SDIO,
} eppp_transport_t;
@ -91,16 +81,6 @@ typedef struct eppp_config_t {
int rx_buffer_size;
} uart;
struct eppp_config_sdio_s {
int width;
int clk;
int cmd;
int d0;
int d1;
int d2;
int d3;
} sdio;
struct eppp_config_task_s {
bool run_task;
int stack_size;

View File

@ -16,9 +16,9 @@ class.
### USB DTE support
For USB enabled targets (ESP32-S2, ESP32-S3, or ESP32-P4), it is possible to connect to the modem device via USB.
For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to the modem device via USB.
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
2. Connect the modem USB signals to your ESP chip (pin 19 (DATA-) and 20 (DATA+) for ESP32-S2/S3).
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
USB example uses Quactel BG96 modem device. BG96 needs a positive pulse on its PWK pin to boot-up.

View File

@ -10,7 +10,7 @@ menu "Example Configuration"
Connect to modem via UART.
config EXAMPLE_SERIAL_CONFIG_USB
bool "USB"
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
endchoice
@ -36,11 +36,6 @@ menu "Example Configuration"
bool "BG96"
help
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
config EXAMPLE_MODEM_DEVICE_EC20
depends on EXAMPLE_SERIAL_CONFIG_USB
bool "EC20"
help
Quectel EC20 is a series of LTE Cat M4 module.
config EXAMPLE_MODEM_DEVICE_SIM7000
depends on EXAMPLE_SERIAL_CONFIG_UART
bool "SIM7000"

View File

@ -6,7 +6,7 @@ dependencies:
version: "^1.0.0"
override_path: "../../../"
espressif/esp_modem_usb_dte:
version: "^1.2.0"
version: "^1.1.0"
rules:
- if: "idf_version >=4.4"
- if: "target in [esp32s2, esp32s3, esp32p4]"
- if: "target in [esp32s2, esp32s3]"

View File

@ -160,9 +160,6 @@ extern "C" void app_main(void)
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_BG96_USB_CONFIG();
#elif CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the EC20 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_EC20_USB_CONFIG();
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_SIM7600_USB_CONFIG();
@ -183,7 +180,7 @@ extern "C" void app_main(void)
});
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
std::unique_ptr<DCE> dce = create_BG96_dce(&dce_config, dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_A7670 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_A7670 == 1
std::unique_ptr<DCE> dce = create_SIM7600_dce(&dce_config, dte, esp_netif);
#else
#error USB modem not selected

View File

@ -1,2 +0,0 @@
CONFIG_IDF_TARGET="esp32p4"
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y

View File

@ -11,9 +11,9 @@ See the README.md file in the upper level `pppos` directory for more information
### USB DTE support
For USB enabled targets (ESP32-S2, ESP32-S3, or ESP32-P4), it is possible to connect to the modem device via USB.
For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to the modem device via USB.
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
2. Connect the modem USB signals to your ESP chip (pin 19 (DATA-) and 20 (DATA+) for ESP32-S2/S3).
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
USB example uses Quactel BG96 modem device. BG96 needs a positive pulse on its PWK pin to boot-up.

View File

@ -9,7 +9,7 @@ menu "Example Configuration"
Connect to modem via UART.
config EXAMPLE_SERIAL_CONFIG_USB
bool "USB"
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
endchoice
@ -29,11 +29,6 @@ menu "Example Configuration"
bool "BG96"
help
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
config EXAMPLE_MODEM_DEVICE_EC20
depends on EXAMPLE_SERIAL_CONFIG_USB
bool "EC20"
help
Quectel EC20 is a series of LTE Cat M4 module.
config EXAMPLE_MODEM_DEVICE_SIM7000
depends on EXAMPLE_SERIAL_CONFIG_UART
bool "SIM7000"

View File

@ -6,7 +6,7 @@ dependencies:
version: "^1.0.0"
override_path: "../../../"
espressif/esp_modem_usb_dte:
version: "^1.2.0"
version: "^1.1.0"
rules:
- if: "idf_version >=4.4"
- if: "target in [esp32s2, esp32s3, esp32p4]"
- if: "target in [esp32s2, esp32s3]"

View File

@ -219,10 +219,6 @@ void app_main(void)
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_BG96_USB_CONFIG();
esp_modem_dce_device_t usb_dev_type = ESP_MODEM_DCE_BG96;
#elif CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the EC20 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_EC20_USB_CONFIG();
esp_modem_dce_device_t usb_dev_type = ESP_MODEM_DCE_EC20;
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
struct esp_modem_usb_term_config usb_config = ESP_MODEM_SIM7600_USB_CONFIG();

View File

@ -1,2 +0,0 @@
CONFIG_IDF_TARGET="esp32p4"
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y

View File

@ -52,7 +52,6 @@ typedef enum esp_modem_dce_device {
ESP_MODEM_DCE_SIM7070,
ESP_MODEM_DCE_SIM7000,
ESP_MODEM_DCE_BG96,
ESP_MODEM_DCE_EC20,
ESP_MODEM_DCE_SIM800,
ESP_MODEM_DCE_CUSTOM
} esp_modem_dce_device_t;

View File

@ -3,6 +3,6 @@ commitizen:
bump_message: 'bump(mqtt_cxx): $current_version -> $new_version'
pre_bump_hooks: python ../../ci/changelog.py esp_mqtt_cxx
tag_format: mqtt_cxx-v$version
version: 0.4.0
version: 0.3.0
version_files:
- idf_component.yml

View File

@ -1,11 +1,5 @@
# Changelog
## [0.4.0](https://github.com/espressif/esp-protocols/commits/mqtt_cxx-v0.4.0)
### Bug Fixes
- Adds missing configuration fields ([d4c6d5ed](https://github.com/espressif/esp-protocols/commit/d4c6d5ed))
## [0.3.0](https://github.com/espressif/esp-protocols/commits/mqtt_cxx-v0.3.0)
### Bug Fixes

View File

@ -1,4 +1,4 @@
version: "0.4.0"
version: "0.3.0"
description: C++ APIs for ESP-MQTT library
url: https://github.com/espressif/esp-protocols/tree/master/components/esp_mqtt_cxx
issues: https://github.com/espressif/esp-protocols/issues

View File

@ -95,9 +95,7 @@ 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 {
@ -206,8 +204,6 @@ 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;
@ -504,10 +500,6 @@ 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) {
@ -541,13 +533,6 @@ 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);
@ -683,11 +668,6 @@ 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;
@ -696,9 +676,7 @@ 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) {
@ -957,9 +935,7 @@ static void esp_websocket_client_task(void *pv)
client->run = true;
//get transport by scheme
if (client->transport == NULL && client->config->ext_transport == NULL) {
client->transport = esp_transport_list_get_transport(client->transport_list, client->config->scheme);
}
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");
@ -972,7 +948,6 @@ 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) {
@ -1107,7 +1082,6 @@ 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;
@ -1126,13 +1100,9 @@ esp_err_t esp_websocket_client_start(esp_websocket_client_handle_t client)
ESP_LOGE(TAG, "The client has started");
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 (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",
@ -1141,7 +1111,6 @@ 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;
}
@ -1309,43 +1278,6 @@ 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,

View File

@ -6,6 +6,7 @@ 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)

View File

@ -1,4 +1,6 @@
idf_component_register(SRCS "websocket_linux.c"
idf_component_register(SRCS "main.c"
INCLUDE_DIRS
"."
REQUIRES esp_websocket_client protocol_examples_common)
if(CONFIG_GCOV_ENABLED)

View File

@ -3,13 +3,20 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <esp_log.h>
#include <stdio.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";
@ -25,9 +32,6 @@ 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;
@ -62,9 +66,6 @@ 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;
}
}

View File

@ -10,6 +10,12 @@ 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}"

View File

@ -0,0 +1,30 @@
-----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-----

View File

@ -19,7 +19,6 @@
#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"
@ -74,9 +73,6 @@ 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;
@ -125,9 +121,6 @@ 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;
}
}
@ -166,12 +159,8 @@ 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
// 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; */
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;
#endif
#if CONFIG_WS_OVER_TLS_SKIP_COMMON_NAME_CHECK

View File

@ -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/server_cert.pem', keyfile='main/certs/server/server_key.pem')
ssl_context.load_cert_chain(certfile='main/certs/server_cert.pem', keyfile='main/certs/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

View File

@ -36,8 +36,6 @@ 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;
@ -120,7 +118,6 @@ 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) */
@ -130,7 +127,6 @@ 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;
/**
@ -420,29 +416,6 @@ 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
*

View File

@ -3,6 +3,6 @@ commitizen:
bump_message: 'bump(wifi_remote): $current_version -> $new_version'
pre_bump_hooks: python ../../ci/changelog.py esp_wifi_remote
tag_format: wifi_remote-v$version
version: 0.3.0
version: 0.2.3
version_files:
- idf_component.yml

View File

@ -1,12 +1,5 @@
# Changelog
## [0.3.0](https://github.com/espressif/esp-protocols/commits/wifi_remote-v0.3.0)
### Features
- add esp_wifi_internal_tx_by_ref ([ba35d14e](https://github.com/espressif/esp-protocols/commit/ba35d14e))
- Make wifi_remote depend on esp_hosted ([ac9972aa](https://github.com/espressif/esp-protocols/commit/ac9972aa))
## [0.2.3](https://github.com/espressif/esp-protocols/commits/wifi_remote-v0.2.3)
### Bug Fixes

View File

@ -59,11 +59,6 @@ WEAK void esp_wifi_internal_free_rx_buffer(void *buffer)
free(buffer);
}
WEAK esp_err_t esp_wifi_internal_tx_by_ref(wifi_interface_t ifx, void *buffer, size_t len, void *netstack_buf)
{
return esp_wifi_internal_tx(ifx, buffer, (uint16_t)len);
}
WEAK int esp_wifi_internal_tx(wifi_interface_t ifx, void *buffer, uint16_t len)
{
if (ifx == WIFI_IF_STA && s_tx_cb[0]) {

View File

@ -1,4 +1,4 @@
version: 0.3.0
version: 0.2.3
url: https://github.com/espressif/esp-protocols/tree/master/components/esp_wifi_remote
description: Utility wrapper for esp_wifi functionality on remote targets
dependencies:
@ -6,5 +6,5 @@ dependencies:
version: '>=0.1'
idf:
version: '>=5.3'
espressif/esp_hosted:
version: '>=0.0.6'
# espressif/esp_hosted:
# version: '*'

View File

@ -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.4.0
version: 1.3.2
version_files:
- idf_component.yml

View File

@ -1,39 +1,5 @@
# 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

View File

@ -12,9 +12,8 @@ endif()
idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "linux")
set(dependencies esp_netif_linux esp_event)
set(private_dependencies esp_timer console esp_system)
set(srcs "mdns.c" ${MDNS_NETWORKING} ${MDNS_CONSOLE})
set(dependencies esp_netif_linux esp_timer esp_system)
set(srcs "mdns.c" ${MDNS_NETWORKING})
else()
set(dependencies lwip console esp_netif)
set(private_dependencies esp_timer esp_wifi)

View File

@ -1,4 +1,4 @@
version: "1.4.0"
version: "1.3.2"
description: mDNS
url: https://github.com/espressif/esp-protocols/tree/master/components/mdns
dependencies:

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -9,7 +9,6 @@
#include "argtable3/argtable3.h"
#include "mdns.h"
#include "mdns_private.h"
#include "inttypes.h"
static const char *ip_protocol_str[] = {"V4", "V6", "MAX"};
@ -19,10 +18,7 @@ static void mdns_print_results(mdns_result_t *results)
mdns_ip_addr_t *a = NULL;
int i = 1;
while (r) {
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);
}
printf("%d: Interface: %s, Type: %s\n", i++, esp_netif_get_ifkey(r->esp_netif), ip_protocol_str[r->ip_protocol]);
if (r->instance_name) {
printf(" PTR : %s\n", r->instance_name);
}
@ -30,7 +26,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] ", (int)r->txt_count);
printf(" TXT : [%u] ", r->txt_count);
for (size_t t = 0; t < r->txt_count; t++) {
printf("%s=%s; ", r->txt[t].key, r->txt[t].value);
}
@ -520,7 +516,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->count) {
if (mdns_init_args.instance->sval[0]) {
ESP_ERROR_CHECK( mdns_instance_name_set(mdns_init_args.instance->sval[0]) );
printf("MDNS: Instance: %s\n", mdns_init_args.instance->sval[0]);
}
@ -697,7 +693,6 @@ 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;
@ -719,11 +714,6 @@ 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);
@ -734,8 +724,7 @@ static int cmd_mdns_service_add(int argc, char **argv)
}
}
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) );
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) );
free(items);
return 0;
}
@ -746,7 +735,6 @@ 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);
@ -762,10 +750,8 @@ 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;
@ -782,16 +768,7 @@ static int cmd_mdns_service_remove(int argc, char **argv)
return 1;
}
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) );
ESP_ERROR_CHECK( mdns_service_remove(mdns_remove_args.service->sval[0], mdns_remove_args.proto->sval[0]) );
return 0;
}
@ -799,9 +776,7 @@ 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.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);
mdns_remove_args.end = arg_end(2);
const esp_console_cmd_t cmd_remove = {
.command = "mdns_service_remove",
@ -818,8 +793,6 @@ 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;
@ -835,20 +808,8 @@ 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;
}
@ -857,9 +818,7 @@ 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.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);
mdns_service_instance_set_args.end = arg_end(2);
const esp_console_cmd_t cmd_add = {
.command = "mdns_service_instance_set",
@ -876,8 +835,6 @@ 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;
@ -894,19 +851,7 @@ static int cmd_mdns_service_port_set(int argc, char **argv)
return 1;
}
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;
}
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]) );
return 0;
}
@ -915,8 +860,6 @@ 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 = {
@ -933,8 +876,6 @@ 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;
@ -952,16 +893,7 @@ 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) {
@ -970,7 +902,7 @@ static int cmd_mdns_service_txt_replace(int argc, char **argv)
}
}
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) );
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) );
free(items);
return 0;
}
@ -979,10 +911,8 @@ 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(5);
mdns_txt_replace_args.end = arg_end(2);
const esp_console_cmd_t cmd_txt_set = {
.command = "mdns_service_txt_replace",
@ -998,8 +928,6 @@ 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;
@ -1017,18 +945,8 @@ 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_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]) );
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]) );
return 0;
}
@ -1038,9 +956,7 @@ 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.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);
mdns_txt_set_args.end = arg_end(2);
const esp_console_cmd_t cmd_txt_set = {
.command = "mdns_service_txt_set",
@ -1057,8 +973,6 @@ 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;
@ -1074,15 +988,8 @@ static int cmd_mdns_service_txt_remove(int argc, char **argv)
printf("ERROR: Bad arguments!\n");
return 1;
}
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]) );
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]) );
return 0;
}
@ -1091,8 +998,6 @@ 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 = {
@ -1125,294 +1030,6 @@ 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();
@ -1428,14 +1045,6 @@ 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

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -187,6 +187,15 @@ 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,
@ -437,6 +446,41 @@ 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;

View File

@ -1,16 +1,11 @@
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS "../.." "../../../../common_components/linux_compat")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
if(${IDF_TARGET} STREQUAL "linux")
set(EXTRA_COMPONENT_DIRS "../../../../common_components/linux_compat")
set(COMPONENTS main)
endif()
set(COMPONENTS main esp_netif_linux)
project(mdns_host)
# 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)
# Enable sanitizers for mdns implementation
idf_component_get_property(mdns mdns COMPONENT_LIB)
target_link_options(${mdns} INTERFACE -fsanitize=address -fsanitize=undefined)
endif()

View File

@ -1,8 +1,2 @@
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()
idf_component_register(SRCS esp_netif_linux.c
INCLUDE_DIRS include $ENV{IDF_PATH}/components/esp_netif/include)

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -15,12 +15,9 @@
#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 {
@ -53,7 +50,6 @@ 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);
}
}
@ -107,7 +103,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) {
ESP_LOGD(TAG, "AF_INET6: %s: %s\n", tmp->ifa_name, addr);
printf("AF_INET6: %s: %s\n", tmp->ifa_name, addr);
memcpy(if_ip6->addr, &pAddr->sin6_addr, 4 * 4);
break;
}
@ -177,21 +173,3 @@ 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;
}

View File

@ -1,130 +0,0 @@
# 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

View File

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

View File

@ -12,10 +12,4 @@ 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

View File

@ -1,7 +0,0 @@
dependencies:
idf: ">=5.0"
espressif/mdns:
version: "^1.0.0"
override_path: "../../.."
protocol_examples_common:
path: ${IDF_PATH}/examples/common_components/protocol_examples_common

View File

@ -1,30 +1,16 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 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);
@ -44,83 +30,37 @@ 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(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));
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));
#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
#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"}
};
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));
ESP_ERROR_CHECK(mdns_service_add("myesp-service2", "_http", "_tcp", 80, serviceTxtData, 3));
#endif
vTaskDelay(pdMS_TO_TICKS(10000));
query_mdns_host("david-work");
vTaskDelay(pdMS_TO_TICKS(1000));
#endif
esp_netif_destroy(sta);
mdns_free();
ESP_LOGI(TAG, "Exit");
return 0;
}

View File

@ -1,180 +0,0 @@
# 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'])

View File

@ -1,4 +0,0 @@
CONFIG_IDF_TARGET="linux"
CONFIG_TEST_HOSTNAME="myesp"
CONFIG_MDNS_ENABLE_DEBUG_PRINTS=y
CONFIG_MDNS_RESPOND_REVERSE_QUERIES=y

View File

@ -1,4 +0,0 @@
CONFIG_IDF_TARGET="linux"
CONFIG_ESP_EVENT_POST_FROM_ISR=n
CONFIG_MDNS_ENABLE_CONSOLE_CLI=y
CONFIG_TEST_CONSOLE=y

View File

@ -1 +0,0 @@
CONFIG_IDF_TARGET="esp32"

View File

@ -1,6 +1,9 @@
CONFIG_TEST_NETIF_NAME="eth0"
CONFIG_ESP_EVENT_POST_FROM_ISR=n
CONFIG_IDF_TARGET="linux"
CONFIG_MDNS_NETWORKING_SOCKET=y
CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES=y
CONFIG_TEST_NETIF_NAME="eth0"
CONFIG_TEST_HOSTNAME="myesp"
CONFIG_MDNS_PREDEF_NETIF_STA=n
CONFIG_MDNS_PREDEF_NETIF_AP=n
CONFIG_MDNS_ENABLE_DEBUG_PRINTS=y
CONFIG_MDNS_RESPOND_REVERSE_QUERIES=y

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@ -9,7 +9,6 @@
#include <stdlib.h>
#include <unistd.h>
#include "esp32_mock.h"
#include "esp_log.h"
void *g_queue;
int g_queue_send_shall_fail = 0;
@ -112,12 +111,3 @@ 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;
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -45,6 +45,11 @@
#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

View File

@ -1,10 +1,9 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 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"
@ -91,7 +90,6 @@ 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
@ -144,153 +142,12 @@ 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)

View File

@ -91,14 +91,10 @@ 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_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`: 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.
* `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.
If the client handle is needed in the event handler it can be accessed through the pointer passed to the event handler: