Skip to content

Commit e425a3c

Browse files
authored
Merge pull request #617 from david-cermak/feat/mdns_console_host
[mdns]: Add linux console functional tests
2 parents f198967 + 50d059a commit e425a3c

File tree

21 files changed

+444
-75
lines changed

21 files changed

+444
-75
lines changed

.github/workflows/mdns__host-tests.yml

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,30 @@ on:
1010
jobs:
1111
host_test_mdns:
1212
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
13-
name: Host test
13+
name: Host test build
1414
runs-on: ubuntu-22.04
15-
container: espressif/idf:release-v5.1
15+
container: espressif/idf:release-v5.3
1616

1717
steps:
1818
- name: Checkout esp-protocols
1919
uses: actions/checkout@v4
2020
with:
21-
path: esp-protocols
21+
path: protocols
2222

2323
- name: Build and Test
2424
shell: bash
2525
run: |
26-
apt-get update && apt-get install -y dnsutils gcc g++
2726
. ${IDF_PATH}/export.sh
28-
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/host_test
29-
idf.py build
30-
./build/mdns_host.elf &
31-
dig +short -p 5353 @224.0.0.251 myesp.local > ip.txt
32-
cat ip.txt | xargs dig +short -p 5353 @224.0.0.251 -x
33-
cat ip.txt
27+
python -m pip install idf-build-apps dnspython pytest pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf
28+
cd $GITHUB_WORKSPACE/protocols
29+
# Build host tests app (with all configs and targets supported)
30+
python ./ci/build_apps.py components/mdns/tests/host_test/
31+
cd components/mdns/tests/host_test
32+
# First run the linux_app and send a quick A query and a reverse query
33+
./build_linux_app/mdns_host.elf &
34+
python dnsfixture.py A myesp.local --ip_only | xargs python dnsfixture.py X
35+
# Next we run the pytest (using the console app)
36+
pytest
3437
3538
build_afl_host_test_mdns:
3639
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
idf_component_register()

common_components/linux_compat/freertos/freertos_linux.c

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -12,8 +12,24 @@
1212
#include <stdlib.h>
1313
#include <string.h>
1414
#include "osal/osal_api.h"
15+
#include <semaphore.h>
16+
17+
typedef struct task_notifiers {
18+
sem_t sem;
19+
TaskHandle_t id;
20+
} task_notifiers_t;
21+
22+
typedef struct pthread_params {
23+
void *const param;
24+
TaskFunction_t task;
25+
bool started;
26+
TaskHandle_t handle;
27+
} pthread_params_t;
1528

1629
static uint64_t s_semaphore_data = 0;
30+
static task_notifiers_t *s_notifiers;
31+
static int s_threads = 0;
32+
pthread_mutex_t s_mutex;
1733

1834
typedef enum queue_type_tag {
1935
MUTEX_REC,
@@ -89,6 +105,7 @@ BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue)
89105
}
90106
return pdFALSE;
91107
}
108+
92109
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
93110
{
94111
struct generic_queue_handle *h = xQueue;
@@ -99,7 +116,6 @@ BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
99116
return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY);
100117
}
101118

102-
103119
BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
104120
{
105121
struct generic_queue_handle *h = xQueue;
@@ -110,9 +126,6 @@ BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
110126
return pdFALSE;
111127
}
112128

113-
114-
115-
116129
void vQueueDelete( QueueHandle_t xQueue )
117130
{
118131
struct generic_queue_handle *h = xQueue;
@@ -128,8 +141,7 @@ void vQueueDelete( QueueHandle_t xQueue )
128141

129142
QueueHandle_t xSemaphoreCreateBinary(void)
130143
{
131-
QueueHandle_t sempaphore = xQueueCreate(1, 1);
132-
return sempaphore;
144+
return xQueueCreate(1, 1);
133145
}
134146

135147
QueueHandle_t xSemaphoreCreateMutex(void)
@@ -145,6 +157,13 @@ QueueHandle_t xSemaphoreCreateRecursiveMutex(void)
145157

146158
void vTaskDelete(TaskHandle_t *task)
147159
{
160+
for (int i = 0; i < s_threads; ++i) {
161+
if (task == s_notifiers[i].id) {
162+
sem_destroy(&s_notifiers[i].sem);
163+
s_notifiers[i].id = 0;
164+
}
165+
}
166+
148167
if (task == NULL) {
149168
pthread_exit(0);
150169
}
@@ -171,14 +190,21 @@ void vTaskDelay( const TickType_t xTicksToDelay )
171190

172191
void *pthread_task(void *params)
173192
{
174-
struct {
175-
void *const param;
176-
TaskFunction_t task;
177-
bool started;
178-
} *pthread_params = params;
193+
pthread_params_t *pthread_params = params;
179194

180195
void *const param = pthread_params->param;
181196
TaskFunction_t task = pthread_params->task;
197+
198+
pthread_params->handle = xTaskGetCurrentTaskHandle();
199+
if (s_threads == 0) {
200+
pthread_mutex_init(&s_mutex, NULL);
201+
}
202+
pthread_mutex_lock(&s_mutex);
203+
s_notifiers = realloc(s_notifiers, sizeof(struct task_notifiers) * (++s_threads));
204+
assert(s_notifiers);
205+
s_notifiers[s_threads - 1].id = pthread_params->handle;
206+
sem_init(&s_notifiers[s_threads - 1].sem, 0, 0);
207+
pthread_mutex_unlock(&s_mutex);
182208
pthread_params->started = true;
183209

184210
task(param);
@@ -198,37 +224,46 @@ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
198224
return pdTRUE;
199225
}
200226

201-
202227
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask)
203228
{
204229
pthread_t new_thread = (pthread_t)NULL;
205230
pthread_attr_t attr;
206-
struct {
207-
void *const param;
208-
TaskFunction_t task;
209-
bool started;
210-
} pthread_params = { .param = pvParameters, .task = pvTaskCode};
231+
pthread_params_t pthread_params = { .param = pvParameters, .task = pvTaskCode};
232+
211233
int res = pthread_attr_init(&attr);
212234
assert(res == 0);
213235
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
214236
assert(res == 0);
215237
res = pthread_create(&new_thread, &attr, pthread_task, &pthread_params);
216238
assert(res == 0);
217239

218-
if (pvCreatedTask) {
219-
*pvCreatedTask = (void *)new_thread;
220-
}
221-
222240
// just wait till the task started so we can unwind params from the stack
223241
while (pthread_params.started == false) {
224242
usleep(1000);
225243
}
244+
if (pvCreatedTask) {
245+
*pvCreatedTask = pthread_params.handle;
246+
}
247+
226248
return pdTRUE;
227249
}
228250

229251
void xTaskNotifyGive(TaskHandle_t task)
230252
{
231-
253+
int i = 0;
254+
while (true) {
255+
pthread_mutex_lock(&s_mutex);
256+
if (task == s_notifiers[i].id) {
257+
sem_post(&s_notifiers[i].sem);
258+
pthread_mutex_unlock(&s_mutex);
259+
return;
260+
}
261+
pthread_mutex_unlock(&s_mutex);
262+
if (++i == s_threads) {
263+
i = 0;
264+
}
265+
usleep(1000);
266+
}
232267
}
233268

234269
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time )
@@ -238,7 +273,7 @@ BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear,
238273

239274
TaskHandle_t xTaskGetCurrentTaskHandle(void)
240275
{
241-
return NULL;
276+
return (TaskHandle_t)pthread_self();
242277
}
243278

244279
EventGroupHandle_t xEventGroupCreate( void )
@@ -270,3 +305,22 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits
270305
{
271306
return osal_signal_wait(xEventGroup, uxBitsToWaitFor, xWaitForAllBits, xTicksToWait);
272307
}
308+
309+
void ulTaskNotifyTake(bool clear_on_exit, uint32_t xTicksToWait)
310+
{
311+
TaskHandle_t task = xTaskGetCurrentTaskHandle();
312+
int i = 0;
313+
while (true) {
314+
pthread_mutex_lock(&s_mutex);
315+
if (task == s_notifiers[i].id) {
316+
pthread_mutex_unlock(&s_mutex);
317+
sem_wait(&s_notifiers[i].sem);
318+
return;
319+
}
320+
pthread_mutex_unlock(&s_mutex);
321+
if (++i == s_threads) {
322+
i = 0;
323+
}
324+
usleep(1000);
325+
}
326+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Unlicense OR CC0-1.0
5+
*/
6+
#pragma once

common_components/linux_compat/freertos/include/freertos/task.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@
1111
extern "C" {
1212
#endif
1313

14+
#define tskNO_AFFINITY ( ( BaseType_t ) 0x7FFFFFFF )
1415
#define TaskHandle_t TaskHandle_t
1516
#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
1617

1718
void vTaskDelay( const TickType_t xTicksToDelay );
1819

1920
void xTaskNotifyGive(TaskHandle_t task);
2021

22+
void ulTaskNotifyTake(bool stuff, uint32_t timeout);
23+
2124
TaskHandle_t xTaskGetCurrentTaskHandle(void);
2225

2326
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time );

components/mdns/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ endif()
1212

1313
idf_build_get_property(target IDF_TARGET)
1414
if(${target} STREQUAL "linux")
15-
set(dependencies esp_netif_linux esp_timer esp_system)
16-
set(srcs "mdns.c" ${MDNS_NETWORKING})
15+
set(dependencies esp_netif_linux esp_event)
16+
set(private_dependencies esp_timer console esp_system)
17+
set(srcs "mdns.c" ${MDNS_NETWORKING} ${MDNS_CONSOLE})
1718
else()
1819
set(dependencies lwip console esp_netif)
1920
set(private_dependencies esp_timer esp_wifi)

components/mdns/mdns.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,17 @@ static void _mdns_browse_send(mdns_browse_t *browse);
2929
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
3030
#include "esp_eth.h"
3131
#endif
32-
#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP
33-
#include "esp_wifi.h"
34-
#endif
3532

3633
#if ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(5, 1, 0)
3734
#define MDNS_ESP_WIFI_ENABLED CONFIG_SOC_WIFI_SUPPORTED
3835
#else
3936
#define MDNS_ESP_WIFI_ENABLED CONFIG_ESP_WIFI_ENABLED
4037
#endif
4138

39+
#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP)
40+
#include "esp_wifi.h"
41+
#endif
42+
4243
#ifdef MDNS_ENABLE_DEBUG
4344
void mdns_debug_packet(const uint8_t *data, size_t len);
4445
#endif
@@ -4411,7 +4412,7 @@ void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base,
44114412
}
44124413

44134414
esp_netif_dhcp_status_t dcst;
4414-
#if MDNS_ESP_WIFI_ENABLED
4415+
#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP)
44154416
if (event_base == WIFI_EVENT) {
44164417
switch (event_id) {
44174418
case WIFI_EVENT_STA_CONNECTED:

components/mdns/mdns_console.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -9,6 +9,7 @@
99
#include "argtable3/argtable3.h"
1010
#include "mdns.h"
1111
#include "mdns_private.h"
12+
#include "inttypes.h"
1213

1314
static const char *ip_protocol_str[] = {"V4", "V6", "MAX"};
1415

@@ -26,7 +27,7 @@ static void mdns_print_results(mdns_result_t *results)
2627
printf(" SRV : %s.local:%u\n", r->hostname, r->port);
2728
}
2829
if (r->txt_count) {
29-
printf(" TXT : [%u] ", r->txt_count);
30+
printf(" TXT : [%u] ", (int)r->txt_count);
3031
for (size_t t = 0; t < r->txt_count; t++) {
3132
printf("%s=%s; ", r->txt[t].key, r->txt[t].value);
3233
}
@@ -516,7 +517,7 @@ static int cmd_mdns_init(int argc, char **argv)
516517
printf("MDNS: Hostname: %s\n", mdns_init_args.hostname->sval[0]);
517518
}
518519

519-
if (mdns_init_args.instance->sval[0]) {
520+
if (mdns_init_args.instance->count) {
520521
ESP_ERROR_CHECK( mdns_instance_name_set(mdns_init_args.instance->sval[0]) );
521522
printf("MDNS: Instance: %s\n", mdns_init_args.instance->sval[0]);
522523
}
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
cmake_minimum_required(VERSION 3.5)
22

3-
set(EXTRA_COMPONENT_DIRS "../.." "../../../../common_components/linux_compat")
43

54
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
6-
set(COMPONENTS main esp_netif_linux)
5+
if(${IDF_TARGET} STREQUAL "linux")
6+
set(EXTRA_COMPONENT_DIRS "../../../../common_components/linux_compat")
7+
set(COMPONENTS main)
8+
endif()
9+
710
project(mdns_host)
811

9-
# Enable sanitizers for mdns implementation
12+
# Enable sanitizers only without console (we'd see some leaks on argtable when console exits)
13+
if(NOT CONFIG_TEST_CONSOLE AND CONFIG_IDF_TARGET_LINUX)
1014
idf_component_get_property(mdns mdns COMPONENT_LIB)
1115
target_link_options(${mdns} INTERFACE -fsanitize=address -fsanitize=undefined)
16+
endif()
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
1-
idf_component_register(SRCS esp_netif_linux.c
2-
INCLUDE_DIRS include $ENV{IDF_PATH}/components/esp_netif/include)
1+
idf_build_get_property(idf_target IDF_TARGET)
2+
if(${IDF_TARGET} STREQUAL "linux")
3+
idf_component_register(SRCS esp_netif_linux.c
4+
INCLUDE_DIRS include $ENV{IDF_PATH}/components/esp_netif/include
5+
REQUIRES esp_event)
6+
else()
7+
idf_component_register()
8+
endif()

0 commit comments

Comments
 (0)