Merge branch 'feature/update_mdns_from_idf' into 'master'

feat(mbedtls): Update mdns from esp-idf

See merge request sdk/ESP8266_RTOS_SDK!1320
This commit is contained in:
Dong Heng
2020-05-27 10:25:01 +08:00
23 changed files with 624 additions and 215 deletions

View File

@ -1,6 +1,6 @@
if(CONFIG_ENABLE_MDNS)
set(COMPONENT_SRCS "src/mdns.c"
"src/mdns_networking.c")
set(COMPONENT_SRCS "mdns.c"
"mdns_networking.c")
set(COMPONENT_PRIV_INCLUDEDIRS "private_include")
endif()
@ -10,10 +10,9 @@ set(COMPONENT_REQUIRES "lwip" "mbedtls" "tcpip_adapter")
if(CONFIG_ENABLE_MDNS_CONSOLE)
set(COMPONENT_SRCS "${COMPONENT_SRCS}"
"src/mdns_console.c")
"mdns_console.c")
endif()
set(COMPONENT_REQUIRES "console" "tcpip_adapter" "newlib")
register_component()

View File

@ -1,38 +1,29 @@
menu "mDNS"
config ENABLE_MDNS
bool "Enable mDNS"
default n
select LWIP_IPV6
help
Enable this option and then mDNS is to be used.
config ENABLE_MDNS
bool "Enable mDNS"
default n
select LWIP_IPV6
help
Enable this option and then mDNS is to be used.
config ENABLE_MDNS_CONSOLE
bool "Enable mDNS console"
default n
depends on ENABLE_MDNS
select USING_ESP_CONSOLE
help
Enable this option and then mDNS console is to be used.
config ENABLE_MDNS_CONSOLE
bool "Enable mDNS console"
default n
depends on ENABLE_MDNS
select USING_ESP_CONSOLE
help
Enable this option and then mDNS console is to be used.
config MDNS_MAX_SERVICES
int "Max number of services"
range 1 64
default 10
depends on ENABLE_MDNS
help
Services take up a certain amount of memory, and allowing fewer
services to be open at the same time conserves memory. Specify
the maximum amount of services here. The valid value is from 1
to 64.
config MDNS_MAX_SERVICES
int "Max number of services"
range 1 64
default 10
depends on ENABLE_MDNS
help
Services take up a certain amount of memory, and allowing fewer
services to be open at the same time conserves memory. Specify
the maximum amount of services here. The valid value is from 1
to 64.
config MDNS_STACKSIZE
int "Max stack size of MDNS"
range 2048 4096
default 4096
depends on ENABLE_MDNS
help
The stacksize of the MDNS task that will be responsible for transmitting
and receiving MDNS packets.
endmenu

View File

@ -1,10 +1,11 @@
COMPONENT_ADD_INCLUDEDIRS := include
COMPONENT_PRIV_INCLUDEDIRS := private_include
ifdef CONFIG_ENABLE_MDNS
COMPONENT_SRCDIRS := src
ifndef CONFIG_ENABLE_MDNS
COMPONENT_OBJEXCLUDE += mdns.o
COMPONENT_OBJEXCLUDE += mdns_networking.o
endif
ifndef CONFIG_ENABLE_MDNS_CONSOLE
COMPONENT_OBJEXCLUDE := src/mdns_console.o
COMPONENT_OBJEXCLUDE += mdns_console.o
endif

View File

@ -44,8 +44,8 @@ typedef enum {
* Used in mdns_service_add()
*/
typedef struct {
char * key; /*!< item key name */
char * value; /*!< item value string */
const char * key; /*!< item key name */
const char * value; /*!< item value string */
} mdns_txt_item_t;
/**
@ -81,10 +81,9 @@ typedef struct mdns_result_s {
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG when bad tcpip_if is given
* - ESP_ERR_INVALID_STATE when the network returned error
* - ESP_ERR_INVALID_STATE when failed to register event handler
* - ESP_ERR_NO_MEM on memory error
* - ESP_ERR_WIFI_NOT_INIT when WiFi is not initialized by eps_wifi_init
* - ESP_FAIL when failed to start mdns task
*/
esp_err_t mdns_init();
@ -127,13 +126,14 @@ esp_err_t mdns_instance_name_set(const char * instance_name);
* @param service_type service type (_http, _ftp, etc)
* @param proto service protocol (_tcp, _udp)
* @param port service port
* @param num_items number of items in TXT data
* @param txt string array of TXT data (eg. {{"var","val"},{"other","2"}})
* @param num_items number of items in TXT data
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NO_MEM memory error
* - ESP_FAIL failed to add serivce
*/
esp_err_t mdns_service_add(const char * instance_name, const char * service_type, const char * proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items);
@ -147,7 +147,7 @@ esp_err_t mdns_service_add(const char * instance_name, const char * service_type
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NOT_FOUND Service not found
* - ESP_FAIL unknown error
* - ESP_ERR_NO_MEM memory error
*/
esp_err_t mdns_service_remove(const char * service_type, const char * proto);
@ -177,6 +177,7 @@ esp_err_t mdns_service_instance_name_set(const char * service_type, const char *
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NOT_FOUND Service not found
* - ESP_ERR_NO_MEM memory error
*/
esp_err_t mdns_service_port_set(const char * service_type, const char * proto, uint16_t port);
@ -185,8 +186,8 @@ esp_err_t mdns_service_port_set(const char * service_type, const char * proto, u
*
* @param service_type service type (_http, _ftp, etc)
* @param proto service protocol (_tcp, _udp)
* @param num_items number of items in TXT data
* @param txt array of TXT data (eg. {{"var","val"},{"other","2"}})
* @param num_items number of items in TXT data
*
* @return
* - ESP_OK success

View File

@ -22,6 +22,10 @@
void mdns_debug_packet(const uint8_t * data, size_t len);
#endif
// Internal size of IPv6 address is defined here as size of AAAA record in mdns packet
// since the ip6_addr_t is defined in lwip and depends on using IPv6 zones
#define _MDNS_SIZEOF_IP6_ADDR (MDNS_ANSWER_AAAA_SIZE)
static const char * MDNS_DEFAULT_DOMAIN = "local";
static const char * MDNS_SUB_STR = "_sub";
@ -174,7 +178,7 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s
size_t index = 0;
while (start[index]) {
if (name->parts == 4) {
return NULL;
name->invalid = true;
}
uint8_t len = start[index++];
if (len < 0xC0) {
@ -195,7 +199,7 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s
strlcat(name->host, buf, sizeof(name->host));
} else if (strcasecmp(buf, MDNS_SUB_STR) == 0) {
name->sub = 1;
} else {
} else if (!name->invalid) {
char* mdns_name_ptrs[]={name->host, name->service, name->proto, name->domain};
memcpy(mdns_name_ptrs[name->parts++], buf, len+1);
}
@ -441,6 +445,10 @@ static uint16_t _mdns_append_ptr_record(uint8_t * packet, uint16_t * index, cons
uint16_t record_length = 0;
uint8_t part_length;
if (service == NULL) {
return 0;
}
str[0] = instance;
str[1] = service;
str[2] = proto;
@ -485,6 +493,10 @@ static uint16_t _mdns_append_sdptr_record(uint8_t * packet, uint16_t * index, md
uint16_t record_length = 0;
uint8_t part_length;
if (service == NULL) {
return 0;
}
sd_str[0] = (char*)"_services";
sd_str[1] = (char*)"_dns-sd";
sd_str[2] = (char*)"_udp";
@ -530,6 +542,10 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns
uint16_t record_length = 0;
uint8_t part_length;
if (service == NULL) {
return 0;
}
str[0] = _mdns_get_service_instance_name(service);
str[1] = service->service;
str[2] = service->proto;
@ -598,6 +614,10 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns
uint16_t record_length = 0;
uint8_t part_length;
if (service == NULL) {
return 0;
}
str[0] = _mdns_get_service_instance_name(service);
str[1] = service->service;
str[2] = service->proto;
@ -734,11 +754,11 @@ static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, uin
uint16_t data_len_location = *index - 2;
if ((*index + 15) >= MDNS_MAX_PACKET_SIZE) {
if ((*index + MDNS_ANSWER_AAAA_SIZE) > MDNS_MAX_PACKET_SIZE) {
return 0;
}
part_length = sizeof(ip6_addr_t);
part_length = MDNS_ANSWER_AAAA_SIZE;
memcpy(packet + *index, ipv6, part_length);
*index += part_length;
_mdns_set_u16(packet, data_len_location, part_length);
@ -817,7 +837,7 @@ static bool _ipv6_address_is_zero(ip6_addr_t ip6)
{
uint8_t i;
uint8_t * data = (uint8_t *)ip6.addr;
for (i=0; i<16; i++) {
for (i=0; i<_MDNS_SIZEOF_IP6_ADDR; i++) {
if (data[i]) {
return false;
}
@ -1147,6 +1167,7 @@ static bool _mdns_alloc_answer(mdns_out_answer_t ** destnation, uint16_t type, m
}
a->type = type;
a->service = service;
a->custom_service = NULL;
a->bye = bye;
a->flush = flush;
a->next = NULL;
@ -1234,7 +1255,7 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed
}
} else if (q->type == MDNS_TYPE_SDPTR) {
shared = true;
if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service->service, false, false)) {
if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, service->service, false, false)) {
_mdns_free_tx_packet(packet);
return;
}
@ -1312,6 +1333,7 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(tcpip_adapter_if_t tcpip_if,
q->domain = MDNS_DEFAULT_DOMAIN;
if (!q->host || _mdns_question_exists(q, packet->questions)) {
free(q);
continue;
} else {
queueToEnd(mdns_out_question_t, packet->questions, q);
}
@ -2188,7 +2210,7 @@ static int _mdns_check_aaaa_collision(ip6_addr_t * ip, tcpip_adapter_if_t tcpip_
if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &if_ip6)) {
return 1;//they win
}
int ret = memcmp((uint8_t*)&if_ip6.addr, (uint8_t*)ip->addr, sizeof(ip6_addr_t));
int ret = memcmp((uint8_t*)&if_ip6.addr, (uint8_t*)ip->addr, _MDNS_SIZEOF_IP6_ADDR);
if (ret > 0) {
return -1;//we win
} else if (ret < 0) {
@ -2200,7 +2222,7 @@ static int _mdns_check_aaaa_collision(ip6_addr_t * ip, tcpip_adapter_if_t tcpip_
if (tcpip_adapter_get_ip6_linklocal(other_if, &other_ip6)) {
return 1;//IPv6 not active! They win
}
if (memcmp((uint8_t*)&other_ip6.addr, (uint8_t*)ip->addr, sizeof(ip6_addr_t))) {
if (memcmp((uint8_t*)&other_ip6.addr, (uint8_t*)ip->addr, _MDNS_SIZEOF_IP6_ADDR)) {
return 1;//IPv6 not ours! They win
}
_mdns_dup_interface(tcpip_if);
@ -2315,6 +2337,7 @@ static const uint8_t * _mdns_parse_fqdn(const uint8_t * packet, const uint8_t *
name->service[0] = 0;
name->proto[0] = 0;
name->domain[0] = 0;
name->invalid = false;
static char buf[MDNS_NAME_BUF_LEN];
@ -2322,7 +2345,7 @@ static const uint8_t * _mdns_parse_fqdn(const uint8_t * packet, const uint8_t *
if (!next_data) {
return 0;
}
if (!name->parts) {
if (!name->parts || name->invalid) {
return next_data;
}
if (name->parts == 3) {
@ -2620,7 +2643,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
clas &= 0x7FFF;
content = content + 4;
if (clas != 0x0001) {//bad class
if (clas != 0x0001 || name->invalid) {//bad class or invalid name for this question entry
continue;
}
@ -2801,7 +2824,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
col = 1;
} else if (!clas) {
col = -1;
} else {
} else if (service) { // only detect srv collision if service existed
col = _mdns_check_srv_collision(service->service, priority, weight, port, name->host, name->domain);
}
if (col && (parsed_packet->probe || parsed_packet->authoritative)) {
@ -2886,7 +2909,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
col = 1;
} else if (!clas) {
col = -1;
} else {
} else if (service) { // only detect txt collision if service existed
col = _mdns_check_txt_collision(service->service, data_ptr, data_len);
}
if (col && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) {
@ -2900,7 +2923,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
} else if (type == MDNS_TYPE_AAAA) {//ipv6
ip_addr_t ip6;
ip6.type = IPADDR_TYPE_V6;
memcpy(ip6.u_addr.ip6.addr, data_ptr, 16);
memcpy(ip6.u_addr.ip6.addr, data_ptr, MDNS_ANSWER_AAAA_SIZE);
if (search_result) {
//check for more applicable searches (PTR & A/AAAA at the same time)
while (search_result) {
@ -3048,56 +3071,50 @@ void _mdns_disable_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protoc
/**
* @brief Dispatch interface changes based on system events
*/
void _mdns_handle_system_event(system_event_id_t event, tcpip_adapter_if_t interface)
static void _mdns_handle_system_event(esp_event_base_t event_base,
int32_t event_id, tcpip_adapter_if_t interface)
{
if (!_mdns_server) {
return;
}
tcpip_adapter_dhcp_status_t dcst;
switch(event) {
case SYSTEM_EVENT_STA_CONNECTED:
if (!tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &dcst)) {
if (dcst != TCPIP_ADAPTER_DHCP_STARTED) {
if (event_base == WIFI_EVENT) {
switch(event_id) {
case WIFI_EVENT_STA_CONNECTED:
if (!tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &dcst)) {
if (dcst == TCPIP_ADAPTER_DHCP_STOPPED) {
_mdns_enable_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V4);
}
}
break;
case WIFI_EVENT_STA_DISCONNECTED:
_mdns_disable_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V4);
_mdns_disable_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V6);
break;
case WIFI_EVENT_AP_START:
_mdns_enable_pcb(TCPIP_ADAPTER_IF_AP, MDNS_IP_PROTOCOL_V4);
break;
case WIFI_EVENT_AP_STOP:
_mdns_disable_pcb(TCPIP_ADAPTER_IF_AP, MDNS_IP_PROTOCOL_V4);
_mdns_disable_pcb(TCPIP_ADAPTER_IF_AP, MDNS_IP_PROTOCOL_V6);
break;
default:
break;
}
} else if (event_base == IP_EVENT) {
switch (event_id) {
case IP_EVENT_STA_GOT_IP:
_mdns_enable_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V4);
}
_mdns_announce_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V6, NULL, 0, true);
break;
case IP_EVENT_GOT_IP6:
_mdns_enable_pcb(interface, MDNS_IP_PROTOCOL_V6);
_mdns_announce_pcb(interface, MDNS_IP_PROTOCOL_V4, NULL, 0, true);
break;
default:
break;
}
break;
case SYSTEM_EVENT_STA_GOT_IP:
_mdns_enable_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V4);
_mdns_announce_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V6, NULL, 0, true);
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
_mdns_disable_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V4);
_mdns_disable_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V6);
break;
case SYSTEM_EVENT_AP_START:
_mdns_enable_pcb(TCPIP_ADAPTER_IF_AP, MDNS_IP_PROTOCOL_V4);
break;
case SYSTEM_EVENT_AP_STOP:
_mdns_disable_pcb(TCPIP_ADAPTER_IF_AP, MDNS_IP_PROTOCOL_V4);
_mdns_disable_pcb(TCPIP_ADAPTER_IF_AP, MDNS_IP_PROTOCOL_V6);
break;
case SYSTEM_EVENT_GOT_IP6:
_mdns_enable_pcb(interface, MDNS_IP_PROTOCOL_V6);
_mdns_announce_pcb(interface, MDNS_IP_PROTOCOL_V4, NULL, 0, true);
break;
case SYSTEM_EVENT_ETH_CONNECTED:
if (!tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_ETH, &dcst)) {
if (dcst != TCPIP_ADAPTER_DHCP_STARTED) {
_mdns_enable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V4);
}
}
break;
case SYSTEM_EVENT_ETH_GOT_IP:
_mdns_enable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V4);
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
_mdns_disable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V4);
_mdns_disable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V6);
break;
default:
break;
}
}
@ -3709,7 +3726,8 @@ static void _mdns_execute_action(mdns_action_t * action)
switch(action->type) {
case ACTION_SYSTEM_EVENT:
_mdns_handle_system_event(action->data.sys_event.event_id, action->data.sys_event.interface);
_mdns_handle_system_event(action->data.sys_event.event_base,
action->data.sys_event.event_id, action->data.sys_event.interface);
break;
case ACTION_HOSTNAME_SET:
_mdns_send_final_bye(true);
@ -3817,23 +3835,25 @@ static void _mdns_execute_action(mdns_action_t * action)
break;
case ACTION_SERVICE_DEL:
a = _mdns_server->services;
if (_mdns_server->services == action->data.srv_del.service) {
_mdns_server->services = a->next;
_mdns_send_bye(&a, 1, false);
_mdns_remove_scheduled_service_packets(a->service);
_mdns_free_service(a->service);
free(a);
} else {
while (a->next && a->next != action->data.srv_del.service) {
a = a->next;
}
if (a->next == action->data.srv_del.service) {
mdns_srv_item_t * b = a->next;
a->next = a->next->next;
_mdns_send_bye(&b, 1, false);
_mdns_remove_scheduled_service_packets(b->service);
_mdns_free_service(b->service);
free(b);
if (action->data.srv_del.service) {
if (_mdns_server->services == action->data.srv_del.service) {
_mdns_server->services = a->next;
_mdns_send_bye(&a, 1, false);
_mdns_remove_scheduled_service_packets(a->service);
_mdns_free_service(a->service);
free(a);
} else {
while (a->next && a->next != action->data.srv_del.service) {
a = a->next;
}
if (a->next == action->data.srv_del.service) {
mdns_srv_item_t * b = a->next;
a->next = a->next->next;
_mdns_send_bye(&b, 1, false);
_mdns_remove_scheduled_service_packets(b->service);
_mdns_free_service(b->service);
free(b);
}
}
}
@ -4098,23 +4118,34 @@ static esp_err_t _mdns_service_task_stop()
* */
esp_err_t mdns_handle_system_event(void *ctx, system_event_t *event)
{
/* no-op, kept for compatibility */
return ESP_OK;
}
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (!_mdns_server) {
return ESP_OK;
return;
}
mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t));
mdns_action_t * action = (mdns_action_t *)calloc(1, sizeof(mdns_action_t));
if (!action) {
HOOK_MALLOC_FAILED;
return ESP_OK;
return;
}
action->type = ACTION_SYSTEM_EVENT;
action->data.sys_event.event_id = event->event_id;
action->data.sys_event.interface = (event->event_id == SYSTEM_EVENT_GOT_IP6)?event->event_info.got_ip6.if_index:0;
action->data.sys_event.event_base = event_base;
action->data.sys_event.event_id = event_id;
if (event_base == IP_EVENT && event_id == IP_EVENT_GOT_IP6) {
ip_event_got_ip6_t* event = (ip_event_got_ip6_t*) event_data;
action->data.sys_event.interface = event->if_index;
}
if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) {
free(action);
}
return ESP_OK;
}
esp_err_t mdns_init()
@ -4144,6 +4175,13 @@ esp_err_t mdns_init()
goto free_lock;
}
if ((err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)) != ESP_OK) {
goto free_event_handlers;
}
if ((err = esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)) != ESP_OK) {
goto free_event_handlers;
}
uint8_t i;
ip6_addr_t tmp_addr6;
tcpip_adapter_ip_info_t if_ip_info;
@ -4170,6 +4208,9 @@ free_all_and_disable_pcbs:
_mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V6);
_mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V4);
}
free_event_handlers:
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler);
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler);
vQueueDelete(_mdns_server->action_queue);
free_lock:
vSemaphoreDelete(_mdns_server->lock);
@ -4185,6 +4226,10 @@ void mdns_free()
if (!_mdns_server) {
return;
}
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler);
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler);
mdns_service_remove_all(_mdns_server);
_mdns_service_task_stop();
for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
@ -4892,7 +4937,7 @@ void mdns_debug_packet(const uint8_t * data, size_t len)
_mdns_dbg_printf("\n");
} else if (type == MDNS_TYPE_AAAA) {
ip6_addr_t ip6;
memcpy(&ip6, data_ptr, sizeof(ip6_addr_t));
memcpy(&ip6, data_ptr, MDNS_ANSWER_AAAA_SIZE);
_mdns_dbg_printf(IPV6STR "\n", IPV62STR(ip6));
} else if (type == MDNS_TYPE_A) {
ip4_addr_t ip;

View File

@ -4,7 +4,6 @@
*
*/
#include <string.h>
#include "mdns_private.h"
#include "mdns_networking.h"
#include "esp_log.h"

View File

@ -6,7 +6,7 @@
*
*/
#include "mdns.h"
#include "mdns_private.h"
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
@ -20,7 +20,7 @@
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_timer.h"
#include "esp_event_loop.h"
#include "esp_event.h"
/**

View File

@ -56,6 +56,7 @@
#define MDNS_ANSWER_AAAA 0x10
#define MDNS_ANSWER_NSEC 0x20
#define MDNS_ANSWER_SDPTR 0x80
#define MDNS_ANSWER_AAAA_SIZE 16
#define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on
#define MDNS_SERVICE_STACK_DEPTH 4096 // Stack size for the service thread
@ -188,6 +189,7 @@ typedef struct {
char domain[MDNS_NAME_BUF_LEN];
uint8_t parts;
uint8_t sub;
bool invalid;
} mdns_name_t;
typedef struct mdns_parsed_question_s {
@ -264,7 +266,7 @@ typedef struct mdns_srv_item_s {
typedef struct mdns_out_question_s {
struct mdns_out_question_s * next;
uint16_t type;
uint8_t unicast;
bool unicast;
const char * host;
const char * service;
const char * proto;
@ -352,7 +354,8 @@ typedef struct {
char * hostname;
char * instance;
struct {
system_event_id_t event_id;
esp_event_base_t event_base;
int32_t event_id;
tcpip_adapter_if_t interface;
} sys_event;
struct {

View File

@ -0,0 +1,2 @@
idf_component_register(SRC_DIRS "."
PRIV_REQUIRES unity test_utils mdns)

View File

@ -0,0 +1,4 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

View File

@ -0,0 +1,99 @@
#include "test_utils.h"
#include "mdns.h"
#include "unity.h"
#define MDNS_HOSTNAME "test-hostname"
#define MDNS_INSTANCE "test-instance"
#define MDNS_SERVICE_NAME "_http"
#define MDNS_SERVICE_PROTO "_tcp"
#define MDNS_SERVICE_PORT 80
static void yield_to_all_priorities(void)
{
// Lower the test-task priority before testing to ensure other tasks got executed on forced context switch
size_t test_task_prio_before = uxTaskPriorityGet(NULL);
vTaskPrioritySet(NULL, tskIDLE_PRIORITY);
taskYIELD(); // Let the RTOS to switch context
vTaskPrioritySet(NULL, test_task_prio_before);
}
TEST_CASE("mdns api to fail in invalid state", "[mdns][leaks=64]")
{
TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_init() );
TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME) );
TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_instance_name_set(MDNS_INSTANCE) );
TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0) );
}
TEST_CASE("mdns init and deinit", "[mdns][leaks=64]")
{
test_case_uses_tcpip();
TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default());
TEST_ASSERT_EQUAL(ESP_OK, mdns_init() );
yield_to_all_priorities(); // Make sure that mdns task has executed to complete initialization
mdns_free();
esp_event_loop_delete_default();
}
TEST_CASE("mdns api return expected err-code and do not leak memory", "[mdns][leaks=64]")
{
mdns_txt_item_t serviceTxtData[CONFIG_MDNS_MAX_SERVICES] = { {NULL, NULL},
};
for (int i=0; i<CONFIG_MDNS_MAX_SERVICES; ++i) {
serviceTxtData[i].key = "Key";
serviceTxtData[i].value = "Value";
}
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_instance_name_set(MDNS_INSTANCE) );
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, serviceTxtData, CONFIG_MDNS_MAX_SERVICES) );
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, serviceTxtData, CONFIG_MDNS_MAX_SERVICES) );
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) );
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
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0) );
TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove_all() );
yield_to_all_priorities(); // Make sure that mdns task has executed to remove all services
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, mdns_service_port_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 8080) );
mdns_free();
esp_event_loop_delete_default();
}
TEST_CASE("mdns query api return expected err-code and do not leak memory", "[leaks=64]")
{
mdns_result_t * results = NULL;
ip6_addr_t addr6;
ip4_addr_t addr4;
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_query_ptr(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 10, CONFIG_MDNS_MAX_SERVICES, &results) );
mdns_query_results_free(results);
TEST_ASSERT_EQUAL(ESP_OK, mdns_query_srv(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 10, &results) );
mdns_query_results_free(results);
TEST_ASSERT_EQUAL(ESP_OK, mdns_query_txt(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 10, &results) );
mdns_query_results_free(results);
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, mdns_query_a(MDNS_HOSTNAME, 10, &addr4) );
mdns_query_results_free(results);
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, mdns_query_aaaa(MDNS_HOSTNAME, 10, &addr6) );
mdns_query_results_free(results);
mdns_free();
esp_event_loop_delete_default();
}

View File

@ -1,7 +1,9 @@
TEST_NAME=test
FUZZ=afl-fuzz
COMPONENTS_DIR=../..
CFLAGS=-g -DMDNS_TEST_MODE -I. -I.. -I../include -I../private_include -I$(COMPONENTS_DIR)/tcpip_adapter/include -I$(COMPONENTS_DIR)/esp32/include -include esp32_compat.h
CFLAGS=-g -DHOOK_MALLOC_FAILED -DESP_EVENT_H_ -D__ESP_LOG_H__ -DMDNS_TEST_MODE \
-I. -I.. -I../include -I../private_include -include esp32_compat.h \
-I$(COMPONENTS_DIR)/tcpip_adapter/include -I$(COMPONENTS_DIR)/esp_event/include -I$(COMPONENTS_DIR)/log/include
MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h
ifeq ($(INSTR),off)
CC=gcc

View File

@ -20,7 +20,6 @@
// Not to include
#define ESP_MDNS_NETWORKING_H_
#define _TCPIP_ADAPTER_H_
#define __ESP_EVENT_H__
#ifdef USE_BSD_STRING
@ -57,6 +56,7 @@
#define portMAX_DELAY 0xFFFFFFFF
#define portTICK_PERIOD_MS 1
#define ESP_LOGD(a,b)
#define xSemaphoreTake(s,d)
#define xTaskDelete(a)
@ -65,6 +65,7 @@
#define _mdns_pcb_init(a,b) true
#define _mdns_pcb_deinit(a,b) true
#define xSemaphoreCreateMutex() malloc(1)
#define xSemaphoreCreateBinary() malloc(1)
#define vSemaphoreDelete(s) free(s)
#define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1)
#define vTaskDelay(m) usleep((m)*0)
@ -114,6 +115,47 @@ typedef enum {
WIFI_MODE_MAX
} wifi_mode_t;
extern const char * WIFI_EVENT;
extern const char * IP_EVENT;
extern const char * ETH_EVENT;
typedef enum {
WIFI_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */
WIFI_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */
WIFI_EVENT_STA_START, /**< ESP32 station start */
WIFI_EVENT_STA_STOP, /**< ESP32 station stop */
WIFI_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */
WIFI_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */
WIFI_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */
WIFI_EVENT_STA_WPS_ER_SUCCESS, /**< ESP32 station wps succeeds in enrollee mode */
WIFI_EVENT_STA_WPS_ER_FAILED, /**< ESP32 station wps fails in enrollee mode */
WIFI_EVENT_STA_WPS_ER_TIMEOUT, /**< ESP32 station wps timeout in enrollee mode */
WIFI_EVENT_STA_WPS_ER_PIN, /**< ESP32 station wps pin code in enrollee mode */
WIFI_EVENT_AP_START, /**< ESP32 soft-AP start */
WIFI_EVENT_AP_STOP, /**< ESP32 soft-AP stop */
WIFI_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */
WIFI_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */
WIFI_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */
} wifi_event_t;
typedef enum {
ETHERNET_EVENT_START, /**< ESP32 ethernet start */
ETHERNET_EVENT_STOP, /**< ESP32 ethernet stop */
ETHERNET_EVENT_CONNECTED, /**< ESP32 ethernet phy link up */
ETHERNET_EVENT_DISCONNECTED, /**< ESP32 ethernet phy link down */
} eth_event_t;
typedef enum {
IP_EVENT_STA_GOT_IP, /*!< ESP32 station got IP from connected AP */
IP_EVENT_STA_LOST_IP, /*!< ESP32 station lost IP and the IP is reset to 0 */
IP_EVENT_AP_STAIPASSIGNED, /*!< ESP32 soft-AP assign an IP to a connected station */
IP_EVENT_GOT_IP6, /*!< ESP32 station or ap or ethernet interface v6IP addr is preferred */
IP_EVENT_ETH_GOT_IP, /*!< ESP32 ethernet got IP from connected AP */
} ip_event_t;
/* status of DHCP client or DHCP server */
typedef enum {
TCPIP_ADAPTER_DHCP_INIT = 0, /**< DHCP client/server in initial state */
@ -122,34 +164,6 @@ typedef enum {
TCPIP_ADAPTER_DHCP_STATUS_MAX
} tcpip_adapter_dhcp_status_t;
typedef enum {
SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */
SYSTEM_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */
SYSTEM_EVENT_STA_START, /**< ESP32 station start */
SYSTEM_EVENT_STA_STOP, /**< ESP32 station stop */
SYSTEM_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */
SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */
SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */
SYSTEM_EVENT_STA_GOT_IP, /**< ESP32 station got IP from connected AP */
SYSTEM_EVENT_STA_LOST_IP, /**< ESP32 station lost IP and the IP is reset to 0 */
SYSTEM_EVENT_STA_WPS_ER_SUCCESS, /**< ESP32 station wps succeeds in enrollee mode */
SYSTEM_EVENT_STA_WPS_ER_FAILED, /**< ESP32 station wps fails in enrollee mode */
SYSTEM_EVENT_STA_WPS_ER_TIMEOUT, /**< ESP32 station wps timeout in enrollee mode */
SYSTEM_EVENT_STA_WPS_ER_PIN, /**< ESP32 station wps pin code in enrollee mode */
SYSTEM_EVENT_AP_START, /**< ESP32 soft-AP start */
SYSTEM_EVENT_AP_STOP, /**< ESP32 soft-AP stop */
SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */
SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */
SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */
SYSTEM_EVENT_GOT_IP6, /**< ESP32 station or ap or ethernet interface v6IP addr is preferred */
SYSTEM_EVENT_ETH_START, /**< ESP32 ethernet start */
SYSTEM_EVENT_ETH_STOP, /**< ESP32 ethernet stop */
SYSTEM_EVENT_ETH_CONNECTED, /**< ESP32 ethernet phy link up */
SYSTEM_EVENT_ETH_DISCONNECTED, /**< ESP32 ethernet phy link down */
SYSTEM_EVENT_ETH_GOT_IP, /**< ESP32 ethernet got IP from connected AP */
SYSTEM_EVENT_MAX
} system_event_id_t;
struct udp_pcb {
uint8_t dummy;
};
@ -178,7 +192,6 @@ typedef struct {
ip4_addr_t gw;
} tcpip_adapter_ip_info_t;
// typedef int32_t system_event_id_t;
typedef enum {
TCPIP_ADAPTER_IF_STA = 0, /**< ESP32 station interface */
TCPIP_ADAPTER_IF_AP, /**< ESP32 soft-AP interface */
@ -189,18 +202,13 @@ typedef enum {
typedef struct {
ip6_addr_t ip;
} tcpip_adapter_ip6_info_t;
typedef struct {
tcpip_adapter_if_t if_index;
tcpip_adapter_ip6_info_t ip6_info;
} system_event_got_ip6_t;
typedef union {
system_event_got_ip6_t got_ip6; /**< ESP32 station or ap or ethernet ipv6 addr state change to preferred */
} system_event_info_t;
typedef struct {
system_event_id_t event_id; /**< event ID */
system_event_info_t event_info; /**< event information */
} system_event_t;
tcpip_adapter_if_t if_index; /*!< Interface for which the event is received */
tcpip_adapter_ip6_info_t ip6_info; /*!< IPv6 address of the interface */
} ip_event_got_ip6_t;
typedef void* system_event_t;
inline esp_err_t esp_wifi_get_mode(wifi_mode_t * mode)
{

View File

@ -9,6 +9,23 @@ void* g_queue;
int g_queue_send_shall_fail = 0;
int g_size = 0;
const char * WIFI_EVENT = "wifi_event";
const char * IP_EVENT = "ip_event";
const char * ETH_EVENT = "eth_event";
esp_err_t esp_event_handler_register(const char * event_base,
int32_t event_id,
void* event_handler,
void* event_handler_arg)
{
return ESP_OK;
}
esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler)
{
return ESP_OK;
}
esp_err_t esp_timer_delete(esp_timer_handle_t timer)
{
return ESP_OK;

View File

@ -40,6 +40,10 @@ void GetLastItem(void *pvBuffer);
void ForceTaskDelete();
esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id, void* event_handler, void* event_handler_arg);
esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler);
#define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len
#endif /* ESP32_MOCK_H_ */