Skip to content

Commit

Permalink
Merge pull request #617 from david-cermak/feat/mdns_console_host
Browse files Browse the repository at this point in the history
[mdns]: Add linux console functional tests
  • Loading branch information
david-cermak authored Aug 15, 2024
2 parents f198967 + 50d059a commit e425a3c
Show file tree
Hide file tree
Showing 21 changed files with 444 additions and 75 deletions.
23 changes: 13 additions & 10 deletions .github/workflows/mdns__host-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,30 @@ on:
jobs:
host_test_mdns:
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
name: Host test
name: Host test build
runs-on: ubuntu-22.04
container: espressif/idf:release-v5.1
container: espressif/idf:release-v5.3

steps:
- name: Checkout esp-protocols
uses: actions/checkout@v4
with:
path: esp-protocols
path: protocols

- name: Build and Test
shell: bash
run: |
apt-get update && apt-get install -y dnsutils gcc g++
. ${IDF_PATH}/export.sh
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/host_test
idf.py build
./build/mdns_host.elf &
dig +short -p 5353 @224.0.0.251 myesp.local > ip.txt
cat ip.txt | xargs dig +short -p 5353 @224.0.0.251 -x
cat ip.txt
python -m pip install idf-build-apps dnspython pytest pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf
cd $GITHUB_WORKSPACE/protocols
# Build host tests app (with all configs and targets supported)
python ./ci/build_apps.py components/mdns/tests/host_test/
cd components/mdns/tests/host_test
# First run the linux_app and send a quick A query and a reverse query
./build_linux_app/mdns_host.elf &
python dnsfixture.py A myesp.local --ip_only | xargs python dnsfixture.py X
# Next we run the pytest (using the console app)
pytest
build_afl_host_test_mdns:
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
Expand Down
1 change: 1 addition & 0 deletions common_components/linux_compat/esp_ringbuf/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
idf_component_register()
102 changes: 78 additions & 24 deletions common_components/linux_compat/freertos/freertos_linux.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -12,8 +12,24 @@
#include <stdlib.h>
#include <string.h>
#include "osal/osal_api.h"
#include <semaphore.h>

typedef struct task_notifiers {
sem_t sem;
TaskHandle_t id;
} task_notifiers_t;

typedef struct pthread_params {
void *const param;
TaskFunction_t task;
bool started;
TaskHandle_t handle;
} pthread_params_t;

static uint64_t s_semaphore_data = 0;
static task_notifiers_t *s_notifiers;
static int s_threads = 0;
pthread_mutex_t s_mutex;

typedef enum queue_type_tag {
MUTEX_REC,
Expand Down Expand Up @@ -89,6 +105,7 @@ BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue)
}
return pdFALSE;
}

BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
{
struct generic_queue_handle *h = xQueue;
Expand All @@ -99,7 +116,6 @@ BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY);
}


BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
{
struct generic_queue_handle *h = xQueue;
Expand All @@ -110,9 +126,6 @@ BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
return pdFALSE;
}




void vQueueDelete( QueueHandle_t xQueue )
{
struct generic_queue_handle *h = xQueue;
Expand All @@ -128,8 +141,7 @@ void vQueueDelete( QueueHandle_t xQueue )

QueueHandle_t xSemaphoreCreateBinary(void)
{
QueueHandle_t sempaphore = xQueueCreate(1, 1);
return sempaphore;
return xQueueCreate(1, 1);
}

QueueHandle_t xSemaphoreCreateMutex(void)
Expand All @@ -145,6 +157,13 @@ QueueHandle_t xSemaphoreCreateRecursiveMutex(void)

void vTaskDelete(TaskHandle_t *task)
{
for (int i = 0; i < s_threads; ++i) {
if (task == s_notifiers[i].id) {
sem_destroy(&s_notifiers[i].sem);
s_notifiers[i].id = 0;
}
}

if (task == NULL) {
pthread_exit(0);
}
Expand All @@ -171,14 +190,21 @@ void vTaskDelay( const TickType_t xTicksToDelay )

void *pthread_task(void *params)
{
struct {
void *const param;
TaskFunction_t task;
bool started;
} *pthread_params = params;
pthread_params_t *pthread_params = params;

void *const param = pthread_params->param;
TaskFunction_t task = pthread_params->task;

pthread_params->handle = xTaskGetCurrentTaskHandle();
if (s_threads == 0) {
pthread_mutex_init(&s_mutex, NULL);
}
pthread_mutex_lock(&s_mutex);
s_notifiers = realloc(s_notifiers, sizeof(struct task_notifiers) * (++s_threads));
assert(s_notifiers);
s_notifiers[s_threads - 1].id = pthread_params->handle;
sem_init(&s_notifiers[s_threads - 1].sem, 0, 0);
pthread_mutex_unlock(&s_mutex);
pthread_params->started = true;

task(param);
Expand All @@ -198,37 +224,46 @@ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
return pdTRUE;
}


BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask)
{
pthread_t new_thread = (pthread_t)NULL;
pthread_attr_t attr;
struct {
void *const param;
TaskFunction_t task;
bool started;
} pthread_params = { .param = pvParameters, .task = pvTaskCode};
pthread_params_t pthread_params = { .param = pvParameters, .task = pvTaskCode};

int res = pthread_attr_init(&attr);
assert(res == 0);
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
assert(res == 0);
res = pthread_create(&new_thread, &attr, pthread_task, &pthread_params);
assert(res == 0);

if (pvCreatedTask) {
*pvCreatedTask = (void *)new_thread;
}

// just wait till the task started so we can unwind params from the stack
while (pthread_params.started == false) {
usleep(1000);
}
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 )
Expand All @@ -238,7 +273,7 @@ BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear,

TaskHandle_t xTaskGetCurrentTaskHandle(void)
{
return NULL;
return (TaskHandle_t)pthread_self();
}

EventGroupHandle_t xEventGroupCreate( void )
Expand Down Expand Up @@ -270,3 +305,22 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits
{
return osal_signal_wait(xEventGroup, uxBitsToWaitFor, xWaitForAllBits, xTicksToWait);
}

void ulTaskNotifyTake(bool clear_on_exit, uint32_t xTicksToWait)
{
TaskHandle_t task = xTaskGetCurrentTaskHandle();
int i = 0;
while (true) {
pthread_mutex_lock(&s_mutex);
if (task == s_notifiers[i].id) {
pthread_mutex_unlock(&s_mutex);
sem_wait(&s_notifiers[i].sem);
return;
}
pthread_mutex_unlock(&s_mutex);
if (++i == s_threads) {
i = 0;
}
usleep(1000);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#pragma once
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
extern "C" {
#endif

#define tskNO_AFFINITY ( ( BaseType_t ) 0x7FFFFFFF )
#define TaskHandle_t TaskHandle_t
#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )

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 );
Expand Down
5 changes: 3 additions & 2 deletions components/mdns/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ endif()

idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "linux")
set(dependencies esp_netif_linux esp_timer esp_system)
set(srcs "mdns.c" ${MDNS_NETWORKING})
set(dependencies esp_netif_linux esp_event)
set(private_dependencies esp_timer console esp_system)
set(srcs "mdns.c" ${MDNS_NETWORKING} ${MDNS_CONSOLE})
else()
set(dependencies lwip console esp_netif)
set(private_dependencies esp_timer esp_wifi)
Expand Down
9 changes: 5 additions & 4 deletions components/mdns/mdns.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,17 @@ static void _mdns_browse_send(mdns_browse_t *browse);
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
#include "esp_eth.h"
#endif
#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP
#include "esp_wifi.h"
#endif

#if ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(5, 1, 0)
#define MDNS_ESP_WIFI_ENABLED CONFIG_SOC_WIFI_SUPPORTED
#else
#define MDNS_ESP_WIFI_ENABLED CONFIG_ESP_WIFI_ENABLED
#endif

#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP)
#include "esp_wifi.h"
#endif

#ifdef MDNS_ENABLE_DEBUG
void mdns_debug_packet(const uint8_t *data, size_t len);
#endif
Expand Down Expand Up @@ -4411,7 +4412,7 @@ void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base,
}

esp_netif_dhcp_status_t dcst;
#if MDNS_ESP_WIFI_ENABLED
#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP)
if (event_base == WIFI_EVENT) {
switch (event_id) {
case WIFI_EVENT_STA_CONNECTED:
Expand Down
7 changes: 4 additions & 3 deletions components/mdns/mdns_console.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -9,6 +9,7 @@
#include "argtable3/argtable3.h"
#include "mdns.h"
#include "mdns_private.h"
#include "inttypes.h"

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

Expand All @@ -26,7 +27,7 @@ static void mdns_print_results(mdns_result_t *results)
printf(" SRV : %s.local:%u\n", r->hostname, r->port);
}
if (r->txt_count) {
printf(" TXT : [%u] ", r->txt_count);
printf(" TXT : [%u] ", (int)r->txt_count);
for (size_t t = 0; t < r->txt_count; t++) {
printf("%s=%s; ", r->txt[t].key, r->txt[t].value);
}
Expand Down Expand Up @@ -516,7 +517,7 @@ static int cmd_mdns_init(int argc, char **argv)
printf("MDNS: Hostname: %s\n", mdns_init_args.hostname->sval[0]);
}

if (mdns_init_args.instance->sval[0]) {
if (mdns_init_args.instance->count) {
ESP_ERROR_CHECK( mdns_instance_name_set(mdns_init_args.instance->sval[0]) );
printf("MDNS: Instance: %s\n", mdns_init_args.instance->sval[0]);
}
Expand Down
11 changes: 8 additions & 3 deletions components/mdns/tests/host_test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
cmake_minimum_required(VERSION 3.5)

set(EXTRA_COMPONENT_DIRS "../.." "../../../../common_components/linux_compat")

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main esp_netif_linux)
if(${IDF_TARGET} STREQUAL "linux")
set(EXTRA_COMPONENT_DIRS "../../../../common_components/linux_compat")
set(COMPONENTS main)
endif()

project(mdns_host)

# Enable sanitizers for mdns implementation
# Enable sanitizers only without console (we'd see some leaks on argtable when console exits)
if(NOT CONFIG_TEST_CONSOLE AND CONFIG_IDF_TARGET_LINUX)
idf_component_get_property(mdns mdns COMPONENT_LIB)
target_link_options(${mdns} INTERFACE -fsanitize=address -fsanitize=undefined)
endif()
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
idf_component_register(SRCS esp_netif_linux.c
INCLUDE_DIRS include $ENV{IDF_PATH}/components/esp_netif/include)
idf_build_get_property(idf_target IDF_TARGET)
if(${IDF_TARGET} STREQUAL "linux")
idf_component_register(SRCS esp_netif_linux.c
INCLUDE_DIRS include $ENV{IDF_PATH}/components/esp_netif/include
REQUIRES esp_event)
else()
idf_component_register()
endif()
Loading

0 comments on commit e425a3c

Please sign in to comment.