From 7fbf8e52475512be6e81cbbc050aedb81c1711a2 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 4 Jan 2017 18:54:07 +0200 Subject: [PATCH 001/289] Initial mDNS component and example * Original commit: espressif/esp-idf@dd3f18d2d88ee78909d4af2840dfdf0b9f715f28 --- components/mdns/component.mk | 0 components/mdns/include/mdns.h | 235 ++++ components/mdns/mdns.c | 1861 ++++++++++++++++++++++++++++++++ 3 files changed, 2096 insertions(+) create mode 100644 components/mdns/component.mk create mode 100644 components/mdns/include/mdns.h create mode 100644 components/mdns/mdns.c diff --git a/components/mdns/component.mk b/components/mdns/component.mk new file mode 100644 index 000000000..e69de29bb diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h new file mode 100644 index 000000000..58e588e3e --- /dev/null +++ b/components/mdns/include/mdns.h @@ -0,0 +1,235 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef ESP_MDNS_H_ +#define ESP_MDNS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct mdns_server_s; +typedef struct mdns_server_s mdns_server_t; + +/** + * @brief mDNS query result structure + * + */ +typedef struct mdns_result_s { + const char * host; /*!< hostname */ + const char * instance; /*!< instance */ + const char * txt; /*!< txt data */ + uint16_t priority; /*!< service priority */ + uint16_t weight; /*!< service weight */ + uint16_t port; /*!< service port */ + struct ip4_addr addr; /*!< ip4 address */ + struct ip6_addr addrv6; /*!< ip6 address */ + const struct mdns_result_s * next; /*!< next result, or NULL for the last result in the list */ +} mdns_result_t; + +/** + * @brief Initialize mDNS on given interface + * + * @param tcpip_if Interface that the server will listen on + * @param server Server pointer to populate on success + * + * @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_NO_MEM on memory error + * - ESP_ERR_WIFI_NOT_INIT when WiFi is not initialized by eps_wifi_init + */ +esp_err_t mdns_init(tcpip_adapter_if_t tcpip_if, mdns_server_t ** server); + +/** + * @brief Stop and free mDNS server + * + * @param server mDNS Server to free + * + */ +void mdns_free(mdns_server_t * server); + +/** + * @brief Set the hostname for mDNS server + * + * @param server mDNS Server + * @param hostname Hostname to set + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname); + +/** + * @brief Set the default instance name for mDNS server + * + * @param server mDNS Server + * @param instance Instance name to set + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance); + +/** + * @brief Add service to mDNS server + * + * @param server mDNS Server + * @param service service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param port service port + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_add(mdns_server_t * server, const char * service, const char * proto, uint16_t port); + +/** + * @brief Remove service from mDNS server + * + * @param server mDNS Server + * @param service service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_FAIL unknown error + */ +esp_err_t mdns_service_remove(mdns_server_t * server, const char * service, const char * proto); + +/** + * @brief Set instance name for service + * + * @param server mDNS Server + * @param service service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param instance instance name to set + * + * @return + * - 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_instance_set(mdns_server_t * server, const char * service, const char * proto, const char * instance); + +/** + * @brief Set TXT data for service + * + * @param server mDNS Server + * @param service service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param num_items number of items in TXT data + * @param txt string array of TXT data (eg. {"var=val","other=2"}) + * + * @return + * - 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_txt_set(mdns_server_t * server, const char * service, const char * proto, uint8_t num_items, const char ** txt); + +/** + * @brief Set service port + * + * @param server mDNS Server + * @param service service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param port service port + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + */ +esp_err_t mdns_service_port_set(mdns_server_t * server, const char * service, const char * proto, uint16_t port); + +/** + * @brief Remove and free all services from mDNS server + * + * @param server mDNS Server + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t mdns_service_remove_all(mdns_server_t * server); + +/** + * @brief Query mDNS for host or service + * + * @param server mDNS Server + * @param service service type or host name + * @param proto service protocol or NULL if searching for host + * @param timeout time to wait for answers. If 0, mdns_query_end MUST be called to end the search + * + * @return the number of results found + */ +size_t mdns_query(mdns_server_t * server, const char * service, const char * proto, uint32_t timeout); + +/** + * @brief Stop mDNS Query started with timeout = 0 + * + * @param server mDNS Server + * + * @return the number of results found + */ +size_t mdns_query_end(mdns_server_t * server); + +/** + * @brief get the number of results currently in memoty + * + * @param server mDNS Server + * + * @return the number of results + */ +size_t mdns_result_get_count(mdns_server_t * server); + +/** + * @brief Get mDNS Search result with given index + * + * @param server mDNS Server + * @param num the index of the result + * + * @return the result or NULL if error + */ +const mdns_result_t * mdns_result_get(mdns_server_t * server, size_t num); + +/** + * @brief Remove and free all search results from mDNS server + * + * @param server mDNS Server + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t mdns_result_free(mdns_server_t * server); + +#ifdef __cplusplus +} +#endif + +#endif /* ESP_MDNS_H_ */ diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c new file mode 100644 index 000000000..d636134c7 --- /dev/null +++ b/components/mdns/mdns.c @@ -0,0 +1,1861 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "mdns.h" + +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "lwip/ip_addr.h" +#include "lwip/pbuf.h" +#include "lwip/igmp.h" +#include "lwip/udp.h" +#include "esp_wifi.h" + +#define MDNS_FLAGS_AUTHORITATIVE 0x8400 + +#define MDNS_NAME_REF 0xC000 + +#define MDNS_TYPE_AAAA 0x001C +#define MDNS_TYPE_A 0x0001 +#define MDNS_TYPE_PTR 0x000C +#define MDNS_TYPE_SRV 0x0021 +#define MDNS_TYPE_TXT 0x0010 +#define MDNS_TYPE_NSEC 0x002F +#define MDNS_TYPE_ANY 0x00FF + +#define MDNS_CLASS_IN 0x0001 +#define MDNS_CLASS_IN_FLUSH_CACHE 0x8001 + +#define MDNS_ANSWER_ALL 0x3F +#define MDNS_ANSWER_PTR 0x08 +#define MDNS_ANSWER_TXT 0x04 +#define MDNS_ANSWER_SRV 0x02 +#define MDNS_ANSWER_A 0x01 +#define MDNS_ANSWER_AAAA 0x10 +#define MDNS_ANSWER_NSEC 0x20 + +#define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on +#define MDNS_SERVICE_STACK_DEPTH 4096 // Stack size for the service thread +#define MDNS_PACKET_QUEUE_LEN 16 // Maximum packets that can be queued for parsing +#define MDNS_TXT_MAX_LEN 1024 // Maximum string length of text data in TXT record +#define MDNS_NAME_MAX_LEN 64 // Maximum string length of hostname, instance, service and proto +#define MDNS_NAME_BUF_LEN (MDNS_NAME_MAX_LEN+1) // Maximum char buffer size to hold hostname, instance, service or proto +#define MDNS_MAX_PACKET_SIZE 1460 // Maximum size of mDNS outgoing packet + +#define MDNS_ANSWER_PTR_TTL 4500 +#define MDNS_ANSWER_TXT_TTL 4500 +#define MDNS_ANSWER_SRV_TTL 120 +#define MDNS_ANSWER_A_TTL 120 +#define MDNS_ANSWER_AAAA_TTL 120 + +#define MDNS_HEAD_LEN 12 +#define MDNS_HEAD_ID_OFFSET 0 +#define MDNS_HEAD_FLAGS_OFFSET 2 +#define MDNS_HEAD_QUESTIONS_OFFSET 4 +#define MDNS_HEAD_ANSWERS_OFFSET 6 +#define MDNS_HEAD_SERVERS_OFFSET 8 +#define MDNS_HEAD_ADDITIONAL_OFFSET 10 + +#define MDNS_TYPE_OFFSET 0 +#define MDNS_CLASS_OFFSET 2 +#define MDNS_TTL_OFFSET 4 +#define MDNS_LEN_OFFSET 8 +#define MDNS_DATA_OFFSET 10 + +#define MDNS_SRV_PRIORITY_OFFSET 0 +#define MDNS_SRV_WEIGHT_OFFSET 2 +#define MDNS_SRV_PORT_OFFSET 4 +#define MDNS_SRV_FQDN_OFFSET 6 + +typedef struct { + char host[MDNS_NAME_BUF_LEN]; + char service[MDNS_NAME_BUF_LEN]; + char proto[MDNS_NAME_BUF_LEN]; + char domain[MDNS_NAME_BUF_LEN]; + uint8_t parts; + uint8_t sub; +} mdns_name_t; + +typedef struct { + char host[MDNS_NAME_BUF_LEN]; + char instance[MDNS_NAME_BUF_LEN]; + char txt[MDNS_TXT_MAX_LEN]; + uint16_t priority; + uint16_t weight; + uint16_t port; + uint32_t addr; + uint8_t addrv6[16]; + uint8_t ptr; +} mdns_result_temp_t; + +typedef struct { + const char * host; + const char * sub; + const char * service; + const char * proto; + const char * domain; + uint8_t parts; + uint8_t done; +} mdns_string_t; + +typedef struct mdns_service_s { + const char * instance; + const char * service; + const char * proto; + uint16_t priority; + uint16_t weight; + uint16_t port; + uint8_t txt_num_items; + const char ** txt; +} mdns_service_t; + +typedef struct mdns_srv_item_s { + mdns_service_t * service; + struct mdns_srv_item_s * next; +} mdns_srv_item_t; + +typedef struct mdns_answer_item_s { + mdns_service_t * service; + uint8_t answer; + struct mdns_answer_item_s * next; +} mdns_answer_item_t; + +struct mdns_server_s { + tcpip_adapter_if_t tcpip_if; + struct udp_pcb * pcb; + const char * hostname; + const char * instance; + mdns_srv_item_t * services; + xSemaphoreHandle lock; + xQueueHandle queue; + struct { + char host[MDNS_NAME_BUF_LEN]; + char service[MDNS_NAME_BUF_LEN]; + char proto[MDNS_NAME_BUF_LEN]; + bool running; + xSemaphoreHandle lock; + mdns_result_t * results; + } search; +}; + +#define MDNS_MUTEX_LOCK() xSemaphoreTake(server->lock, portMAX_DELAY) +#define MDNS_MUTEX_UNLOCK() xSemaphoreGive(server->lock) + +#define MDNS_SEARCH_LOCK() xSemaphoreTake(server->search.lock, portMAX_DELAY) +#define MDNS_SEARCH_UNLOCK() xSemaphoreGive(server->search.lock) + +static const char * MDNS_DEFAULT_DOMAIN = "local"; +static const char * MDNS_SUB_STR = "_sub"; + +static mdns_server_t * _mdns_servers[TCPIP_ADAPTER_IF_MAX] = {0,0,0}; +static TaskHandle_t _mdns_service_task_handle = NULL; +static QueueSetHandle_t _mdns_queue_set = NULL; + +static xSemaphoreHandle _mdns_service_semaphore = NULL; +#define MDNS_SERVICE_LOCK() xSemaphoreTake(_mdns_service_semaphore, portMAX_DELAY) +#define MDNS_SERVICE_UNLOCK() xSemaphoreGive(_mdns_service_semaphore) + +/* + * MDNS Server Networking + * */ + +/** + * @brief the receive callback of the raw udp api. Packets are received here + * + */ +static void _mdns_server_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *addr, uint16_t port) +{ + while(pb != NULL) { + struct pbuf * this_pb = pb; + pb = pb->next; + this_pb->next = NULL; + mdns_server_t * server = (mdns_server_t *)arg; + if (!server || !server->queue || xQueueSend(server->queue, &this_pb, (portTickType)0) != pdPASS) { + pbuf_free(this_pb); + } + } +} + +/** + * @brief init the network of MDNS server + * + * @param server The server + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE on igmp/bind error + * - ESP_ERR_NO_MEM on memory error + */ +esp_err_t _mdns_server_init(mdns_server_t * server) +{ + esp_err_t err = ESP_OK; + + tcpip_adapter_ip_info_t if_ip_info; + err = tcpip_adapter_get_ip_info(server->tcpip_if, &if_ip_info); + if (err) { + return err; + } + + ip_addr_t laddr; + IP_ADDR4(&laddr, 224, 0, 0, 251); + + ip_addr_t multicast_if_addr = IPADDR4_INIT(if_ip_info.ip.addr); + + if (igmp_joingroup((const struct ip4_addr *)&multicast_if_addr.u_addr.ip4, (const struct ip4_addr *)&laddr.u_addr.ip4)) { + return ESP_ERR_INVALID_STATE; + } + + struct udp_pcb * pcb = udp_new(); + if (!pcb) { + return ESP_ERR_NO_MEM; + } + + pcb->remote_port = MDNS_SERVICE_PORT; + + if (udp_bind(pcb, &multicast_if_addr, pcb->remote_port) != 0) { + udp_remove(pcb); + return ESP_ERR_INVALID_STATE; + } + + pcb->mcast_ttl = 1; + ip_addr_copy(pcb->multicast_ip, multicast_if_addr); + ip_addr_copy(pcb->remote_ip, laddr); + + server->pcb = pcb; + udp_recv(pcb, &_mdns_server_recv, server); + return err; +} + +/** + * @brief stop the network of MDNS server + * + * @param server The server + * + * @return ESP_OK + */ +esp_err_t _mdns_server_deinit(mdns_server_t * server) +{ + if (server->pcb) { + udp_recv(server->pcb, NULL, NULL); + udp_disconnect(server->pcb); + udp_remove(server->pcb); + server->pcb = NULL; + } + return ESP_OK; +} + +/** + * @brief send packet over UDP + * + * @param server The server + * @param data byte array containing the packet data + * @param len length of the packet data + * + * @return length of sent packet or 0 on error + */ +static size_t _mdns_server_write(mdns_server_t * server, uint8_t * data, size_t len) +{ + struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pbt != NULL) { + uint8_t* dst = (uint8_t *)pbt->payload; + memcpy(dst, data, len); + err_t err = udp_sendto(server->pcb, pbt, &(server->pcb->remote_ip), server->pcb->remote_port); + pbuf_free(pbt); + if (err) { + return 0; + } + return len; + } + return 0; +} + +/* + * MDNS Servers + * */ + +static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len); + +/** + * @brief the main MDNS service task. Packets are received and parsed here + */ +static void _mdns_service_task(void *pvParameters) +{ + uint8_t i; + struct pbuf * pb; + QueueSetMemberHandle_t queue; + + for(;;) { + queue = xQueueSelectFromSet(_mdns_queue_set, portMAX_DELAY); + if (queue && xQueueReceive(queue, &pb, 0) == pdTRUE) { + for(i=0; iqueue == queue) { + MDNS_MUTEX_LOCK(); + _mdns_parse_packet(server, (uint8_t*)pb->payload, pb->len); + MDNS_MUTEX_UNLOCK(); + break; + } + } + pbuf_free(pb); + } + } +} + +/** + * @brief get the server assigned to particular interface + * + * @param tcpip_if The interface + * + * @return reference to the server from the server list or NULL if not found + */ +static mdns_server_t * _mdns_server_get(tcpip_adapter_if_t tcpip_if) +{ + if (tcpip_if < TCPIP_ADAPTER_IF_MAX) { + return _mdns_servers[tcpip_if]; + } + return NULL; +} + +/** + * @brief add server to the server list. Start the service thread if not running + * + * @param server The server to add + * + * @return + * - ESP_OK on success + * - ESP_FAIL on error + * - ESP_ERR_* on network error + */ +static esp_err_t _mdns_server_add(mdns_server_t * server) +{ + if (!_mdns_service_semaphore) { + _mdns_service_semaphore = xSemaphoreCreateMutex(); + if (!_mdns_service_semaphore) { + return ESP_FAIL; + } + } + MDNS_SERVICE_LOCK(); + if (!_mdns_service_task_handle) { + _mdns_queue_set = xQueueCreateSet(TCPIP_ADAPTER_IF_MAX * MDNS_PACKET_QUEUE_LEN); + if (!_mdns_queue_set) { + MDNS_SERVICE_UNLOCK(); + return ESP_FAIL; + } + xTaskCreatePinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, 1, &_mdns_service_task_handle, 0); + if (!_mdns_service_task_handle) { + vQueueDelete(_mdns_queue_set); + _mdns_queue_set = NULL; + MDNS_SERVICE_UNLOCK(); + return ESP_FAIL; + } + } + MDNS_SERVICE_UNLOCK(); + + if (xQueueAddToSet(server->queue, _mdns_queue_set) != pdPASS) { + return ESP_FAIL; + } + + //start UDP + esp_err_t err = _mdns_server_init(server); + if (err) { + return err; + } + + _mdns_servers[server->tcpip_if] = server; + + return ESP_OK; +} + +/** + * @brief remove server from server list. Stop the service thread in no more servers are running + * + * @param server The server to remove + * + * @return + * - ESP_OK on success + * - ESP_FAIL on error + */ +static esp_err_t _mdns_server_remove(mdns_server_t * server) +{ + //stop UDP + _mdns_server_deinit(server); + + _mdns_servers[server->tcpip_if] = NULL; + + if (xQueueRemoveFromSet(server->queue, _mdns_queue_set) != pdPASS) { + return ESP_FAIL; + } + + uint8_t i; + for(i=0; iservice == service) { + //just add the new answer type to it + a->answer |= type; + return answers; + } + a = a->next; + } + //prepend the q with this new answer + a = (mdns_answer_item_t *)malloc(sizeof(mdns_answer_item_t)); + if (!a) { + return answers;//fail! + } + a->service = service; + a->answer = type; + a->next = answers; + answers = a; + return a; +} + +/** + * @brief reads MDNS FQDN into mdns_name_t structure + * FQDN is in format: [hostname.|[instance.]_service._proto.]local. + * + * @param packet MDNS packet + * @param start Starting point of FQDN + * @param name mdns_name_t structure to populate + * @param buf temporary char buffer + * + * @return the address after the parsed FQDN in the packet or NULL on error + */ +static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * start, mdns_name_t * name, char * buf) +{ + size_t index = 0; + while(start[index]) { + if (name->parts == 4) { + return NULL; + } + uint8_t len = start[index++]; + if ((len & 0xC0) == 0) { + if (len > 64) { + //length can not be more than 64 + return NULL; + } + uint8_t i; + for(i=0; iparts == 1 && buf[0] != '_' + && (strcmp(buf, MDNS_DEFAULT_DOMAIN) != 0) + && (strcmp(buf, "ip6") != 0) + && (strcmp(buf, "in-addr") != 0)) { + sprintf((char*)name, "%s.%s", name->host, buf); + } else if (strcmp(buf, MDNS_SUB_STR) == 0) { + name->sub = 1; + } else { + memcpy((uint8_t*)name + (name->parts++ * (MDNS_NAME_BUF_LEN)), buf, len+1); + } + } else { + size_t address = (((uint16_t)len & 0x3F) << 8) | start[index++]; + if ((packet + address) > start) { + //reference address can not be after where we are + return NULL; + } + if (_mdns_read_fqdn(packet, packet + address, name, buf)) { + return start + index; + } + return NULL; + } + } + return start + index + 1; +} + +/** + * @brief reads and formats MDNS FQDN into mdns_name_t structure + * + * @param packet MDNS packet + * @param start Starting point of FQDN + * @param name mdns_name_t structure to populate + * + * @return the address after the parsed FQDN in the packet or NULL on error + */ +static const uint8_t * _mdns_parse_fqdn(const uint8_t * packet, const uint8_t * start, mdns_name_t * name) +{ + name->parts = 0; + name->sub = 0; + name->host[0] = 0; + name->service[0] = 0; + name->proto[0] = 0; + name->domain[0] = 0; + + static char buf[MDNS_NAME_BUF_LEN]; + + const uint8_t * next_data = (uint8_t*)_mdns_read_fqdn(packet, start, name, buf); + if (!next_data || name->parts < 2) { + return 0; + } + if (name->parts == 3) { + memmove((uint8_t*)name + (MDNS_NAME_BUF_LEN), (uint8_t*)name, 3*(MDNS_NAME_BUF_LEN)); + name->host[0] = 0; + } else if (name->parts == 2) { + memmove((uint8_t*)(name->domain), (uint8_t*)(name->service), (MDNS_NAME_BUF_LEN)); + name->service[0] = 0; + name->proto[0] = 0; + } + if (strcmp(name->domain, MDNS_DEFAULT_DOMAIN) == 0 || strcmp(name->domain, "arpa") == 0) { + return next_data; + } + return 0; +} + +/* + * Packet construction + * */ + +/** + * @brief sets uint16_t value in a packet + * + * @param packet MDNS packet + * @param index offset of uint16_t value + * @param value the value to set + */ +static inline void _mdns_set_u16(uint8_t * packet, uint16_t index, uint16_t value) +{ + if ((index + 1) >= MDNS_MAX_PACKET_SIZE) { + return; + } + packet[index] = (value >> 8) & 0xFF; + packet[index+1] = value & 0xFF; +} + +/** + * @brief appends byte in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 1 on success + */ +static inline uint8_t _mdns_append_u8(uint8_t * packet, uint16_t * index, uint8_t value) +{ + if (*index >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + packet[*index] = value; + *index += 1; + return 1; +} + +/** + * @brief appends uint16_t in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 2 on success + */ +static inline uint8_t _mdns_append_u16(uint8_t * packet, uint16_t * index, uint16_t value) +{ + if ((*index + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, (value >> 8) & 0xFF); + _mdns_append_u8(packet, index, value & 0xFF); + return 2; +} + +/** + * @brief appends uint32_t in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 4 on success + */ +static inline uint8_t _mdns_append_u32(uint8_t * packet, uint16_t * index, uint32_t value) +{ + if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, (value >> 24) & 0xFF); + _mdns_append_u8(packet, index, (value >> 16) & 0xFF); + _mdns_append_u8(packet, index, (value >> 8) & 0xFF); + _mdns_append_u8(packet, index, value & 0xFF); + return 4; +} + +/** + * @brief appends answer type, class, ttl and data length to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param type answer type + * @param ttl answer ttl + * + * @return length of added data: 0 on error or 10 on success + */ +static inline uint8_t _mdns_append_type(uint8_t * packet, uint16_t * index, uint8_t type, uint32_t ttl) +{ + if ((*index + 10) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + if (type == MDNS_ANSWER_PTR) { + _mdns_append_u16(packet, index, MDNS_TYPE_PTR); + _mdns_append_u16(packet, index, MDNS_CLASS_IN); + } else if (type == MDNS_ANSWER_TXT) { + _mdns_append_u16(packet, index, MDNS_TYPE_TXT); + _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE); + } else if (type == MDNS_ANSWER_SRV) { + _mdns_append_u16(packet, index, MDNS_TYPE_SRV); + _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE); + } else if (type == MDNS_ANSWER_A) { + _mdns_append_u16(packet, index, MDNS_TYPE_A); + _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE); + } else if (type == MDNS_ANSWER_AAAA) { + _mdns_append_u16(packet, index, MDNS_TYPE_AAAA); + _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE); + } else { + return 0; + } + _mdns_append_u32(packet, index, ttl); + _mdns_append_u16(packet, index, 0); + return 10; +} + +/** + * @brief appends single string to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param string the string to append + * + * @return length of added data: 0 on error or length of the string + 1 on success + */ +static inline uint8_t _mdns_append_string(uint8_t * packet, uint16_t * index, const char * string) +{ + uint8_t len = strlen(string); + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, string, len); + *index += len; + return len + 1; +} + +/** + * @brief appends FQDN to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param strings string array containing the parts of the FQDN + * @param count number of strings in the array + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_fqdn(uint8_t * packet, uint16_t * index, const char * strings[], uint8_t count) +{ + if (!count) { + return _mdns_append_u8(packet, index, 0); + } + mdns_name_t name; + static char buf[MDNS_NAME_BUF_LEN]; + uint8_t len = strlen(strings[0]); + uint8_t * len_location = (uint8_t *)memchr(packet, (char)len, *index); + while(len_location) { + if (memcmp(len_location+1, strings[0], len)) { //not continuing with our string +search_next: + len_location = (uint8_t *)memchr(len_location+1, (char)len, *index - (len_location+1 - packet)); + continue; + } + //read string into name and compare + name.parts = 0; + name.sub = 0; + name.host[0] = 0; + name.service[0] = 0; + name.proto[0] = 0; + name.domain[0] = 0; + const uint8_t * content = _mdns_read_fqdn(packet, len_location, &name, buf); + if (!content) { + return 0; + } + if (name.parts == count) { + uint8_t i; + for(i=0; iinstance)?service->instance + :(server->instance)?server->instance + :server->hostname; + str[1] = service->service; + str[2] = service->proto; + str[3] = MDNS_DEFAULT_DOMAIN; + + part_length = _mdns_append_fqdn(packet, index, str + 1, 3); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, MDNS_ANSWER_PTR_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + part_length = _mdns_append_fqdn(packet, index, str, 4); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} + +/** + * @brief appends TXT record for service to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server that is hosting the service + * @param service the service to add record for + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, mdns_service_t * service) +{ + const char * str[4]; + uint16_t record_length = 0; + uint8_t part_length; + + str[0] = (service->instance)?service->instance + :(server->instance)?server->instance + :server->hostname; + str[1] = service->service; + str[2] = service->proto; + str[3] = MDNS_DEFAULT_DOMAIN; + + part_length = _mdns_append_fqdn(packet, index, str, 4); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_TXT, MDNS_ANSWER_TXT_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + uint16_t data_len = 0; + if (service->txt_num_items) { + uint8_t len = service->txt_num_items; + const char ** txt = service->txt; + uint8_t i, l; + for(i=0; iinstance)?service->instance + :(server->instance)?server->instance + :server->hostname; + str[1] = service->service; + str[2] = service->proto; + str[3] = MDNS_DEFAULT_DOMAIN; + + part_length = _mdns_append_fqdn(packet, index, str, 4); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_SRV, MDNS_ANSWER_SRV_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + + part_length = 0; + part_length += _mdns_append_u16(packet, index, service->priority); + part_length += _mdns_append_u16(packet, index, service->weight); + part_length += _mdns_append_u16(packet, index, service->port); + if (part_length != 6) { + return 0; + } + + str[0] = server->hostname; + str[1] = MDNS_DEFAULT_DOMAIN; + part_length = _mdns_append_fqdn(packet, index, str, 2); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length + 6); + + record_length += part_length + 6; + return record_length; +} + +/** + * @brief appends A record to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server + * @param ip the IP address to add + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, uint32_t ip) +{ + const char * str[2]; + uint16_t record_length = 0; + uint8_t part_length; + + str[0] = server->hostname; + str[1] = MDNS_DEFAULT_DOMAIN; + + part_length = _mdns_append_fqdn(packet, index, str, 2); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_A, MDNS_ANSWER_A_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + + if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, ip & 0xFF); + _mdns_append_u8(packet, index, (ip >> 8) & 0xFF); + _mdns_append_u8(packet, index, (ip >> 16) & 0xFF); + _mdns_append_u8(packet, index, (ip >> 24) & 0xFF); + _mdns_set_u16(packet, data_len_location, 4); + + record_length += 4; + return record_length; +} + +/** + * @brief appends AAAA record to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server + * @param ipv6 the IPv6 address to add + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, uint8_t * ipv6) +{ + const char * str[2]; + uint16_t record_length = 0; + uint8_t part_length; + + str[0] = server->hostname; + str[1] = MDNS_DEFAULT_DOMAIN; + + part_length = _mdns_append_fqdn(packet, index, str, 2); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_AAAA, MDNS_ANSWER_AAAA_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + + if ((*index + 15) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + + part_length = sizeof(ip6_addr_t); + memcpy(packet + *index, ipv6, part_length); + *index += part_length; + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} + +/** + * @brief sends all collected answers + * + * @param server the server + * @param answers linked list of answers + */ +static void _mdns_send_answers(mdns_server_t * server, mdns_answer_item_t * answers) +{ + bool send_ip = false; + static uint8_t packet[MDNS_MAX_PACKET_SIZE]; + uint16_t index = MDNS_HEAD_LEN; + uint8_t answer_count = 0; + + memset(packet, 0, MDNS_HEAD_LEN); + + _mdns_set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, MDNS_FLAGS_AUTHORITATIVE); + + while(answers) { + if (answers->answer & MDNS_ANSWER_A) { + answers->answer &= ~MDNS_ANSWER_A; + send_ip = true; + } + if (answers->service) { + + if (answers->answer & MDNS_ANSWER_PTR) { + if (!_mdns_append_ptr_record(packet, &index, server, answers->service)) { + return; + } + answer_count += 1; + } + + if (answers->answer & MDNS_ANSWER_TXT) { + if (!_mdns_append_txt_record(packet, &index, server, answers->service)) { + return; + } + answer_count += 1; + } + + if (answers->answer & MDNS_ANSWER_SRV) { + if (!_mdns_append_srv_record(packet, &index, server, answers->service)) { + return; + } + answer_count += 1; + } + } + mdns_answer_item_t * a = answers; + answers = answers->next; + free(a); + } + if (send_ip) { + tcpip_adapter_ip_info_t if_ip_info; + tcpip_adapter_get_ip_info(server->tcpip_if, &if_ip_info); + + if (!_mdns_append_a_record(packet, &index, server, if_ip_info.ip.addr)) { + return; + } + answer_count += 1; + + //add ipv6 if available + struct ip6_addr if_ip6; + if (!tcpip_adapter_get_ip6_linklocal(server->tcpip_if, &if_ip6)) { + uint8_t * v6addr = (uint8_t*)if_ip6.addr; + //check if not 0 + int i; + for(i=0;ipriority = r->priority; + n->weight = r->weight; + n->port = r->port; + n->addr.addr = r->addr; + + size_t hlen = strlen(r->host); + if (hlen) { + n->host = strdup(r->host); + if (!n->host) { + free(n); + return; + } + } else { + n->host = NULL; + } + + size_t ilen = strlen(r->instance); + if (ilen) { + n->instance = strdup(r->instance); + if (!n->instance) { + free((char *)n->host); + free(n); + return; + } + } else { + n->instance = NULL; + } + + size_t tlen = strlen(r->txt); + if (tlen) { + n->txt = strdup(r->txt); + if (!n->txt) { + free((char *)n->host); + free((char *)n->instance); + free(n); + return; + } + } else { + n->txt = NULL; + } + + memcpy((uint8_t *)n->addrv6.addr, r->addrv6, sizeof(ip6_addr_t)); + + mdns_result_t * o = server->search.results; + server->search.results = n; + n->next = o; +} + +/** + * @brief finds service from given service type + * @param server the server + * @param service service type to match + * @param proto proto to match + * + * @return the service item if found or NULL on error + */ +static mdns_srv_item_t * _mdns_get_service_item(mdns_server_t * server, const char * service, const char * proto) +{ + mdns_srv_item_t * s = server->services; + while(s) { + if (!strcmp(s->service->service, service) && !strcmp(s->service->proto, proto)) { + return s; + } + s = s->next; + } + return NULL; +} + +/** + * @brief creates/allocates new service + * @param service service type + * @param proto service proto + * @param port service port + * + * @return pointer to the service or NULL on error + */ +static mdns_service_t * _mdns_create_service(const char * service, const char * proto, uint16_t port) +{ + mdns_service_t * s = (mdns_service_t *)malloc(sizeof(mdns_service_t)); + if (!s) { + return NULL; + } + + s->priority = 0; + s->weight = 0; + s->txt_num_items = 0; + s->instance = NULL; + s->txt = NULL; + s->port = port; + + s->service = strdup(service); + if (!s->service) { + free(s); + return NULL; + } + + s->proto = strdup(proto); + if (!s->proto) { + free((char *)s->service); + free(s); + return NULL; + } + + return s; +} + +/** + * @brief free service memory + * + * @param service the service + */ +static void _mdns_free_service(mdns_service_t * service) +{ + if (!service) { + return; + } + free((char *)service->instance); + free((char *)service->service); + free((char *)service->proto); + if (service->txt_num_items) { + uint8_t i; + for(i=0; itxt_num_items; i++) { + free((char *)service->txt[i]); + } + } + free(service->txt); + free(service); +} + +/** + * @brief read uint16_t from a packet + * @param packet the packet + * @param index index in the packet where the value starts + * + * @return the value + */ +static inline uint16_t _mdns_read_u16(const uint8_t * packet, uint16_t index) +{ + return (uint16_t)(packet[index]) << 8 | packet[index+1]; +} + +/** + * @brief main packet parser + * + * @param server the server + * @param data byte array holding the packet data + * @param len length of the byte array + */ +static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len) +{ + static mdns_name_t n; + static mdns_result_temp_t a; + + const uint8_t * content = data + MDNS_HEAD_LEN; + mdns_name_t * name = &n; + memset(name, 0, sizeof(mdns_name_t)); + + uint16_t questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); + uint16_t answers = _mdns_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); + uint16_t additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); + + if (questions) { + uint8_t qs = questions; + mdns_answer_item_t * answers = NULL; + + while(qs--) { + content = _mdns_parse_fqdn(data, content, name); + if (!content) { + break;//error + } + + uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); + content = content + 4; + + if (!name->service[0] || !name->proto[0]) { + if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA || type == MDNS_TYPE_ANY) {//send A + AAAA + if (name->host[0] && server->hostname && server->hostname[0] && !strcmp(name->host, server->hostname)) { + answers = _mdns_add_answer(answers, NULL, MDNS_ANSWER_A); + } + } + continue; + } + + if (name->sub) { + continue; + } + + mdns_srv_item_t * si = _mdns_get_service_item(server, name->service, name->proto); + if (!si) { + //service not found + continue; + } + + if (type == MDNS_TYPE_PTR) { + answers = _mdns_add_answer(answers, si->service, MDNS_ANSWER_ALL); + } else if (type == MDNS_TYPE_TXT) { + //match instance/host + const char * host = (si->service->instance)?si->service->instance + :(server->instance)?server->instance + :server->hostname; + if (!host || !host[0] || !name->host[0] || strcmp(name->host, host)) { + continue; + } + answers = _mdns_add_answer(answers, si->service, MDNS_ANSWER_TXT); + } else if (type == MDNS_TYPE_SRV) { + //match instance/host + const char * host = (si->service->instance)?si->service->instance + :(server->instance)?server->instance + :server->hostname; + if (!host || !host[0] || !name->host[0] || strcmp(name->host, host)) { + continue; + } + answers = _mdns_add_answer(answers, si->service, MDNS_ANSWER_SRV | MDNS_ANSWER_A); + } else if (type == MDNS_TYPE_ANY) {//send all + //match host + if (!name->host[0] || !server->hostname || !server->hostname[0] || strcmp(name->host, server->hostname)) { + answers = _mdns_add_answer(answers, si->service, MDNS_ANSWER_ALL); + } + } + } + if (answers) { + _mdns_send_answers(server, answers); + } + } + + if (server->search.running && (answers || additional)) { + mdns_result_temp_t * answer = &a; + memset(answer, 0, sizeof(mdns_result_temp_t)); + + while(content < (data + len)) { + content = _mdns_parse_fqdn(data, content, name); + if (!content) { + break;//error + } + uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t data_len = _mdns_read_u16(content, MDNS_LEN_OFFSET); + const uint8_t * data_ptr = content + MDNS_DATA_OFFSET; + + content = data_ptr + data_len; + + if (type == MDNS_TYPE_PTR) { + if (!_mdns_parse_fqdn(data, data_ptr, name)) { + continue;//error + } + if (server->search.host[0] || + (strcmp(name->service, server->search.service) != 0) || + (strcmp(name->proto, server->search.proto) != 0)) { + continue;//not searching for service or wrong service/proto + } + sprintf(answer->instance, "%s", name->host); + } else if (type == MDNS_TYPE_SRV) { + if (server->search.host[0] || + (strcmp(name->service, server->search.service) != 0) || + (strcmp(name->proto, server->search.proto) != 0)) { + continue;//not searching for service or wrong service/proto + } + if (answer->instance[0]) { + if (strcmp(answer->instance, name->host) != 0) { + continue;//instance name is not the same as the one in the PTR record + } + } else { + sprintf(answer->instance, "%s", name->host); + } + //parse record value + if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name)) { + continue;//error + } + + answer->ptr = 1; + answer->priority = _mdns_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); + answer->weight = _mdns_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); + answer->port = _mdns_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); + if (answer->host[0]) { + if (strcmp(answer->host, name->host) != 0) { + answer->addr = 0; + sprintf(answer->host, "%s", name->host); + } + } else { + sprintf(answer->host, "%s", name->host); + } + } else if (type == MDNS_TYPE_TXT) { + uint16_t i=0,b=0, y; + while(i < data_len) { + uint8_t partLen = data_ptr[i++]; + for(y=0; ytxt[b++] = d; + } + if (itxt[b++] = '&'; + } + } + answer->txt[b] = 0; + } else if (type == MDNS_TYPE_AAAA) { + if (server->search.host[0]) { + if (strcmp(name->host, server->search.host) != 0) { + continue;//wrong host + } + } else if (!answer->ptr) { + sprintf(answer->host, "%s", name->host); + } else if (strcmp(answer->host, name->host) != 0) { + continue;//wrong host + } + memcpy(answer->addrv6, data_ptr, sizeof(ip6_addr_t)); + } else if (type == MDNS_TYPE_A) { + if (server->search.host[0]) { + if (strcmp(name->host, server->search.host) != 0) { + continue;//wrong host + } + } else if (!answer->ptr) { + sprintf(answer->host, "%s", name->host); + } else if (strcmp(answer->host, name->host) != 0) { + continue;//wrong host + } + if (server->search.running && answer->addr) { + _mdns_add_result(server, answer);//another IP for our host + } + IP4_ADDR(answer, data_ptr[0], data_ptr[1], data_ptr[2], data_ptr[3]); + } + } + if (server->search.running && (server->search.host[0] || answer->ptr) && answer->addr) { + _mdns_add_result(server, answer); + } + //end while + } +} + + + +/* + * Public Methods + * */ +esp_err_t mdns_init(tcpip_adapter_if_t tcpip_if, mdns_server_t ** mdns_server) +{ + esp_err_t err = ESP_OK; + + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { + return ESP_ERR_INVALID_ARG; + } + + if (_mdns_server_get(tcpip_if)) { + return ESP_ERR_INVALID_STATE; + } + + uint8_t mode; + err = esp_wifi_get_mode((wifi_mode_t*)&mode); + if (err) { + return err; + } + + if ((tcpip_if == TCPIP_ADAPTER_IF_STA && !(mode & WIFI_MODE_STA)) + || (tcpip_if == TCPIP_ADAPTER_IF_AP && !(mode & WIFI_MODE_AP))) { + return ESP_ERR_INVALID_ARG; + } + + mdns_server_t * server = (mdns_server_t *)malloc(sizeof(mdns_server_t)); + if (!server) { + return ESP_ERR_NO_MEM; + } + + server->tcpip_if = tcpip_if; + server->hostname = NULL; + server->instance = NULL; + server->services = NULL; + server->search.host[0] = 0; + server->search.service[0] = 0; + server->search.proto[0] = 0; + server->search.running = false; + server->search.results = NULL; + server->pcb = NULL; + + server->lock = xSemaphoreCreateMutex(); + if (!server->lock) { + free(server); + return ESP_ERR_NO_MEM; + } + + server->search.lock = xSemaphoreCreateMutex(); + if (!server->search.lock) { + vSemaphoreDelete(server->lock); + free(server); + return ESP_ERR_NO_MEM; + } + + server->queue = xQueueCreate(MDNS_PACKET_QUEUE_LEN, sizeof(struct pbuf *)); + if (!server->queue) { + vSemaphoreDelete(server->lock); + vSemaphoreDelete(server->search.lock); + free(server); + return ESP_ERR_NO_MEM; + } + + if (_mdns_server_add(server)) { + //service start failed! + vSemaphoreDelete(server->lock); + vSemaphoreDelete(server->search.lock); + vQueueDelete(server->queue); + free(server); + return ESP_FAIL; + } + + const char * hostname = NULL; + tcpip_adapter_get_hostname(server->tcpip_if, &hostname); + mdns_set_hostname(server, hostname); + + *mdns_server = server; + + return ESP_OK; +} + +void mdns_free(mdns_server_t * server) +{ + if (!server) { + return; + } + _mdns_server_remove(server); + mdns_service_remove_all(server); + MDNS_MUTEX_LOCK(); + free((char*)server->hostname); + free((char*)server->instance); + if (server->queue) { + struct pbuf * c; + while(xQueueReceive(server->queue, &c, 0) == pdTRUE) { + pbuf_free(c); + } + vQueueDelete(server->queue); + } + if (server->search.running) { + mdns_query_end(server); + } + mdns_result_free(server); + vSemaphoreDelete(server->search.lock); + MDNS_MUTEX_UNLOCK(); + vSemaphoreDelete(server->lock); + free(server); +} + +esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname) +{ + if (!server) { + return ESP_ERR_INVALID_ARG; + } + MDNS_MUTEX_LOCK(); + free((char*)server->hostname); + server->hostname = (char *)malloc(strlen(hostname)+1); + if (!server->hostname) { + MDNS_MUTEX_UNLOCK(); + return ESP_ERR_NO_MEM; + } + sprintf((char *)server->hostname, "%s", hostname); + MDNS_MUTEX_UNLOCK(); + return ERR_OK; +} + +esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance) +{ + if (!server) { + return ESP_ERR_INVALID_ARG; + } + MDNS_MUTEX_LOCK(); + free((char*)server->instance); + server->instance = (char *)malloc(strlen(instance)+1); + if (!server->instance) { + MDNS_MUTEX_UNLOCK(); + return ESP_ERR_NO_MEM; + } + sprintf((char *)server->instance, "%s", instance); + MDNS_MUTEX_UNLOCK(); + return ERR_OK; +} + +/* + * MDNS SERVICES + * */ + +esp_err_t mdns_service_add(mdns_server_t * server, const char * service, const char * proto, uint16_t port) +{ + if (!server || !service || !proto || !port) { + //bad argument + return ESP_ERR_INVALID_ARG; + } + mdns_srv_item_t * item = _mdns_get_service_item(server, service, proto); + if (item) { + //we already have that service + return mdns_service_port_set(server, service, proto, port); + } + + mdns_service_t * s = _mdns_create_service(service, proto, port); + if (!s) { + return ESP_ERR_NO_MEM; + } + + item = (mdns_srv_item_t *)malloc(sizeof(mdns_srv_item_t)); + if (!item) { + return ESP_ERR_NO_MEM; + } + + item->service = s; + item->next = server->services; + server->services = item; + return ESP_OK; +} + +esp_err_t mdns_service_port_set(mdns_server_t * server, const char * service, const char * proto, uint16_t port) +{ + if (!server || !server->services || !service || !proto || !port) { + return ESP_ERR_INVALID_ARG; + } + mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto); + if (!s) { + return ESP_ERR_NOT_FOUND; + } + MDNS_MUTEX_LOCK(); + s->service->port = port; + MDNS_MUTEX_UNLOCK(); + return ESP_OK; +} + +esp_err_t mdns_service_txt_set(mdns_server_t * server, const char * service, const char * proto, uint8_t num_items, const char ** txt) +{ + if (!server || !server->services || !service || !proto) { + return ESP_ERR_INVALID_ARG; + } + mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto); + if (!s) { + return ESP_ERR_NOT_FOUND; + } + MDNS_MUTEX_LOCK(); + if (s->service->txt_num_items) { + uint8_t i; + for(i=0; iservice->txt_num_items; i++) { + free((char *)s->service->txt[i]); + } + } + free(s->service->txt); + if (num_items) { + s->service->txt = (const char **)malloc(sizeof(char *) * num_items); + if (!s->service->txt) { + s->service->txt_num_items = 0; + goto fail; + } + uint8_t i; + s->service->txt_num_items = num_items; + for(i=0; iservice->txt[i] = strdup(txt[i]); + if (!s->service->txt[i]) { + s->service->txt_num_items = i; + goto fail; + } + } + } + MDNS_MUTEX_UNLOCK(); + return ESP_OK; +fail: + MDNS_MUTEX_UNLOCK(); + return ESP_ERR_NO_MEM; +} + +esp_err_t mdns_service_instance_set(mdns_server_t * server, const char * service, const char * proto, const char * instance) +{ + if (!server || !server->services || !service || !proto) { + return ESP_ERR_INVALID_ARG; + } + mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto); + if (!s) { + return ESP_ERR_NOT_FOUND; + } + MDNS_MUTEX_LOCK(); + free((char*)s->service->instance); + s->service->instance = strdup(instance); + if (!s->service->instance) { + MDNS_MUTEX_UNLOCK(); + return ESP_ERR_NO_MEM; + } + MDNS_MUTEX_UNLOCK(); + return ESP_OK; +} + +esp_err_t mdns_service_remove(mdns_server_t * server, const char * service, const char * proto) +{ + if (!server || !server->services || !service || !proto) { + return ESP_ERR_INVALID_ARG; + } + mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto); + if (!s) { + return ESP_ERR_NOT_FOUND; + } + //first item + if (server->services == s) { + MDNS_MUTEX_LOCK(); + server->services = server->services->next; + MDNS_MUTEX_UNLOCK(); + _mdns_free_service(s->service); + free(s); + return ESP_OK; + } + //not first item + mdns_srv_item_t * a = server->services; + while(a->next && a->next != s) { + a = a->next; + } + //next item of the current item is our item + if (a->next == s) { + MDNS_MUTEX_LOCK(); + a->next = s->next; + MDNS_MUTEX_UNLOCK(); + _mdns_free_service(s->service); + free(s); + return ESP_OK; + } + //how did we end here? + return ESP_FAIL; +} + +esp_err_t mdns_service_remove_all(mdns_server_t * server) +{ + if (!server) { + return ESP_ERR_INVALID_ARG; + } + if (!server->services) { + return ESP_OK; + } + MDNS_MUTEX_LOCK(); + mdns_srv_item_t * a = server->services; + server->services = NULL; + while(a) { + mdns_srv_item_t * s = a; + a = a->next; + _mdns_free_service(s->service); + free(s); + } + MDNS_MUTEX_UNLOCK(); + return ESP_OK; +} + +/* + * MDNS QUERY + * */ + +uint32_t mdns_query(mdns_server_t * server, const char * service, const char * proto, uint32_t timeout) +{ + if (!server || !service) { + return 0; + } + MDNS_SEARCH_LOCK(); + uint16_t qtype = MDNS_TYPE_PTR; + mdns_result_free(server); + if (proto) { + server->search.host[0] = 0; + snprintf(server->search.service, MDNS_NAME_MAX_LEN, "%s", service); + snprintf(server->search.proto, MDNS_NAME_MAX_LEN, "%s", proto); + } else { + snprintf(server->search.host, MDNS_NAME_MAX_LEN, "%s", service); + server->search.service[0] = 0; + server->search.proto[0] = 0; + qtype = MDNS_TYPE_A; + } + + uint8_t hostname_len = strlen(server->search.host); + uint8_t service_type_len = strlen(server->search.service); + uint8_t protoname_len = strlen(server->search.proto); + + size_t len = 23; //head+type+class+(strlen(local)+1)+fqdn_end + if (hostname_len) { + len += hostname_len + 1; + } else if (service_type_len) { + len += service_type_len + protoname_len + 2; + } + + uint8_t * packet = (uint8_t *)malloc(len); + if (!packet) { + return 0; + } + memset(packet, 0, len); + _mdns_set_u16(packet, MDNS_HEAD_QUESTIONS_OFFSET, 1); + uint16_t index = MDNS_HEAD_LEN; + + if (hostname_len) { + _mdns_append_string(packet, &index, server->search.host); + } else if (service_type_len) { + _mdns_append_string(packet, &index, server->search.service); + _mdns_append_string(packet, &index, server->search.proto); + } + + _mdns_append_string(packet, &index, MDNS_DEFAULT_DOMAIN); + _mdns_append_u8(packet, &index, 0); //fqdn_end + + _mdns_append_u16(packet, &index, qtype); + _mdns_append_u16(packet, &index, MDNS_CLASS_IN); + + MDNS_MUTEX_LOCK(); + size_t written = _mdns_server_write(server, packet, index); + MDNS_MUTEX_UNLOCK(); + free(packet); + if (written != index) { + return 0; + } + + server->search.running = true; + if (timeout) { + uint32_t startAt = xTaskGetTickCount() * portTICK_PERIOD_MS; + while(server->search.running && ((xTaskGetTickCount() * portTICK_PERIOD_MS) - startAt) < timeout) { + vTaskDelay(1 / portTICK_PERIOD_MS); + } + server->search.running = false; + MDNS_SEARCH_UNLOCK(); + return mdns_result_get_count(server); + } + return 0; +} + +size_t mdns_query_end(mdns_server_t * server) +{ + if (!server || !server->search.running) { + return 0; + } + server->search.running = false; + MDNS_SEARCH_UNLOCK(); + return mdns_result_get_count(server); +} + +esp_err_t mdns_result_free(mdns_server_t * server) +{ + if (!server || server->search.running || !server->search.results) { + return ESP_ERR_INVALID_ARG; + } + while(server->search.results) { + const mdns_result_t * r = server->search.results; + server->search.results = (mdns_result_t *)r->next; + free((char *)r->host); + free((char *)r->instance); + free((char *)r->txt); + free((mdns_result_t *)r); + } + server->search.results = NULL; + return ESP_OK; +} + +size_t mdns_result_get_count(mdns_server_t * server) +{ + if (!server || !server->search.results) { + return 0; + } + size_t len = 0; + const mdns_result_t * r = server->search.results; + while(r) { + len++; + r = r->next; + } + return len; +} + +const mdns_result_t * mdns_result_get(mdns_server_t * server, size_t num) +{ + if (!server || !server->search.results) { + return NULL; + } + size_t len = 0; + const mdns_result_t * r = server->search.results; + while(r) { + if (len++ == num) { + return r; + } + r = r->next; + } + return NULL; +} From 441a53c604f5ec2c89bc43561a336355f5ca2334 Mon Sep 17 00:00:00 2001 From: Krzysztof Budzynski Date: Mon, 16 Jan 2017 23:08:35 +0100 Subject: [PATCH 002/289] Moved examples to new folders / categories. Removed example numbers from example names * Original commit: espressif/esp-idf@382999b378dfeb1dc224c74e8830e64fa1ed0d61 --- examples/protocols/mdns/Makefile | 9 + examples/protocols/mdns/README.md | 5 + .../protocols/mdns/main/Kconfig.projbuild | 29 +++ examples/protocols/mdns/main/component.mk | 4 + .../protocols/mdns/main/mdns_example_main.c | 184 ++++++++++++++++++ 5 files changed, 231 insertions(+) create mode 100644 examples/protocols/mdns/Makefile create mode 100644 examples/protocols/mdns/README.md create mode 100644 examples/protocols/mdns/main/Kconfig.projbuild create mode 100644 examples/protocols/mdns/main/component.mk create mode 100644 examples/protocols/mdns/main/mdns_example_main.c diff --git a/examples/protocols/mdns/Makefile b/examples/protocols/mdns/Makefile new file mode 100644 index 000000000..0353c51c0 --- /dev/null +++ b/examples/protocols/mdns/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := mdns-test + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/protocols/mdns/README.md b/examples/protocols/mdns/README.md new file mode 100644 index 000000000..1c298604b --- /dev/null +++ b/examples/protocols/mdns/README.md @@ -0,0 +1,5 @@ +# 30_mdns example + +Shows how to use mDNS to advertise lookup services and hosts + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild new file mode 100644 index 000000000..3122e0309 --- /dev/null +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -0,0 +1,29 @@ +menu "Example Configuration" + +config WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + +config WIFI_PASSWORD + string "WiFi Password" + default "myssid" + help + WiFi password (WPA or WPA2) for the example to use. + + Can be left blank if the network has no security set. + +config MDNS_HOSTNAME + string "mDNS Hostname" + default "esp32-mdns" + help + mDNS Hostname for example to use + +config MDNS_INSTANCE + string "mDNS Instance Name" + default "ESP32 with mDNS" + help + mDNS Instance Name for example to use + +endmenu \ No newline at end of file diff --git a/examples/protocols/mdns/main/component.mk b/examples/protocols/mdns/main/component.mk new file mode 100644 index 000000000..a98f634ea --- /dev/null +++ b/examples/protocols/mdns/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c new file mode 100644 index 000000000..d19fd1ae6 --- /dev/null +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -0,0 +1,184 @@ +/* MDNS-SD Query and advertise Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "mdns.h" + +/* The examples use simple WiFi configuration that you can set via + 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID +#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD + +#define EXAMPLE_MDNS_HOSTNAME CONFIG_MDNS_HOSTNAME +#define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE + +/* FreeRTOS event group to signal when we are connected & ready to make a request */ +static EventGroupHandle_t wifi_event_group; + +/* The event group allows multiple bits for each event, + but we only care about one event - are we connected + to the AP with an IP? */ +const int CONNECTED_BIT = BIT0; + +static const char *TAG = "mdns-test"; + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + switch(event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_CONNECTED: + /* enable ipv6 */ + tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); + break; + case SYSTEM_EVENT_STA_GOT_IP: + xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + /* This is a workaround as ESP32 WiFi libs don't currently + auto-reassociate. */ + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +static void initialise_wifi(void) +{ + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); + ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); + wifi_config_t wifi_config = { + .sta = { + .ssid = EXAMPLE_WIFI_SSID, + .password = EXAMPLE_WIFI_PASS, + }, + }; + ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); + ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); + ESP_ERROR_CHECK( esp_wifi_start() ); +} + +static void query_mdns_service(mdns_server_t * mdns, const char * service, const char * proto) +{ + if(!mdns) { + return; + } + uint32_t res; + if (!proto) { + ESP_LOGI(TAG, "Host Lookup: %s", service); + res = mdns_query(mdns, service, 0, 1000); + if (res) { + size_t i; + for(i=0; iaddr), IPV62STR(r->addrv6)); + } + } + mdns_result_free(mdns); + } else { + ESP_LOGI(TAG, " Not Found"); + } + } else { + ESP_LOGI(TAG, "Service Lookup: %s.%s ", service, proto); + res = mdns_query(mdns, service, proto, 1000); + if (res) { + size_t i; + for(i=0; ihost)?r->host:"", (r->instance)?r->instance:"", + IP2STR(&r->addr), IPV62STR(r->addrv6), + r->port, (r->txt)?r->txt:""); + } + } + mdns_result_free(mdns); + } + } +} + +static void mdns_task(void *pvParameters) +{ + mdns_server_t * mdns = NULL; + while(1) { + /* Wait for the callback to set the CONNECTED_BIT in the + event group. + */ + xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, + false, true, portMAX_DELAY); + ESP_LOGI(TAG, "Connected to AP"); + + if (!mdns) { + esp_err_t err = mdns_init(TCPIP_ADAPTER_IF_STA, &mdns); + if (err) { + ESP_LOGE(TAG, "Failed starting MDNS: %u", err); + continue; + } + + ESP_ERROR_CHECK( mdns_set_hostname(mdns, EXAMPLE_MDNS_HOSTNAME) ); + ESP_ERROR_CHECK( mdns_set_instance(mdns, EXAMPLE_MDNS_INSTANCE) ); + + const char * arduTxtData[4] = { + "board=esp32", + "tcp_check=no", + "ssh_upload=no", + "auth_upload=no" + }; + + ESP_ERROR_CHECK( mdns_service_add(mdns, "_arduino", "_tcp", 3232) ); + ESP_ERROR_CHECK( mdns_service_txt_set(mdns, "_arduino", "_tcp", 4, arduTxtData) ); + ESP_ERROR_CHECK( mdns_service_add(mdns, "_http", "_tcp", 80) ); + ESP_ERROR_CHECK( mdns_service_instance_set(mdns, "_http", "_tcp", "ESP32 WebServer") ); + ESP_ERROR_CHECK( mdns_service_add(mdns, "_smb", "_tcp", 445) ); + } else { + query_mdns_service(mdns, "esp32", NULL); + query_mdns_service(mdns, "_arduino", "_tcp"); + query_mdns_service(mdns, "_http", "_tcp"); + query_mdns_service(mdns, "_printer", "_tcp"); + query_mdns_service(mdns, "_ipp", "_tcp"); + query_mdns_service(mdns, "_afpovertcp", "_tcp"); + query_mdns_service(mdns, "_smb", "_tcp"); + query_mdns_service(mdns, "_ftp", "_tcp"); + query_mdns_service(mdns, "_nfs", "_tcp"); + } + + ESP_LOGI(TAG, "Restarting in 10 seconds!"); + vTaskDelay(10000 / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "Starting again!"); + } +} + +void app_main() +{ + nvs_flash_init(); + initialise_wifi(); + xTaskCreate(&mdns_task, "mdns_task", 2048, NULL, 5, NULL); +} From caa4884b3ad6c4efec41fc2e09f8541cfa2c23cf Mon Sep 17 00:00:00 2001 From: krzychb Date: Wed, 18 Jan 2017 21:03:15 +0100 Subject: [PATCH 003/289] Added README.md to example category folders * Original commit: espressif/esp-idf@0b6598c49206228896f41f20ada2382270d9da6b --- examples/protocols/mdns/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/mdns/README.md b/examples/protocols/mdns/README.md index 1c298604b..76dbdc17b 100644 --- a/examples/protocols/mdns/README.md +++ b/examples/protocols/mdns/README.md @@ -1,4 +1,4 @@ -# 30_mdns example +# mDNS example Shows how to use mDNS to advertise lookup services and hosts From 91bb5095f52b66ac23799890994abb503990c706 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 13 Mar 2017 11:56:50 +0200 Subject: [PATCH 004/289] address security issues with mDNS * Original commit: espressif/esp-idf@c89e11c8fa64641edddf9a055745d825ae3fab9d --- components/mdns/mdns.c | 43 +++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index d636134c7..d0fc69c4c 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -491,7 +491,7 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s && (strcmp(buf, MDNS_DEFAULT_DOMAIN) != 0) && (strcmp(buf, "ip6") != 0) && (strcmp(buf, "in-addr") != 0)) { - sprintf((char*)name, "%s.%s", name->host, buf); + snprintf((char*)name, MDNS_NAME_BUF_LEN, "%s.%s", name->host, buf); } else if (strcmp(buf, MDNS_SUB_STR) == 0) { name->sub = 1; } else { @@ -499,7 +499,7 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s } } else { size_t address = (((uint16_t)len & 0x3F) << 8) | start[index++]; - if ((packet + address) > start) { + if ((packet + address) >= start) { //reference address can not be after where we are return NULL; } @@ -1182,13 +1182,13 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * s->txt = NULL; s->port = port; - s->service = strdup(service); + s->service = strndup(service, MDNS_NAME_BUF_LEN - 1); if (!s->service) { free(s); return NULL; } - s->proto = strdup(proto); + s->proto = strndup(proto, MDNS_NAME_BUF_LEN - 1); if (!s->proto) { free((char *)s->service); free(s); @@ -1341,7 +1341,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz (strcmp(name->proto, server->search.proto) != 0)) { continue;//not searching for service or wrong service/proto } - sprintf(answer->instance, "%s", name->host); + strlcpy(answer->instance, name->host, MDNS_NAME_BUF_LEN); } else if (type == MDNS_TYPE_SRV) { if (server->search.host[0] || (strcmp(name->service, server->search.service) != 0) || @@ -1353,7 +1353,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz continue;//instance name is not the same as the one in the PTR record } } else { - sprintf(answer->instance, "%s", name->host); + strlcpy(answer->instance, name->host, MDNS_NAME_BUF_LEN); } //parse record value if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name)) { @@ -1367,15 +1367,19 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz if (answer->host[0]) { if (strcmp(answer->host, name->host) != 0) { answer->addr = 0; - sprintf(answer->host, "%s", name->host); + strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN); } } else { - sprintf(answer->host, "%s", name->host); + strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN); } } else if (type == MDNS_TYPE_TXT) { uint16_t i=0,b=0, y; while(i < data_len) { uint8_t partLen = data_ptr[i++]; + //check if partLen will fit in the buffer + if (partLen > (MDNS_TXT_MAX_LEN - b - 1)) { + break; + } for(y=0; ytxt[b++] = d; @@ -1391,7 +1395,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz continue;//wrong host } } else if (!answer->ptr) { - sprintf(answer->host, "%s", name->host); + strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN); } else if (strcmp(answer->host, name->host) != 0) { continue;//wrong host } @@ -1402,7 +1406,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz continue;//wrong host } } else if (!answer->ptr) { - sprintf(answer->host, "%s", name->host); + strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN); } else if (strcmp(answer->host, name->host) != 0) { continue;//wrong host } @@ -1534,6 +1538,9 @@ esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname) if (!server) { return ESP_ERR_INVALID_ARG; } + if (strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + return ESP_ERR_INVALID_ARG; + } MDNS_MUTEX_LOCK(); free((char*)server->hostname); server->hostname = (char *)malloc(strlen(hostname)+1); @@ -1541,7 +1548,7 @@ esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname) MDNS_MUTEX_UNLOCK(); return ESP_ERR_NO_MEM; } - sprintf((char *)server->hostname, "%s", hostname); + strlcpy((char *)server->hostname, hostname, MDNS_NAME_BUF_LEN); MDNS_MUTEX_UNLOCK(); return ERR_OK; } @@ -1551,6 +1558,9 @@ esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance) if (!server) { return ESP_ERR_INVALID_ARG; } + if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { + return ESP_ERR_INVALID_ARG; + } MDNS_MUTEX_LOCK(); free((char*)server->instance); server->instance = (char *)malloc(strlen(instance)+1); @@ -1558,7 +1568,7 @@ esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance) MDNS_MUTEX_UNLOCK(); return ESP_ERR_NO_MEM; } - sprintf((char *)server->instance, "%s", instance); + strlcpy((char *)server->instance, instance, MDNS_NAME_BUF_LEN); MDNS_MUTEX_UNLOCK(); return ERR_OK; } @@ -1655,6 +1665,9 @@ esp_err_t mdns_service_instance_set(mdns_server_t * server, const char * service if (!server || !server->services || !service || !proto) { return ESP_ERR_INVALID_ARG; } + if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { + return ESP_ERR_INVALID_ARG; + } mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto); if (!s) { return ESP_ERR_NOT_FOUND; @@ -1741,10 +1754,10 @@ uint32_t mdns_query(mdns_server_t * server, const char * service, const char * p mdns_result_free(server); if (proto) { server->search.host[0] = 0; - snprintf(server->search.service, MDNS_NAME_MAX_LEN, "%s", service); - snprintf(server->search.proto, MDNS_NAME_MAX_LEN, "%s", proto); + strlcpy(server->search.service, service, MDNS_NAME_BUF_LEN); + strlcpy(server->search.proto, proto, MDNS_NAME_BUF_LEN); } else { - snprintf(server->search.host, MDNS_NAME_MAX_LEN, "%s", service); + strlcpy(server->search.host, service, MDNS_NAME_BUF_LEN); server->search.service[0] = 0; server->search.proto[0] = 0; qtype = MDNS_TYPE_A; From 5924dafd94928c4144581ac831c07c02786ba702 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 14 Mar 2017 21:39:44 +0800 Subject: [PATCH 005/289] examples: check return value of nvs_flash_init nvs_flash_init may return an error code in some cases, and applications should check this error code (or at least assert on it being ESP_OK, to make potential issues more immediately obvious). This change modifies all the examples which use NVS to check the error code. Most examples get a simple ESP_ERROR_CHECK assert, while NVS examples, OTA example, and NVS unit tests get a more verbose check which may be used in real applications. * Original commit: espressif/esp-idf@4813ab2d28081ca1f7682343e721485b1a53cd19 --- examples/protocols/mdns/main/mdns_example_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index d19fd1ae6..50b74e08c 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -178,7 +178,7 @@ static void mdns_task(void *pvParameters) void app_main() { - nvs_flash_init(); + ESP_ERROR_CHECK( nvs_flash_init() ); initialise_wifi(); xTaskCreate(&mdns_task, "mdns_task", 2048, NULL, 5, NULL); } From 1a1cf71a841991af5be49ab15b03155a0496ac68 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 22 Mar 2017 12:36:11 +0800 Subject: [PATCH 006/289] examples: Standardise naming of files, symbols, etc. in examples * Use "example" in all example function & variable names, ie use i2c_example_xxx instead of i2c_xxx for example functions. Closes #198 https://github.com/espressif/esp-idf/issues/198 * Mark example functions, etc. static * Replace uses of "test" & "demo" with "example" * Split the UART example into two * Rename "main" example files to end with "_main.c" for disambiguation * Original commit: espressif/esp-idf@821c70f5d7df7ffcfaaa013dba60cc9c38b43512 --- examples/protocols/mdns/main/mdns_example_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 50b74e08c..29e4e9b47 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -125,7 +125,7 @@ static void query_mdns_service(mdns_server_t * mdns, const char * service, const } } -static void mdns_task(void *pvParameters) +static void mdns_example_task(void *pvParameters) { mdns_server_t * mdns = NULL; while(1) { @@ -180,5 +180,5 @@ void app_main() { ESP_ERROR_CHECK( nvs_flash_init() ); initialise_wifi(); - xTaskCreate(&mdns_task, "mdns_task", 2048, NULL, 5, NULL); + xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL); } From 4acf639afc9e54dd7b70db05c4ceb4fef1b45cd6 Mon Sep 17 00:00:00 2001 From: negativekelvin Date: Mon, 13 Feb 2017 21:53:46 -0700 Subject: [PATCH 007/289] mdns: add simple dns-sd meta query support tabs to spaces match domain * Original commit: espressif/esp-idf@96e8a3c725095562d2725aaefa15adcfc5d78dd5 --- components/mdns/mdns.c | 68 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index d0fc69c4c..953ed64b9 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -46,6 +46,7 @@ #define MDNS_ANSWER_A 0x01 #define MDNS_ANSWER_AAAA 0x10 #define MDNS_ANSWER_NSEC 0x20 +#define MDNS_ANSWER_SDPTR 0x80 #define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on #define MDNS_SERVICE_STACK_DEPTH 4096 // Stack size for the service thread @@ -796,6 +797,52 @@ static uint16_t _mdns_append_ptr_record(uint8_t * packet, uint16_t * index, mdns return record_length; } +/** + * @brief appends DNS-SD PTR record for service to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server that is hosting the service + * @param service the service to add record for + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_sdptr_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, mdns_service_t * service) +{ + const char * str[3]; + const char * sd_str[4]; + uint16_t record_length = 0; + uint8_t part_length; + + sd_str[0] = (char*)"_services"; + sd_str[1] = (char*)"_dns-sd"; + sd_str[2] = (char*)"_udp"; + sd_str[3] = MDNS_DEFAULT_DOMAIN; + + str[0] = service->service; + str[1] = service->proto; + str[2] = MDNS_DEFAULT_DOMAIN; + + part_length = _mdns_append_fqdn(packet, index, sd_str, 4); + + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, MDNS_ANSWER_PTR_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + part_length = _mdns_append_fqdn(packet, index, str, 3); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} + /** * @brief appends TXT record for service to a packet, incrementing the index * @@ -1042,6 +1089,13 @@ static void _mdns_send_answers(mdns_server_t * server, mdns_answer_item_t * answ } answer_count += 1; } + + if (answers->answer & MDNS_ANSWER_SDPTR) { + if (!_mdns_append_sdptr_record(packet, &index, server, answers->service)) { + return; + } + answer_count += 1; + } } mdns_answer_item_t * a = answers; answers = answers->next; @@ -1274,6 +1328,20 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz } continue; } + + //is this a dns-sd service discovery meta query? + if (!strcmp(name->host, "_services") && !strcmp(name->service, "_dns-sd") && !strcmp(name->proto, "_udp") && !strcmp(name->domain, MDNS_DEFAULT_DOMAIN) && type == MDNS_TYPE_PTR) + { + //add answers for all services + mdns_srv_item_t * s = server->services; + while(s) { + if (s->service->service && s->service->proto) { + answers = _mdns_add_answer(answers, s->service, MDNS_ANSWER_SDPTR); + } + s = s->next; + } + continue; + } if (name->sub) { continue; From 75de31cea3a93cfd77cd08c911178ed9d77fc2ce Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 3 Apr 2017 16:45:59 +0300 Subject: [PATCH 008/289] implement fixes for issues found while fuzz testing * Original commit: espressif/esp-idf@99d39909c4f19c63909d663e927ac0a8933a3ed5 --- components/mdns/mdns.c | 65 +++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 953ed64b9..6467a5534 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -269,18 +269,18 @@ esp_err_t _mdns_server_deinit(mdns_server_t * server) */ static size_t _mdns_server_write(mdns_server_t * server, uint8_t * data, size_t len) { - struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pbt != NULL) { - uint8_t* dst = (uint8_t *)pbt->payload; - memcpy(dst, data, len); - err_t err = udp_sendto(server->pcb, pbt, &(server->pcb->remote_ip), server->pcb->remote_port); - pbuf_free(pbt); - if (err) { - return 0; - } - return len; - } - return 0; + struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pbt == NULL) { + return 0; + } + uint8_t* dst = (uint8_t *)pbt->payload; + memcpy(dst, data, len); + err_t err = udp_sendto(server->pcb, pbt, &(server->pcb->remote_ip), server->pcb->remote_port); + pbuf_free(pbt); + if (err) { + return 0; + } + return len; } /* @@ -391,11 +391,11 @@ static esp_err_t _mdns_server_add(mdns_server_t * server) */ static esp_err_t _mdns_server_remove(mdns_server_t * server) { + _mdns_servers[server->tcpip_if] = NULL; + //stop UDP _mdns_server_deinit(server); - _mdns_servers[server->tcpip_if] = NULL; - if (xQueueRemoveFromSet(server->queue, _mdns_queue_set) != pdPASS) { return ESP_FAIL; } @@ -1309,11 +1309,13 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz if (questions) { uint8_t qs = questions; - mdns_answer_item_t * answers = NULL; + mdns_answer_item_t * answer_items = NULL; while(qs--) { content = _mdns_parse_fqdn(data, content, name); if (!content) { + answers = 0; + additional = 0; break;//error } @@ -1323,7 +1325,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz if (!name->service[0] || !name->proto[0]) { if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA || type == MDNS_TYPE_ANY) {//send A + AAAA if (name->host[0] && server->hostname && server->hostname[0] && !strcmp(name->host, server->hostname)) { - answers = _mdns_add_answer(answers, NULL, MDNS_ANSWER_A); + answer_items = _mdns_add_answer(answer_items, NULL, MDNS_ANSWER_A); } } continue; @@ -1336,7 +1338,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz mdns_srv_item_t * s = server->services; while(s) { if (s->service->service && s->service->proto) { - answers = _mdns_add_answer(answers, s->service, MDNS_ANSWER_SDPTR); + answer_items = _mdns_add_answer(answer_items, s->service, MDNS_ANSWER_SDPTR); } s = s->next; } @@ -1354,7 +1356,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz } if (type == MDNS_TYPE_PTR) { - answers = _mdns_add_answer(answers, si->service, MDNS_ANSWER_ALL); + answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_ALL); } else if (type == MDNS_TYPE_TXT) { //match instance/host const char * host = (si->service->instance)?si->service->instance @@ -1363,7 +1365,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz if (!host || !host[0] || !name->host[0] || strcmp(name->host, host)) { continue; } - answers = _mdns_add_answer(answers, si->service, MDNS_ANSWER_TXT); + answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_TXT); } else if (type == MDNS_TYPE_SRV) { //match instance/host const char * host = (si->service->instance)?si->service->instance @@ -1372,16 +1374,16 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz if (!host || !host[0] || !name->host[0] || strcmp(name->host, host)) { continue; } - answers = _mdns_add_answer(answers, si->service, MDNS_ANSWER_SRV | MDNS_ANSWER_A); + answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_SRV | MDNS_ANSWER_A); } else if (type == MDNS_TYPE_ANY) {//send all //match host if (!name->host[0] || !server->hostname || !server->hostname[0] || strcmp(name->host, server->hostname)) { - answers = _mdns_add_answer(answers, si->service, MDNS_ANSWER_ALL); + answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_ALL); } } } - if (answers) { - _mdns_send_answers(server, answers); + if (answer_items) { + _mdns_send_answers(server, answer_items); } } @@ -1392,7 +1394,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz while(content < (data + len)) { content = _mdns_parse_fqdn(data, content, name); if (!content) { - break;//error + return;//error } uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); uint16_t data_len = _mdns_read_u16(content, MDNS_LEN_OFFSET); @@ -1400,6 +1402,10 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz content = data_ptr + data_len; + if(content > (data + len)){ + return; + } + if (type == MDNS_TYPE_PTR) { if (!_mdns_parse_fqdn(data, data_ptr, name)) { continue;//error @@ -1444,6 +1450,9 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz uint16_t i=0,b=0, y; while(i < data_len) { uint8_t partLen = data_ptr[i++]; + if((i+partLen) > data_len){ + break;//error + } //check if partLen will fit in the buffer if (partLen > (MDNS_TXT_MAX_LEN - b - 1)) { break; @@ -1611,12 +1620,11 @@ esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname) } MDNS_MUTEX_LOCK(); free((char*)server->hostname); - server->hostname = (char *)malloc(strlen(hostname)+1); + server->hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); if (!server->hostname) { MDNS_MUTEX_UNLOCK(); return ESP_ERR_NO_MEM; } - strlcpy((char *)server->hostname, hostname, MDNS_NAME_BUF_LEN); MDNS_MUTEX_UNLOCK(); return ERR_OK; } @@ -1631,12 +1639,11 @@ esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance) } MDNS_MUTEX_LOCK(); free((char*)server->instance); - server->instance = (char *)malloc(strlen(instance)+1); + server->instance = strndup(instance, MDNS_NAME_BUF_LEN - 1); if (!server->instance) { MDNS_MUTEX_UNLOCK(); return ESP_ERR_NO_MEM; } - strlcpy((char *)server->instance, instance, MDNS_NAME_BUF_LEN); MDNS_MUTEX_UNLOCK(); return ERR_OK; } @@ -1812,7 +1819,7 @@ esp_err_t mdns_service_remove_all(mdns_server_t * server) * MDNS QUERY * */ -uint32_t mdns_query(mdns_server_t * server, const char * service, const char * proto, uint32_t timeout) +size_t mdns_query(mdns_server_t * server, const char * service, const char * proto, uint32_t timeout) { if (!server || !service) { return 0; From 4a8582f5008e529d89bd5823abb19468e4de932d Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 3 Apr 2017 16:50:12 +0300 Subject: [PATCH 009/289] Add AFL fuzz test * Original commit: espressif/esp-idf@4c2622755d92efa1818d062d433725553437993c --- components/mdns/include/mdns.h | 4 + components/mdns/mdns.c | 56 ++++-- components/mdns/test_afl_fuzz_host/Makefile | 35 ++++ components/mdns/test_afl_fuzz_host/README.md | 58 ++++++ .../mdns/test_afl_fuzz_host/esp32_compat.h | 129 ++++++++++++++ .../mdns/test_afl_fuzz_host/in/test-14.bin | Bin 0 -> 568 bytes .../mdns/test_afl_fuzz_host/in/test-15.bin | Bin 0 -> 524 bytes .../mdns/test_afl_fuzz_host/in/test-16.bin | Bin 0 -> 254 bytes .../mdns/test_afl_fuzz_host/in/test-28.bin | Bin 0 -> 62 bytes .../mdns/test_afl_fuzz_host/in/test-29.bin | Bin 0 -> 39 bytes .../mdns/test_afl_fuzz_host/in/test-31.bin | Bin 0 -> 91 bytes .../mdns/test_afl_fuzz_host/in/test-53.bin | Bin 0 -> 140 bytes .../mdns/test_afl_fuzz_host/in/test-56.bin | Bin 0 -> 262 bytes .../mdns/test_afl_fuzz_host/in/test-63.bin | Bin 0 -> 147 bytes .../mdns/test_afl_fuzz_host/in/test-83.bin | Bin 0 -> 105 bytes .../mdns/test_afl_fuzz_host/in/test-88.bin | Bin 0 -> 48 bytes .../mdns/test_afl_fuzz_host/in/test-89.bin | Bin 0 -> 459 bytes .../mdns/test_afl_fuzz_host/in/test-95.bin | Bin 0 -> 286 bytes .../mdns/test_afl_fuzz_host/in/test-96.bin | Bin 0 -> 319 bytes .../mdns/test_afl_fuzz_host/input_packets.txt | 166 ++++++++++++++++++ components/mdns/test_afl_fuzz_host/test.c | 113 ++++++++++++ 21 files changed, 542 insertions(+), 19 deletions(-) create mode 100644 components/mdns/test_afl_fuzz_host/Makefile create mode 100644 components/mdns/test_afl_fuzz_host/README.md create mode 100644 components/mdns/test_afl_fuzz_host/esp32_compat.h create mode 100755 components/mdns/test_afl_fuzz_host/in/test-14.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-15.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-16.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-28.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-29.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-31.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-53.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-56.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-63.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-83.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-88.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-89.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-95.bin create mode 100755 components/mdns/test_afl_fuzz_host/in/test-96.bin create mode 100644 components/mdns/test_afl_fuzz_host/input_packets.txt create mode 100644 components/mdns/test_afl_fuzz_host/test.c diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 58e588e3e..c0855466a 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -18,7 +18,11 @@ extern "C" { #endif +#ifndef MDNS_TEST_MODE #include +#else +#include "esp32_compat.h" +#endif struct mdns_server_s; typedef struct mdns_server_s mdns_server_t; diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 6467a5534..39cc01829 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -14,6 +14,7 @@ #include "mdns.h" #include +#ifndef MDNS_TEST_MODE #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/queue.h" @@ -23,6 +24,7 @@ #include "lwip/igmp.h" #include "lwip/udp.h" #include "esp_wifi.h" +#endif #define MDNS_FLAGS_AUTHORITATIVE 0x8400 @@ -162,6 +164,9 @@ static const char * MDNS_DEFAULT_DOMAIN = "local"; static const char * MDNS_SUB_STR = "_sub"; static mdns_server_t * _mdns_servers[TCPIP_ADAPTER_IF_MAX] = {0,0,0}; + +#ifndef MDNS_TEST_MODE + static TaskHandle_t _mdns_service_task_handle = NULL; static QueueSetHandle_t _mdns_queue_set = NULL; @@ -257,6 +262,7 @@ esp_err_t _mdns_server_deinit(mdns_server_t * server) } return ESP_OK; } +#endif /** * @brief send packet over UDP @@ -269,25 +275,28 @@ esp_err_t _mdns_server_deinit(mdns_server_t * server) */ static size_t _mdns_server_write(mdns_server_t * server, uint8_t * data, size_t len) { - struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pbt == NULL) { - return 0; - } - uint8_t* dst = (uint8_t *)pbt->payload; - memcpy(dst, data, len); - err_t err = udp_sendto(server->pcb, pbt, &(server->pcb->remote_ip), server->pcb->remote_port); - pbuf_free(pbt); - if (err) { - return 0; - } - return len; +#ifndef MDNS_TEST_MODE + struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pbt == NULL) { + return 0; + } + uint8_t* dst = (uint8_t *)pbt->payload; + memcpy(dst, data, len); + err_t err = udp_sendto(server->pcb, pbt, &(server->pcb->remote_ip), server->pcb->remote_port); + pbuf_free(pbt); + if (err) { + return 0; + } +#endif + return len; } /* * MDNS Servers * */ -static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len); +#ifndef MDNS_TEST_MODE +void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len); /** * @brief the main MDNS service task. Packets are received and parsed here @@ -305,7 +314,7 @@ static void _mdns_service_task(void *pvParameters) mdns_server_t * server = _mdns_servers[i]; if (server && server->queue == queue) { MDNS_MUTEX_LOCK(); - _mdns_parse_packet(server, (uint8_t*)pb->payload, pb->len); + mdns_parse_packet(server, (uint8_t*)pb->payload, pb->len); MDNS_MUTEX_UNLOCK(); break; } @@ -314,6 +323,7 @@ static void _mdns_service_task(void *pvParameters) } } } +#endif /** * @brief get the server assigned to particular interface @@ -342,6 +352,7 @@ static mdns_server_t * _mdns_server_get(tcpip_adapter_if_t tcpip_if) */ static esp_err_t _mdns_server_add(mdns_server_t * server) { +#ifndef MDNS_TEST_MODE if (!_mdns_service_semaphore) { _mdns_service_semaphore = xSemaphoreCreateMutex(); if (!_mdns_service_semaphore) { @@ -374,7 +385,7 @@ static esp_err_t _mdns_server_add(mdns_server_t * server) if (err) { return err; } - +#endif _mdns_servers[server->tcpip_if] = server; return ESP_OK; @@ -392,7 +403,7 @@ static esp_err_t _mdns_server_add(mdns_server_t * server) static esp_err_t _mdns_server_remove(mdns_server_t * server) { _mdns_servers[server->tcpip_if] = NULL; - +#ifndef MDNS_TEST_MODE //stop UDP _mdns_server_deinit(server); @@ -417,7 +428,7 @@ static esp_err_t _mdns_server_remove(mdns_server_t * server) } MDNS_SERVICE_UNLOCK(); } - +#endif return ESP_OK; } @@ -1294,7 +1305,7 @@ static inline uint16_t _mdns_read_u16(const uint8_t * packet, uint16_t index) * @param data byte array holding the packet data * @param len length of the byte array */ -static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len) +void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len) { static mdns_name_t n; static mdns_result_temp_t a; @@ -1401,7 +1412,6 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz const uint8_t * data_ptr = content + MDNS_DATA_OFFSET; content = data_ptr + data_len; - if(content > (data + len)){ return; } @@ -1410,18 +1420,22 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz if (!_mdns_parse_fqdn(data, data_ptr, name)) { continue;//error } +#ifndef MDNS_TEST_MODE if (server->search.host[0] || (strcmp(name->service, server->search.service) != 0) || (strcmp(name->proto, server->search.proto) != 0)) { continue;//not searching for service or wrong service/proto } +#endif strlcpy(answer->instance, name->host, MDNS_NAME_BUF_LEN); } else if (type == MDNS_TYPE_SRV) { +#ifndef MDNS_TEST_MODE if (server->search.host[0] || (strcmp(name->service, server->search.service) != 0) || (strcmp(name->proto, server->search.proto) != 0)) { continue;//not searching for service or wrong service/proto } +#endif if (answer->instance[0]) { if (strcmp(answer->instance, name->host) != 0) { continue;//instance name is not the same as the one in the PTR record @@ -1468,9 +1482,11 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz answer->txt[b] = 0; } else if (type == MDNS_TYPE_AAAA) { if (server->search.host[0]) { +#ifndef MDNS_TEST_MODE if (strcmp(name->host, server->search.host) != 0) { continue;//wrong host } +#endif } else if (!answer->ptr) { strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN); } else if (strcmp(answer->host, name->host) != 0) { @@ -1479,9 +1495,11 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz memcpy(answer->addrv6, data_ptr, sizeof(ip6_addr_t)); } else if (type == MDNS_TYPE_A) { if (server->search.host[0]) { +#ifndef MDNS_TEST_MODE if (strcmp(name->host, server->search.host) != 0) { continue;//wrong host } +#endif } else if (!answer->ptr) { strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN); } else if (strcmp(answer->host, name->host) != 0) { diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile new file mode 100644 index 000000000..65a318ef2 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -0,0 +1,35 @@ +TEST_NAME=test +FUZZ=afl-fuzz +CC=afl-clang-fast +CPP=$(CC) +LD=$(CC) +OBJECTS=mdns.o test.o +CFLAGS=-DMDNS_TEST_MODE -I. -I../include + +OS := $(shell uname) +ifeq ($(OS),Darwin) + LDLIBS= +else + LDLIBS=-lbsd + CFLAGS+=-DUSE_BSD_STRING +endif + +all: $(TEST_NAME) + +%.o: %.c + @echo "[CC] $<" + @$(CC) $(CFLAGS) -c $< -o $@ + +mdns.o: ../mdns.c + @echo "[CC] $<" + @$(CC) $(CFLAGS) -c $< -o $@ + +$(TEST_NAME): $(OBJECTS) + @echo "[LD] $@" + @$(LD) $(LDLIBS) $(OBJECTS) -o $@ + +fuzz: $(TEST_NAME) + @$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) + +clean: + @rm -rf *.o *.SYM $(TEST_NAME) out diff --git a/components/mdns/test_afl_fuzz_host/README.md b/components/mdns/test_afl_fuzz_host/README.md new file mode 100644 index 000000000..7d78bab55 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/README.md @@ -0,0 +1,58 @@ +## Introduction +This test uses [american fuzzy lop](http://lcamtuf.coredump.cx/afl/) to mangle real mdns packets and look for exceptions caused by the parser. + +A few actuall packets are collected and exported as bins in the ```in``` folder, which is then passed as input to AFL when testing. The setup procedure for the test includes all possible services and scenarios that could be used with the given input packets. Output of the parser before fuzzing can be found in [input_packets.txt](input_packets.txt) + +## Installing AFL +To run the test yourself, you need to dounload the [latest afl archive](http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz) and extract it to a folder on your computer. + +The rest of the document will refer to that folder as ```PATH_TO_AFL```. + +### Preparation +- On Mac, you will need to insall the latest Xcode and llvm support from [Homebrew](https://brew.sh) + + ```bash + /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + brew install --with-clang --with-lld --HEAD llvm + export PATH="/usr/local/opt/llvm/bin:$PATH" + ``` + +- On Ubuntu you need the following packages: + + ```bash + sudo apt-get install make clang llvm libbsd-dev + ``` + +### Compile AFL +Compiling AFL is as easy as running make: + +```bash +cd [PATH_TO_AFL] +make +cd llvm_mode/ +make +``` + +After successful compilation, you can export the following variables to your shell (you can also add them to your profile if you want to use afl in other projects) + +```bash +export AFL_PATH=[PATH_TO_AFL] +export PATH="$AFL_PATH:$PATH" +``` + +## Running the test +Apple has a crash reporting service that could interfere with AFLs normal operation. To turn that off, run the following command: + +```bash +launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist +sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist +``` + +Ubuntu has a similar service. To turn that off, run as root: + +```bash +echo core >/proc/sys/kernel/core_pattern +``` + +After going through all of the requirements above, you can ```cd``` into this test's folder and simply run ```make fuzz```. + diff --git a/components/mdns/test_afl_fuzz_host/esp32_compat.h b/components/mdns/test_afl_fuzz_host/esp32_compat.h new file mode 100644 index 000000000..d6a913a3c --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/esp32_compat.h @@ -0,0 +1,129 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP32_COMPAT_H_ +#define _ESP32_COMPAT_H_ + +#ifdef MDNS_TEST_MODE + +#ifdef USE_BSD_STRING +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#define ERR_OK 0 +#define ESP_OK 0 +#define ESP_FAIL -1 + +#define ESP_ERR_NO_MEM 0x101 +#define ESP_ERR_INVALID_ARG 0x102 +#define ESP_ERR_INVALID_STATE 0x103 +#define ESP_ERR_INVALID_SIZE 0x104 +#define ESP_ERR_NOT_FOUND 0x105 +#define ESP_ERR_NOT_SUPPORTED 0x106 +#define ESP_ERR_TIMEOUT 0x107 +#define ESP_ERR_INVALID_RESPONSE 0x108 +#define ESP_ERR_INVALID_CRC 0x109 + +#define pdTRUE true +#define pdFALSE false + +#define portMAX_DELAY 0xFFFFFFFF +#define portTICK_PERIOD_MS 1 + +#define xSemaphoreTake(s,d) +#define xSemaphoreGive(s) +#define xSemaphoreCreateMutex() malloc(1) +#define vSemaphoreDelete(s) free(s) +#define xQueueCreate(n,s) malloc((n)*(s)) +#define vQueueDelete(q) free(q) +#define xQueueReceive(q, d, t) (ESP_OK) +#define vTaskDelay(m) usleep((m)*1000) +#define pbuf_free(p) free(p) + +#define tcpip_adapter_get_ip_info(i,d) +#define tcpip_adapter_get_ip6_linklocal(i,d) (ESP_OK) +#define tcpip_adapter_get_hostname(i, n) *(n) = "esp32-0123456789AB" + +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((uint32_t)((d) & 0xff) << 24) | \ + ((uint32_t)((c) & 0xff) << 16) | \ + ((uint32_t)((b) & 0xff) << 8) | \ + (uint32_t)((a) & 0xff) + +typedef uint32_t esp_err_t; + +typedef void * xSemaphoreHandle; +typedef void * xQueueHandle; + +typedef enum { + TCPIP_ADAPTER_IF_STA = 0, /**< ESP32 station interface */ + TCPIP_ADAPTER_IF_AP, /**< ESP32 soft-AP interface */ + TCPIP_ADAPTER_IF_ETH, /**< ESP32 ethernet interface */ + TCPIP_ADAPTER_IF_MAX +} tcpip_adapter_if_t; + +typedef enum { + WIFI_MODE_NULL = 0, /**< null mode */ + WIFI_MODE_STA, /**< WiFi station mode */ + WIFI_MODE_AP, /**< WiFi soft-AP mode */ + WIFI_MODE_APSTA, /**< WiFi station + soft-AP mode */ + WIFI_MODE_MAX +} wifi_mode_t; + +struct udp_pcb { + uint8_t dummy; +}; + +struct ip4_addr { + uint32_t addr; +}; +typedef struct ip4_addr ip4_addr_t; + +struct ip6_addr { + uint32_t addr[4]; +}; +typedef struct ip6_addr ip6_addr_t; + +typedef struct { + ip4_addr_t ip; + ip4_addr_t netmask; + ip4_addr_t gw; +} tcpip_adapter_ip_info_t; + +inline esp_err_t esp_wifi_get_mode(wifi_mode_t * mode) +{ + *mode = WIFI_MODE_APSTA; + return ESP_OK; +} + +inline uint32_t xTaskGetTickCount() +{ + struct timeval tv; + struct timezone tz; + if (gettimeofday(&tv, &tz) == 0) { + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + } + return 0; +} + +#endif //MDNS_TEST_MODE + +#endif //_ESP32_COMPAT_H_ diff --git a/components/mdns/test_afl_fuzz_host/in/test-14.bin b/components/mdns/test_afl_fuzz_host/in/test-14.bin new file mode 100755 index 0000000000000000000000000000000000000000..b9d059d8202682602e7232a8505c495a3047e3a4 GIT binary patch literal 568 zcmZPo0U-u<5XBLnm|0YiUsS>pUy@wFnvHzlzovACotH8B^WmnFUc=31Wk;+)jf0^Ne5{EAAJ z_|lYu15zL-s#;nY7&@A}np(Iy8aj9sWfqs@s~0OcW)=nH7nLZuRumMa78f5#W)NUt zl)x#?1CkbnONV6UrYblm78IA}q#gjv9pC|3#=yYwfPv|tG78TL5>^ZhoX;7=MLYr& zd=iUOi@Z`x6r2ML4UA0l$`7a>FobBwt;F!aazaX$AJ|7o$-V>k;Y!q$O$~I7O>_+n Obj=O)3>C2Z?mhsxkDR6e literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/in/test-15.bin b/components/mdns/test_afl_fuzz_host/in/test-15.bin new file mode 100755 index 0000000000000000000000000000000000000000..3250de543150ac9d872a46e7d2d03fe6281c9170 GIT binary patch literal 524 zcmZQzXklPrU|x` zoc!d(90mq~21W)3!6^*OmX;^_I@(%V=o%R6I-2Xcn(A7(={g$f6rl=R=sFwe8o7dm zjgVABgxz$C68&;*EAvZ>bc>5KQ*??Foil6=b&8xbjBHJfbczy#OKc55iX3eXb&4z9 za%>GMEF2A-b&4w;18fZqO?8SZ!-{Rq_004vbc&0T%WTcfEDQ|v40V#Sf>Ugbj8!cy z3=AF3T}>_A91R_Cd6hN3C^5g_fF9g;ZJZ?)C1t5a#kPhl$r-jrY{_}H20DgpsUYW= za1@u>rX}VSr?RIc+LjcRrg9V)*_xOb8W^w^7uy<|aTJt8J0) zA}I73Di{<%(I?y?4)IX2F4P=dXw)4rKET7E4^k^Qg@N+`4+AR$Lj!}ufmcX^ub_ee DNCA-n literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/in/test-16.bin b/components/mdns/test_afl_fuzz_host/in/test-16.bin new file mode 100755 index 0000000000000000000000000000000000000000..19915d89c7c7b0e3698226213282eea301a7c77d GIT binary patch literal 254 zcmZQzXklPrU|$xT)|~w0 z#2f|&fd)nf2Ei!|E0&ih`a0U08|a!F>pDB>I+^G?Tk1L)>lC31JLwvj=(?JNgpH6? zLxe4KiW2>DZS#^ci*-v09iNz1kYAQsRFYi45?_*Bz?zev MoS4JFpxD3&0KJP4#sB~S literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/in/test-29.bin b/components/mdns/test_afl_fuzz_host/in/test-29.bin new file mode 100755 index 0000000000000000000000000000000000000000..837737b32e12e3f33ff3f1c3b59f6ff351b05fba GIT binary patch literal 39 pcmZPo0VWW^z`&WCnU|SXlvz^6nviw-R{RqNlAgCdB-P{AMsavS4bPLRQAMVTd42aFCZWsrf&3jAvT z$ulsB=!N{>apW)Ofu#(LP&t+ZEB*-_C}7YB@dc+aa2_aNU}a!vU~o9F6e7q_!N74~ LDFcfG0|N&D#Un?@ literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/in/test-63.bin b/components/mdns/test_afl_fuzz_host/in/test-63.bin new file mode 100755 index 0000000000000000000000000000000000000000..883d444ba269c8938aa87f3ba8da53a1305f9763 GIT binary patch literal 147 zcmZPo0VW0}5XBvzm{yQqmReMjT)+}vl3c)=lb@WJ!@$79z$hM^pO#sfsOwpln3rFc zSgh-tnCz6FpM5}osCPfW=y z&W3Of@PLFE7&r|XWTk@h(=sa)6+Ful^YY6QA2rM@R`5+scFNDsKEMN0$luB!ChSp^ zSzMA2Q=pKWnU{%B!D+}KAqr8UUaSz3nVYKMoLEp?nv;5f=YR%r)@i^L@?F4T9b5$- G>ofo+LQshS literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/in/test-96.bin b/components/mdns/test_afl_fuzz_host/in/test-96.bin new file mode 100755 index 0000000000000000000000000000000000000000..fabf8b79304ed9e0a90a73da369aa4566907923d GIT binary patch literal 319 zcmZQzXklPrU|?ckU|<&YD9S7@$yYB{2+7P%Rd7x$C@#%O<%v&8Ez3+!)y>RH%V&u% zNiJZ`$xlwqVPFtoU}RtroWdY3mYbiFnqv#n1=VDxV`yl`7N3}sS)6@9pMeLeQUbdb z2VxH7GYB+5Ov_U%t}M1KPxN)PH8-#_H@0$ivT`!9a<;T`GS*2<33IbGs4z4zFmOxB zHnN5DEx>Yqwov;)3PWv8P16#Sk}Q&R6U~g1bWKf640SCn%uRI7Qd5#l4NOv#j13YG yad4{?UaRc);X9K7&3;q2Lq-&I9=jtPBhd3=RM_)K}dA literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/input_packets.txt b/components/mdns/test_afl_fuzz_host/input_packets.txt new file mode 100644 index 000000000..6156ffa23 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/input_packets.txt @@ -0,0 +1,166 @@ +Input: in/test-14.bin +Packet Length: 568 +Questions: 18 + Q: _airport._tcp.local. PTR IN + Q: _http._tcp.local. PTR IN + Q: _printer._tcp.local. PTR IN + Q: _sub._http._tcp.local. PTR IN + Q: _airplay._tcp.local. PTR IN + Q: _raop._tcp.local. PTR IN + Q: _uscan._tcp.local. PTR IN + Q: _uscans._tcp.local. PTR IN + Q: _ippusb._tcp.local. PTR IN + Q: _scanner._tcp.local. PTR IN + Q: _ipp._tcp.local. PTR IN + Q: _ipps._tcp.local. PTR IN + Q: _pdl-datastream._tcp.local. PTR IN + Q: _ptp._tcp.local. PTR IN + Q: _sleep-proxy._udp.local. PTR IN + Q: 9801A7E58FA1@Hristo's AirPort Express._raop._tcp.local. TXT IN + Q: Hristo's AirPort Express._airport._tcp.local. TXT IN + Q: Hristo's Time Capsule._airport._tcp.local. TXT IN +Answers: 7 + 0 + A: _airport._tcp.local. PTR IN 2272 [2] Hristo's AirPort Express._airport._tcp.local. + A: _airport._tcp.local. PTR IN 2272 [2] Hristo's Time Capsule._airport._tcp.local. + A: _http._tcp.local. PTR IN 2535 [23] HP LaserJet CP1025nw._http._tcp.local. + A: _printer._tcp.local. PTR IN 2535 [23] HP LaserJet CP1025nw._printer._tcp.local. + A: _ipp._tcp.local. PTR IN 2535 [23] HP LaserJet CP1025nw._ipp._tcp.local. + A: _pdl-datastream._tcp.local. PTR IN 2535 [23] HP LaserJet CP1025nw._pdl-datastream._tcp.local. + A: _sleep-proxy._udp.local. PTR IN 2535 [38] 50-34-10-70.1 Hristo's Time Capsule._sleep-proxy._udp.local. + +Input: in/test-15.bin +Packet Length: 524 +Answers: 3 + 3 + A: Hristo's AirPort Express._airport._tcp.local. TXT IN FLUSH 4500 [166] waMA=98-01-A7-E5-8F-A1,raMA=98-01-A7-E8-C2-2E,raM2=98-01-A7-E8-C2-2F,raNm=your-ssid,raCh=1,rCh2=52,raSt=0,raNA=1,syFl=0x8A0C,syAP=115,syVs=7.6.8,srcv=76800.1,bjSd=23 + A: 9801A7E58FA1@Hristo's AirPort Express._raop._tcp.local. TXT IN FLUSH 4500 [134] txtvers=1; ch=2; cn=0,1; et=0,4; sv=false; da=true; sr=44100; ss=16; pw=false; vn=65537; tp=TCP,UDP; vs=105.1; am=AirPort10,115; fv=76800.1; sf=0x1 + A: _raop._tcp.local. PTR IN 4500 [2] 9801A7E58FA1@Hristo's AirPort Express._raop._tcp.local. + A: 9801A7E58FA1@Hristo's AirPort Express._raop._tcp.local. SRV IN FLUSH 120 [32] 5000 Hristos-AirPort-Express.local. + A: Hristo's AirPort Express.local. NSEC IN FLUSH 4500 [9] Hristo's AirPort Express._airport._tcp.local. 00 05 00 00 80 00 40 + A: 9801A7E58FA1@Hristo's AirPort Express.local. NSEC IN FLUSH 4500 [9] 9801A7E58FA1@Hristo's AirPort Express._raop._tcp.local. 00 05 00 00 80 00 40 + +Input: in/test-16.bin +Packet Length: 254 +Answers: 1 + 1 + A: Hristo's Time Capsule._airport._tcp.local. TXT IN FLUSH 4500 [168] waMA=70-73-CB-B4-C9-B3,raMA=70-73-CB-BB-04-E7,raM2=70-73-CB-BB-04-E8,raNm=nbis-test,raCh=11,rCh2=132,raSt=0,raNA=0,syFl=0x820C,syAP=116,syVs=7.6.8,srcv=76800.1,bjSd=30 + A: Hristo's Time Capsule.local. NSEC IN FLUSH 4500 [9] Hristo's Time Capsule._airport._tcp.local. 00 05 00 00 80 00 40 + +Input: in/test-28.bin +Packet Length: 62 +Questions: 1 + Q: Hristo's Time Capsule._afpovertcp._tcp.local. SRV IN FLUSH + +Input: in/test-29.bin +Packet Length: 39 +Questions: 2 + Q: minifritz.local. A IN FLUSH + Q: minifritz.local. AAAA IN FLUSH + +Input: in/test-31.bin +Packet Length: 91 +Answers: 2 + 1 + A: minifritz.local. AAAA IN FLUSH 120 [16] fe80:0000:0000:0000:142e:54ff:b8c4:fd09 + A: minifritz.local. A IN FLUSH 120 [4] 192.168.254.16 + A: minifritz.local. NSEC IN FLUSH 120 [8] minifritz...local. 00 04 40 00 00 08 + +Input: in/test-53.bin +Packet Length: 140 +Questions: 2 + Q: _smb._tcp.local. PTR IN + Q: Sofiya-Ivanovas-MacBook.local. A IN +Answers: 2 + 0 + A: _smb._tcp.local. PTR IN 3061 [29] Sofiya Ivanova’s MacBook._smb._tcp.local. + A: _smb._tcp.local. PTR IN 3062 [24] Hristo's Time Capsule._smb._tcp.local. + +Input: in/test-56.bin +Packet Length: 262 +Answers: 2 + 6 + A: Hristo’s Mac mini._device-info._tcp.local. TXT IN 4500 [28] model=Macmini6,2; osxvers=16 + A: _smb._tcp.local. PTR IN 4500 [22] Hristo’s Mac mini._smb._tcp.local. + A: Hristo’s Mac mini._smb._tcp.local. TXT IN FLUSH 4500 [1] + A: Hristo’s Mac mini._smb._tcp.local. SRV IN FLUSH 120 [18] 445 minifritz.local. + A: minifritz.local. AAAA IN FLUSH 120 [16] fe80:0000:0000:0000:142e:54ff:b8c4:fd09 + A: minifritz.local. A IN FLUSH 120 [4] 192.168.254.16 + A: Hristo’s Mac mini.local. NSEC IN FLUSH 4500 [9] Hristo’s Mac mini._smb._tcp.local. 00 05 00 00 80 00 40 + A: minifritz.local. NSEC IN FLUSH 120 [8] minifritz...local. 00 04 40 00 00 08 + +Input: in/test-63.bin +Packet Length: 147 +Questions: 2 + Q: _afpovertcp._tcp.local. PTR IN + Q: Sofiya-Ivanovas-MacBook.local. A IN +Answers: 2 + 0 + A: _afpovertcp._tcp.local. PTR IN 2881 [29] Sofiya Ivanova’s MacBook._afpovertcp._tcp.local. + A: _afpovertcp._tcp.local. PTR IN 2881 [24] Hristo's Time Capsule._afpovertcp._tcp.local. + +Input: in/test-66.bin +Packet Length: 269 +Answers: 2 + 6 + A: Hristo’s Mac mini._device-info._tcp.local. TXT IN 4500 [28] model=Macmini6,2; osxvers=16 + A: _afpovertcp._tcp.local. PTR IN 4500 [22] Hristo’s Mac mini._afpovertcp._tcp.local. + A: Hristo’s Mac mini._afpovertcp._tcp.local. TXT IN FLUSH 4500 [1] + A: Hristo’s Mac mini._afpovertcp._tcp.local. SRV IN FLUSH 120 [18] 548 minifritz.local. + A: minifritz.local. AAAA IN FLUSH 120 [16] fe80:0000:0000:0000:142e:54ff:b8c4:fd09 + A: minifritz.local. A IN FLUSH 120 [4] 192.168.254.16 + A: Hristo’s Mac mini.local. NSEC IN FLUSH 4500 [9] Hristo’s Mac mini._afpovertcp._tcp.local. 00 05 00 00 80 00 40 + A: minifritz.local. NSEC IN FLUSH 120 [8] minifritz...local. 00 04 40 00 00 08 + +Input: in/test-83.bin +Packet Length: 105 +Answers: 1 + 2 + A: Sofiya-Ivanovas-MacBook.local. A IN FLUSH 120 [4] 192.168.254.20 + A: Sofiya-Ivanovas-MacBook.local. AAAA IN FLUSH 120 [16] fe80:0000:0000:0000:021c:b3ff:feb2:72a3 + A: Sofiya-Ivanovas-MacBook.local. NSEC IN FLUSH 120 [8] Sofiya-Ivanovas-MacBook...local. 00 04 40 00 00 08 + +Input: in/test-88.bin +Packet Length: 48 +Questions: 2 + Q: _rfb._tcp.local. PTR IN + Q: _airport._tcp.local. PTR IN + +Input: in/test-89.bin +Packet Length: 459 +Answers: 2 + 7 + A: _airport._tcp.local. PTR IN 4500 [24] Hristo's Time Capsule._airport._tcp.local. + A: Hristo's Time Capsule._device-info._tcp.local. TXT IN 4500 [23] model=TimeCapsule6,116 + A: Hristos-Time-Capsule.local. A IN FLUSH 120 [4] 192.168.254.49 + A: Hristo's Time Capsule._airport._tcp.local. TXT IN FLUSH 4500 [168] waMA=70-73-CB-B4-C9-B3,raMA=70-73-CB-BB-04-E7,raM2=70-73-CB-BB-04-E8,raNm=nbis-test,raCh=11,rCh2=132,raSt=0,raNA=0,syFl=0x820C,syAP=116,syVs=7.6.8,srcv=76800.1,bjSd=30 + A: Hristos-Time-Capsule.local. AAAA IN FLUSH 120 [16] fe80:0000:0000:0000:7273:cbff:feb4:c9b3 + A: Hristo's Time Capsule._airport._tcp.local. SRV IN FLUSH 120 [8] 5009 Hristos-Time-Capsule.local. + A: Hristos-Time-Capsule.local. A IN FLUSH 120 [4] 169.254.23.40 + A: Hristos-Time-Capsule.local. NSEC IN FLUSH 120 [8] Hristos-Time-Capsule...local. 00 04 40 00 00 08 + A: Hristo's Time Capsule.local. NSEC IN FLUSH 4500 [9] Hristo's Time Capsule._airport._tcp.local. 00 05 00 00 80 00 40 + +Input: in/test-91.bin +Packet Length: 279 +Answers: 2 + 6 + A: Sofiya Ivanova’s MacBook._device-info._tcp.local. TXT IN 4500 [17] model=Macmini2,1 + A: _rfb._tcp.local. PTR IN 4500 [29] Sofiya Ivanova’s MacBook._rfb._tcp.local. + A: Sofiya Ivanova’s MacBook._rfb._tcp.local. TXT IN FLUSH 4500 [1] + A: Sofiya Ivanova’s MacBook._rfb._tcp.local. SRV IN FLUSH 120 [32] 5900 Sofiya-Ivanovas-MacBook.local. + A: Sofiya-Ivanovas-MacBook.local. AAAA IN FLUSH 120 [16] fe80:0000:0000:0000:021c:b3ff:feb2:72a3 + A: Sofiya-Ivanovas-MacBook.local. A IN FLUSH 120 [4] 192.168.254.20 + A: Sofiya Ivanova’s MacBook.local. NSEC IN FLUSH 4500 [9] Sofiya Ivanova’s MacBook._rfb._tcp.local. 00 05 00 00 80 00 40 + A: Sofiya-Ivanovas-MacBook.local. NSEC IN FLUSH 120 [8] Sofiya-Ivanovas-MacBook...local. 00 04 40 00 00 08 + +Input: in/test-95.bin +Packet Length: 286 +Questions: 3 + Q: _afpovertcp._tcp.local. PTR IN + Q: _smb._tcp.local. PTR IN + Q: _adisk._tcp.local. PTR IN +Answers: 6 + 0 + A: _afpovertcp._tcp.local. PTR IN 2353 [29] Sofiya Ivanova’s MacBook._afpovertcp._tcp.local. + A: _afpovertcp._tcp.local. PTR IN 3973 [22] Hristo’s Mac mini._afpovertcp._tcp.local. + A: _afpovertcp._tcp.local. PTR IN 2353 [24] Hristo's Time Capsule._afpovertcp._tcp.local. + A: _smb._tcp.local. PTR IN 2353 [29] Sofiya Ivanova’s MacBook._smb._tcp.local. + A: _smb._tcp.local. PTR IN 3792 [22] Hristo’s Mac mini._smb._tcp.local. + A: _smb._tcp.local. PTR IN 2353 [24] Hristo's Time Capsule._smb._tcp.local. + +Input: in/test-96.bin +Packet Length: 319 +Answers: 2 + 3 + A: Hristo's Time Capsule._device-info._tcp.local. TXT IN 4500 [23] model=TimeCapsule6,116 + A: _adisk._tcp.local. PTR IN 4500 [24] Hristo's Time Capsule._adisk._tcp.local. + A: Hristo's Time Capsule._adisk._tcp.local. TXT IN FLUSH 4500 [110] sys=waMA=70:73:CB:B4:C9:B3,adVF=0x1000; dk2=adVF=0x1083,adVN=Capsule,adVU=55fabb8b-a63b-5441-9874-6edb504eb30a + A: Hristo's Time Capsule._adisk._tcp.local. SRV IN FLUSH 120 [29] 9 Hristos-Time-Capsule.local. + A: Hristo's Time Capsule.local. NSEC IN FLUSH 4500 [9] Hristo's Time Capsule._adisk._tcp.local. 00 05 00 00 80 00 40 diff --git a/components/mdns/test_afl_fuzz_host/test.c b/components/mdns/test_afl_fuzz_host/test.c new file mode 100644 index 000000000..be06ac0bf --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/test.c @@ -0,0 +1,113 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifdef MDNS_TEST_MODE + +#include +#include +#include +#include +#include + +#include "mdns.h" + +void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len); + +int main(int argc, char** argv) +{ + const char * mdns_hostname = "minifritz"; + const char * mdns_instance = "Hristo's Time Capsule"; + const char * arduTxtData[4] = { + "board=esp32", + "tcp_check=no", + "ssh_upload=no", + "auth_upload=no" + }; + const uint8_t mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x32}; + + mdns_server_t * mdns = NULL; + uint8_t buf[1460]; + char winstance[21+strlen(mdns_hostname)]; + + sprintf(winstance, "%s [%02x:%02x:%02x:%02x:%02x:%02x]", mdns_hostname, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + if (mdns_init(TCPIP_ADAPTER_IF_ETH, &mdns)) { + abort(); + } + + if (mdns_set_hostname(mdns, mdns_hostname)) { + abort(); + } + + if (mdns_set_instance(mdns, mdns_instance)) { + abort(); + } + + if (mdns_service_add(mdns, "_workstation", "_tcp", 9)) { + abort(); + } + + if (mdns_service_instance_set(mdns, "_workstation", "_tcp", winstance)) { + abort(); + } + + if (mdns_service_add(mdns, "_arduino", "_tcp", 3232)) { + abort(); + } + + if (mdns_service_txt_set(mdns, "_arduino", "_tcp", 4, arduTxtData)) { + abort(); + } + + if (mdns_service_add(mdns, "_http", "_tcp", 80)) { + abort(); + } + + if (mdns_service_instance_set(mdns, "_http", "_tcp", "ESP WebServer")) { + abort(); + } + + if ( + mdns_service_add(mdns, "_afpovertcp", "_tcp", 548) + || mdns_service_add(mdns, "_rfb", "_tcp", 885) + || mdns_service_add(mdns, "_smb", "_tcp", 885) + || mdns_service_add(mdns, "_adisk", "_tcp", 885) + || mdns_service_add(mdns, "_airport", "_tcp", 885) + || mdns_service_add(mdns, "_printer", "_tcp", 885) + || mdns_service_add(mdns, "_airplay", "_tcp", 885) + || mdns_service_add(mdns, "_raop", "_tcp", 885) + || mdns_service_add(mdns, "_uscan", "_tcp", 885) + || mdns_service_add(mdns, "_uscans", "_tcp", 885) + || mdns_service_add(mdns, "_ippusb", "_tcp", 885) + || mdns_service_add(mdns, "_scanner", "_tcp", 885) + || mdns_service_add(mdns, "_ipp", "_tcp", 885) + || mdns_service_add(mdns, "_ipps", "_tcp", 885) + || mdns_service_add(mdns, "_pdl-datastream", "_tcp", 885) + || mdns_service_add(mdns, "_ptp", "_tcp", 885) + || mdns_service_add(mdns, "_sleep-proxy", "_udp", 885)) + { + abort(); + } + + while (__AFL_LOOP(1000)) { + memset(buf, 0, 1460); + size_t len = read(0, buf, 1460); + mdns_query(mdns, "_afpovertcp", "_tcp", 0); + mdns_parse_packet(mdns, buf, len); + mdns_query_end(mdns); + } + return 0; +} + +#endif From b36748436187dcb95c35faf383b6865aac4a2575 Mon Sep 17 00:00:00 2001 From: Eugene Zagidullin Date: Tue, 27 Jun 2017 00:35:16 +0300 Subject: [PATCH 010/289] Use LwIP IPC for low-level API calls * Original commit: espressif/esp-idf@713964fe9e98b4fa34145c497b7ab638dc57614c --- components/mdns/mdns.c | 298 +++++++++++++++++++++++++---------------- 1 file changed, 182 insertions(+), 116 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 39cc01829..01e7b91d3 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -23,6 +23,8 @@ #include "lwip/pbuf.h" #include "lwip/igmp.h" #include "lwip/udp.h" +#include "lwip/tcpip.h" +#include "lwip/priv/tcpip_priv.h" #include "esp_wifi.h" #endif @@ -154,6 +156,14 @@ struct mdns_server_s { } search; }; +typedef struct { + struct tcpip_api_call call; + mdns_server_t *server; + uint8_t *data; + size_t len; + esp_err_t err; +} mdns_api_call_t; + #define MDNS_MUTEX_LOCK() xSemaphoreTake(server->lock, portMAX_DELAY) #define MDNS_MUTEX_UNLOCK() xSemaphoreGive(server->lock) @@ -163,7 +173,7 @@ struct mdns_server_s { static const char * MDNS_DEFAULT_DOMAIN = "local"; static const char * MDNS_SUB_STR = "_sub"; -static mdns_server_t * _mdns_servers[TCPIP_ADAPTER_IF_MAX] = {0,0,0}; +static mdns_server_t * _mdns_servers[TCPIP_ADAPTER_IF_MAX] = {0, 0, 0}; #ifndef MDNS_TEST_MODE @@ -184,7 +194,7 @@ static xSemaphoreHandle _mdns_service_semaphore = NULL; */ static void _mdns_server_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *addr, uint16_t port) { - while(pb != NULL) { + while (pb != NULL) { struct pbuf * this_pb = pb; pb = pb->next; this_pb->next = NULL; @@ -195,6 +205,56 @@ static void _mdns_server_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, } } +/** + * @brief init the network of MDNS server (called in tcpip thread context) + */ +static err_t _mdns_server_init_api(struct tcpip_api_call *api_call_msg) +{ + mdns_api_call_t *msg = (mdns_api_call_t*)api_call_msg; + mdns_server_t *server = msg->server; + esp_err_t err = ESP_OK; + + tcpip_adapter_ip_info_t if_ip_info; + err = tcpip_adapter_get_ip_info(server->tcpip_if, &if_ip_info); + if (err) { + msg->err = err; + return ERR_OK; + } + + ip_addr_t laddr; + IP_ADDR4(&laddr, 224, 0, 0, 251); + + ip_addr_t multicast_if_addr = IPADDR4_INIT(if_ip_info.ip.addr); + + if (igmp_joingroup((const struct ip4_addr *)&multicast_if_addr.u_addr.ip4, (const struct ip4_addr *)&laddr.u_addr.ip4)) { + msg->err = ESP_ERR_INVALID_STATE; + return ERR_OK; + } + + struct udp_pcb * pcb = udp_new(); + if (!pcb) { + msg->err = ESP_ERR_NO_MEM; + return ERR_OK; + } + + pcb->remote_port = MDNS_SERVICE_PORT; + + if (udp_bind(pcb, &multicast_if_addr, pcb->remote_port) != 0) { + udp_remove(pcb); + msg->err = ESP_ERR_INVALID_STATE; + return ERR_OK; + } + + pcb->mcast_ttl = 1; + ip_addr_copy(pcb->multicast_ip, multicast_if_addr); + ip_addr_copy(pcb->remote_ip, laddr); + + server->pcb = pcb; + udp_recv(pcb, &_mdns_server_recv, server); + msg->err = err; + return ERR_OK; +} + /** * @brief init the network of MDNS server * @@ -207,42 +267,29 @@ static void _mdns_server_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, */ esp_err_t _mdns_server_init(mdns_server_t * server) { - esp_err_t err = ESP_OK; + mdns_api_call_t msg = { + .server = server, + }; + tcpip_api_call(_mdns_server_init_api, (struct tcpip_api_call*)&msg); + return msg.err; +} - tcpip_adapter_ip_info_t if_ip_info; - err = tcpip_adapter_get_ip_info(server->tcpip_if, &if_ip_info); - if (err) { - return err; +/** + * @brief stop the network of MDNS server (called in tcpip thread context) + */ +static err_t _mdns_server_deinit_api(struct tcpip_api_call *api_call_msg) +{ + mdns_api_call_t *msg = (mdns_api_call_t*)api_call_msg; + mdns_server_t *server = msg->server; + + if (server->pcb) { + udp_recv(server->pcb, NULL, NULL); + udp_disconnect(server->pcb); + udp_remove(server->pcb); + server->pcb = NULL; } - - ip_addr_t laddr; - IP_ADDR4(&laddr, 224, 0, 0, 251); - - ip_addr_t multicast_if_addr = IPADDR4_INIT(if_ip_info.ip.addr); - - if (igmp_joingroup((const struct ip4_addr *)&multicast_if_addr.u_addr.ip4, (const struct ip4_addr *)&laddr.u_addr.ip4)) { - return ESP_ERR_INVALID_STATE; - } - - struct udp_pcb * pcb = udp_new(); - if (!pcb) { - return ESP_ERR_NO_MEM; - } - - pcb->remote_port = MDNS_SERVICE_PORT; - - if (udp_bind(pcb, &multicast_if_addr, pcb->remote_port) != 0) { - udp_remove(pcb); - return ESP_ERR_INVALID_STATE; - } - - pcb->mcast_ttl = 1; - ip_addr_copy(pcb->multicast_ip, multicast_if_addr); - ip_addr_copy(pcb->remote_ip, laddr); - - server->pcb = pcb; - udp_recv(pcb, &_mdns_server_recv, server); - return err; + msg->err = ESP_OK; + return ERR_OK; } /** @@ -254,16 +301,39 @@ esp_err_t _mdns_server_init(mdns_server_t * server) */ esp_err_t _mdns_server_deinit(mdns_server_t * server) { - if (server->pcb) { - udp_recv(server->pcb, NULL, NULL); - udp_disconnect(server->pcb); - udp_remove(server->pcb); - server->pcb = NULL; - } - return ESP_OK; + mdns_api_call_t msg = { + .server = server, + }; + tcpip_api_call(_mdns_server_deinit_api, (struct tcpip_api_call*)&msg); + return msg.err; } #endif +/** + * @brief send packet over UDP (called in tcpip thread context) + */ +static err_t _mdns_server_write_api(struct tcpip_api_call *api_call_msg) +{ + mdns_api_call_t *msg = (mdns_api_call_t*)api_call_msg; + mdns_server_t *server = msg->server; + + struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, msg->len, PBUF_RAM); + if (pbt == NULL) { + msg->len = 0; + return ERR_OK; + } + uint8_t* dst = (uint8_t *)pbt->payload; + memcpy(dst, msg->data, msg->len); + err_t err = udp_sendto(server->pcb, pbt, &(server->pcb->remote_ip), server->pcb->remote_port); + pbuf_free(pbt); + if (err) { + msg->len = 0; + return ERR_OK; + } + + return ERR_OK; +} + /** * @brief send packet over UDP * @@ -273,22 +343,18 @@ esp_err_t _mdns_server_deinit(mdns_server_t * server) * * @return length of sent packet or 0 on error */ -static size_t _mdns_server_write(mdns_server_t * server, uint8_t * data, size_t len) -{ +static size_t _mdns_server_write(mdns_server_t * server, uint8_t * data, size_t len) { #ifndef MDNS_TEST_MODE - struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pbt == NULL) { - return 0; - } - uint8_t* dst = (uint8_t *)pbt->payload; - memcpy(dst, data, len); - err_t err = udp_sendto(server->pcb, pbt, &(server->pcb->remote_ip), server->pcb->remote_port); - pbuf_free(pbt); - if (err) { - return 0; - } -#endif + mdns_api_call_t msg = { + .server = server, + .data = data, + .len = len, + }; + tcpip_api_call(_mdns_server_write_api, (struct tcpip_api_call*)&msg); + return msg.len; +#else return len; +#endif } /* @@ -307,10 +373,10 @@ static void _mdns_service_task(void *pvParameters) struct pbuf * pb; QueueSetMemberHandle_t queue; - for(;;) { + for (;;) { queue = xQueueSelectFromSet(_mdns_queue_set, portMAX_DELAY); if (queue && xQueueReceive(queue, &pb, 0) == pdTRUE) { - for(i=0; iqueue == queue) { MDNS_MUTEX_LOCK(); @@ -412,7 +478,7 @@ static esp_err_t _mdns_server_remove(mdns_server_t * server) } uint8_t i; - for(i=0; iservice == service) { //just add the new answer type to it a->answer |= type; @@ -484,7 +550,7 @@ static mdns_answer_item_t * _mdns_add_answer(mdns_answer_item_t * answers, mdns_ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * start, mdns_name_t * name, char * buf) { size_t index = 0; - while(start[index]) { + while (start[index]) { if (name->parts == 4) { return NULL; } @@ -495,7 +561,7 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s return NULL; } uint8_t i; - for(i=0; isub = 1; } else { - memcpy((uint8_t*)name + (name->parts++ * (MDNS_NAME_BUF_LEN)), buf, len+1); + memcpy((uint8_t*)name + (name->parts++ * (MDNS_NAME_BUF_LEN)), buf, len + 1); } } else { size_t address = (((uint16_t)len & 0x3F) << 8) | start[index++]; @@ -549,7 +615,7 @@ static const uint8_t * _mdns_parse_fqdn(const uint8_t * packet, const uint8_t * return 0; } if (name->parts == 3) { - memmove((uint8_t*)name + (MDNS_NAME_BUF_LEN), (uint8_t*)name, 3*(MDNS_NAME_BUF_LEN)); + memmove((uint8_t*)name + (MDNS_NAME_BUF_LEN), (uint8_t*)name, 3 * (MDNS_NAME_BUF_LEN)); name->host[0] = 0; } else if (name->parts == 2) { memmove((uint8_t*)(name->domain), (uint8_t*)(name->service), (MDNS_NAME_BUF_LEN)); @@ -579,7 +645,7 @@ static inline void _mdns_set_u16(uint8_t * packet, uint16_t index, uint16_t valu return; } packet[index] = (value >> 8) & 0xFF; - packet[index+1] = value & 0xFF; + packet[index + 1] = value & 0xFF; } /** @@ -719,10 +785,10 @@ static uint16_t _mdns_append_fqdn(uint8_t * packet, uint16_t * index, const char static char buf[MDNS_NAME_BUF_LEN]; uint8_t len = strlen(strings[0]); uint8_t * len_location = (uint8_t *)memchr(packet, (char)len, *index); - while(len_location) { - if (memcmp(len_location+1, strings[0], len)) { //not continuing with our string + while (len_location) { + if (memcmp(len_location + 1, strings[0], len)) { //not continuing with our string search_next: - len_location = (uint8_t *)memchr(len_location+1, (char)len, *index - (len_location+1 - packet)); + len_location = (uint8_t *)memchr(len_location + 1, (char)len, *index - (len_location + 1 - packet)); continue; } //read string into name and compare @@ -738,7 +804,7 @@ search_next: } if (name.parts == count) { uint8_t i; - for(i=0; iinstance)?service->instance - :(server->instance)?server->instance - :server->hostname; + str[0] = (service->instance) ? service->instance + : (server->instance) ? server->instance + : server->hostname; str[1] = service->service; str[2] = service->proto; str[3] = MDNS_DEFAULT_DOMAIN; @@ -824,7 +890,7 @@ static uint16_t _mdns_append_sdptr_record(uint8_t * packet, uint16_t * index, md const char * sd_str[4]; uint16_t record_length = 0; uint8_t part_length; - + sd_str[0] = (char*)"_services"; sd_str[1] = (char*)"_dns-sd"; sd_str[2] = (char*)"_udp"; @@ -835,7 +901,7 @@ static uint16_t _mdns_append_sdptr_record(uint8_t * packet, uint16_t * index, md str[2] = MDNS_DEFAULT_DOMAIN; part_length = _mdns_append_fqdn(packet, index, sd_str, 4); - + record_length += part_length; part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, MDNS_ANSWER_PTR_TTL); @@ -870,9 +936,9 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns uint16_t record_length = 0; uint8_t part_length; - str[0] = (service->instance)?service->instance - :(server->instance)?server->instance - :server->hostname; + str[0] = (service->instance) ? service->instance + : (server->instance) ? server->instance + : server->hostname; str[1] = service->service; str[2] = service->proto; str[3] = MDNS_DEFAULT_DOMAIN; @@ -895,10 +961,10 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns uint8_t len = service->txt_num_items; const char ** txt = service->txt; uint8_t i, l; - for(i=0; iinstance)?service->instance - :(server->instance)?server->instance - :server->hostname; + str[0] = (service->instance) ? service->instance + : (server->instance) ? server->instance + : server->hostname; str[1] = service->service; str[2] = service->proto; str[3] = MDNS_DEFAULT_DOMAIN; @@ -1047,7 +1113,7 @@ static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, mdn if ((*index + 15) >= MDNS_MAX_PACKET_SIZE) { return 0; } - + part_length = sizeof(ip6_addr_t); memcpy(packet + *index, ipv6, part_length); *index += part_length; @@ -1073,7 +1139,7 @@ static void _mdns_send_answers(mdns_server_t * server, mdns_answer_item_t * answ _mdns_set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, MDNS_FLAGS_AUTHORITATIVE); - while(answers) { + while (answers) { if (answers->answer & MDNS_ANSWER_A) { answers->answer &= ~MDNS_ANSWER_A; send_ip = true; @@ -1100,7 +1166,7 @@ static void _mdns_send_answers(mdns_server_t * server, mdns_answer_item_t * answ } answer_count += 1; } - + if (answers->answer & MDNS_ANSWER_SDPTR) { if (!_mdns_append_sdptr_record(packet, &index, server, answers->service)) { return; @@ -1127,12 +1193,12 @@ static void _mdns_send_answers(mdns_server_t * server, mdns_answer_item_t * answ uint8_t * v6addr = (uint8_t*)if_ip6.addr; //check if not 0 int i; - for(i=0;iservices; - while(s) { + while (s) { if (!strcmp(s->service->service, service) && !strcmp(s->service->proto, proto)) { return s; } @@ -1278,7 +1344,7 @@ static void _mdns_free_service(mdns_service_t * service) free((char *)service->proto); if (service->txt_num_items) { uint8_t i; - for(i=0; itxt_num_items; i++) { + for (i = 0; i < service->txt_num_items; i++) { free((char *)service->txt[i]); } } @@ -1295,7 +1361,7 @@ static void _mdns_free_service(mdns_service_t * service) */ static inline uint16_t _mdns_read_u16(const uint8_t * packet, uint16_t index) { - return (uint16_t)(packet[index]) << 8 | packet[index+1]; + return (uint16_t)(packet[index]) << 8 | packet[index + 1]; } /** @@ -1322,7 +1388,7 @@ void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len) uint8_t qs = questions; mdns_answer_item_t * answer_items = NULL; - while(qs--) { + while (qs--) { content = _mdns_parse_fqdn(data, content, name); if (!content) { answers = 0; @@ -1341,13 +1407,13 @@ void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len) } continue; } - + //is this a dns-sd service discovery meta query? if (!strcmp(name->host, "_services") && !strcmp(name->service, "_dns-sd") && !strcmp(name->proto, "_udp") && !strcmp(name->domain, MDNS_DEFAULT_DOMAIN) && type == MDNS_TYPE_PTR) { //add answers for all services mdns_srv_item_t * s = server->services; - while(s) { + while (s) { if (s->service->service && s->service->proto) { answer_items = _mdns_add_answer(answer_items, s->service, MDNS_ANSWER_SDPTR); } @@ -1370,18 +1436,18 @@ void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len) answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_ALL); } else if (type == MDNS_TYPE_TXT) { //match instance/host - const char * host = (si->service->instance)?si->service->instance - :(server->instance)?server->instance - :server->hostname; + const char * host = (si->service->instance) ? si->service->instance + : (server->instance) ? server->instance + : server->hostname; if (!host || !host[0] || !name->host[0] || strcmp(name->host, host)) { continue; } answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_TXT); } else if (type == MDNS_TYPE_SRV) { //match instance/host - const char * host = (si->service->instance)?si->service->instance - :(server->instance)?server->instance - :server->hostname; + const char * host = (si->service->instance) ? si->service->instance + : (server->instance) ? server->instance + : server->hostname; if (!host || !host[0] || !name->host[0] || strcmp(name->host, host)) { continue; } @@ -1402,7 +1468,7 @@ void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len) mdns_result_temp_t * answer = &a; memset(answer, 0, sizeof(mdns_result_temp_t)); - while(content < (data + len)) { + while (content < (data + len)) { content = _mdns_parse_fqdn(data, content, name); if (!content) { return;//error @@ -1412,7 +1478,7 @@ void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len) const uint8_t * data_ptr = content + MDNS_DATA_OFFSET; content = data_ptr + data_len; - if(content > (data + len)){ + if (content > (data + len)) { return; } @@ -1461,21 +1527,21 @@ void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len) strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN); } } else if (type == MDNS_TYPE_TXT) { - uint16_t i=0,b=0, y; - while(i < data_len) { + uint16_t i = 0, b = 0, y; + while (i < data_len) { uint8_t partLen = data_ptr[i++]; - if((i+partLen) > data_len){ + if ((i + partLen) > data_len) { break;//error } //check if partLen will fit in the buffer if (partLen > (MDNS_TXT_MAX_LEN - b - 1)) { break; } - for(y=0; ytxt[b++] = d; } - if (itxt[b++] = '&'; } } @@ -1613,7 +1679,7 @@ void mdns_free(mdns_server_t * server) free((char*)server->instance); if (server->queue) { struct pbuf * c; - while(xQueueReceive(server->queue, &c, 0) == pdTRUE) { + while (xQueueReceive(server->queue, &c, 0) == pdTRUE) { pbuf_free(c); } vQueueDelete(server->queue); @@ -1725,7 +1791,7 @@ esp_err_t mdns_service_txt_set(mdns_server_t * server, const char * service, con MDNS_MUTEX_LOCK(); if (s->service->txt_num_items) { uint8_t i; - for(i=0; iservice->txt_num_items; i++) { + for (i = 0; i < s->service->txt_num_items; i++) { free((char *)s->service->txt[i]); } } @@ -1738,7 +1804,7 @@ esp_err_t mdns_service_txt_set(mdns_server_t * server, const char * service, con } uint8_t i; s->service->txt_num_items = num_items; - for(i=0; iservice->txt[i] = strdup(txt[i]); if (!s->service->txt[i]) { s->service->txt_num_items = i; @@ -1796,7 +1862,7 @@ esp_err_t mdns_service_remove(mdns_server_t * server, const char * service, cons } //not first item mdns_srv_item_t * a = server->services; - while(a->next && a->next != s) { + while (a->next && a->next != s) { a = a->next; } //next item of the current item is our item @@ -1823,7 +1889,7 @@ esp_err_t mdns_service_remove_all(mdns_server_t * server) MDNS_MUTEX_LOCK(); mdns_srv_item_t * a = server->services; server->services = NULL; - while(a) { + while (a) { mdns_srv_item_t * s = a; a = a->next; _mdns_free_service(s->service); @@ -1899,7 +1965,7 @@ size_t mdns_query(mdns_server_t * server, const char * service, const char * pro server->search.running = true; if (timeout) { uint32_t startAt = xTaskGetTickCount() * portTICK_PERIOD_MS; - while(server->search.running && ((xTaskGetTickCount() * portTICK_PERIOD_MS) - startAt) < timeout) { + while (server->search.running && ((xTaskGetTickCount() * portTICK_PERIOD_MS) - startAt) < timeout) { vTaskDelay(1 / portTICK_PERIOD_MS); } server->search.running = false; @@ -1924,7 +1990,7 @@ esp_err_t mdns_result_free(mdns_server_t * server) if (!server || server->search.running || !server->search.results) { return ESP_ERR_INVALID_ARG; } - while(server->search.results) { + while (server->search.results) { const mdns_result_t * r = server->search.results; server->search.results = (mdns_result_t *)r->next; free((char *)r->host); @@ -1943,7 +2009,7 @@ size_t mdns_result_get_count(mdns_server_t * server) } size_t len = 0; const mdns_result_t * r = server->search.results; - while(r) { + while (r) { len++; r = r->next; } @@ -1957,7 +2023,7 @@ const mdns_result_t * mdns_result_get(mdns_server_t * server, size_t num) } size_t len = 0; const mdns_result_t * r = server->search.results; - while(r) { + while (r) { if (len++ == num) { return r; } From 907e7ee29e8642040507c551b67ce51dc986592d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Th=C3=A9rond?= Date: Tue, 25 Jul 2017 14:14:35 +0200 Subject: [PATCH 011/289] mdns: fix leak after _mdns_create_service if we have a malloc error. * Original commit: espressif/esp-idf@b6b36bd9ddf169039a5528f8b766048d97b975f7 --- components/mdns/mdns.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 01e7b91d3..40b4c7096 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1755,6 +1755,7 @@ esp_err_t mdns_service_add(mdns_server_t * server, const char * service, const c item = (mdns_srv_item_t *)malloc(sizeof(mdns_srv_item_t)); if (!item) { + free(s); return ESP_ERR_NO_MEM; } From 00a72b8920b8c5ce0e6f9efbbc68c197b9a986cf Mon Sep 17 00:00:00 2001 From: Siarhei Volkau Date: Fri, 27 Oct 2017 10:22:01 +0300 Subject: [PATCH 012/289] components/mdns: wrong Message compression detect Old behavior assumes message compressed when any of 2 most significant bits are set, But in fact Message compressed only when both those bits are set to 1. Also maximal label length should be 63 bytes. * Original commit: espressif/esp-idf@6e24566186c52dc5432b6b25c81abda577c21e85 --- components/mdns/mdns.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 40b4c7096..c77283e07 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -555,9 +555,9 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s return NULL; } uint8_t len = start[index++]; - if ((len & 0xC0) == 0) { - if (len > 64) { - //length can not be more than 64 + if (len < 0xC0) { + if (len > 63) { + //length can not be more than 63 return NULL; } uint8_t i; From 3aa605fe24117dd794cbe3d0e0bd01bba4a729c9 Mon Sep 17 00:00:00 2001 From: Roman Valls Guimera Date: Wed, 25 Oct 2017 23:23:42 +0200 Subject: [PATCH 013/289] Fix compilation errors when using gcc-7.2.0 for the crosstool-ng toolchain * Change snprintf for strlcat does not complain w/gcc7.2.0 and it is safer, thanks @projectgus * Use proper quotes for character literals Merges https://github.com/espressif/esp-idf/pull/1163 * Original commit: espressif/esp-idf@519edc332dae0160069fd790467cde8de78f1a0e --- components/mdns/mdns.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index c77283e07..171da177c 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -569,7 +569,8 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s && (strcmp(buf, MDNS_DEFAULT_DOMAIN) != 0) && (strcmp(buf, "ip6") != 0) && (strcmp(buf, "in-addr") != 0)) { - snprintf((char*)name, MDNS_NAME_BUF_LEN, "%s.%s", name->host, buf); + strlcat(name->host, ".", sizeof(name->host)); + strlcat(name->host, buf, sizeof(name->host)); } else if (strcmp(buf, MDNS_SUB_STR) == 0) { name->sub = 1; } else { From ad8c92db52acc711ab0bdbe88c532d61de700e16 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 7 Dec 2017 14:21:40 +0100 Subject: [PATCH 014/289] Import mDNS changes * Original commit: espressif/esp-idf@4bddbc031cee83935c0e4df1dc72cc7000c97ba5 --- components/mdns/component.mk | 2 + components/mdns/include/mdns.h | 335 +- components/mdns/include/mdns_console.h | 22 + components/mdns/mdns.c | 5090 +++++++++++++---- components/mdns/mdns_console.c | 1060 ++++ .../mdns/private_include/mdns_private.h | 388 ++ examples/protocols/mdns/README.md | 16 + .../protocols/mdns/main/mdns_example_main.c | 228 +- 8 files changed, 5844 insertions(+), 1297 deletions(-) create mode 100644 components/mdns/include/mdns_console.h create mode 100644 components/mdns/mdns_console.c create mode 100644 components/mdns/private_include/mdns_private.h mode change 100644 => 100755 examples/protocols/mdns/main/mdns_example_main.c diff --git a/components/mdns/component.mk b/components/mdns/component.mk index e69de29bb..064cc0608 100644 --- a/components/mdns/component.mk +++ b/components/mdns/component.mk @@ -0,0 +1,2 @@ +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_PRIV_INCLUDEDIRS := private_include diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index c0855466a..db0e3b522 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -20,35 +20,69 @@ extern "C" { #ifndef MDNS_TEST_MODE #include +#include "esp_event.h" #else #include "esp32_compat.h" #endif -struct mdns_server_s; -typedef struct mdns_server_s mdns_server_t; +#define MDNS_TYPE_A 0x0001 +#define MDNS_TYPE_PTR 0x000C +#define MDNS_TYPE_TXT 0x0010 +#define MDNS_TYPE_AAAA 0x001C +#define MDNS_TYPE_SRV 0x0021 +#define MDNS_TYPE_OPT 0x0029 +#define MDNS_TYPE_NSEC 0x002F +#define MDNS_TYPE_ANY 0x00FF /** - * @brief mDNS query result structure - * + * @brief mDNS enum to specify the ip_protocol type + */ +typedef enum { + MDNS_IP_PROTOCOL_V4, + MDNS_IP_PROTOCOL_V6, + MDNS_IP_PROTOCOL_MAX +} mdns_ip_protocol_t; + +/** + * @brief mDNS basic text item structure + * Used in mdns_service_add() + */ +typedef struct { + char * key; /*!< item key name */ + char * value; /*!< item value string */ +} mdns_txt_item_t; + +/** + * @brief mDNS query linked list IP item + */ +typedef struct mdns_ip_addr_s { + ip_addr_t addr; /*!< IP address */ + struct mdns_ip_addr_s * next; /*!< next IP, or NULL for the last IP in the list */ +} mdns_ip_addr_t; + +/** + * @brief mDNS query result structure */ typedef struct mdns_result_s { - const char * host; /*!< hostname */ - const char * instance; /*!< instance */ - const char * txt; /*!< txt data */ - uint16_t priority; /*!< service priority */ - uint16_t weight; /*!< service weight */ - uint16_t port; /*!< service port */ - struct ip4_addr addr; /*!< ip4 address */ - struct ip6_addr addrv6; /*!< ip6 address */ - const struct mdns_result_s * next; /*!< next result, or NULL for the last result in the list */ + struct mdns_result_s * next; /*!< next result, or NULL for the last result in the list */ + + tcpip_adapter_if_t tcpip_if; /*!< interface on which the result came (AP/STA/ETH) */ + mdns_ip_protocol_t ip_protocol; /*!< ip_protocol type of the interface (v4/v6) */ + // PTR + char * instance_name; /*!< instance name */ + // SRV + char * hostname; /*!< hostname */ + uint16_t port; /*!< service port */ + // TXT + mdns_txt_item_t * txt; /*!< txt record */ + size_t txt_count; /*!< number of txt items */ + // A and AAAA + mdns_ip_addr_t * addr; /*!< linked list of IP addreses found */ } mdns_result_t; /** * @brief Initialize mDNS on given interface * - * @param tcpip_if Interface that the server will listen on - * @param server Server pointer to populate on success - * * @return * - ESP_OK on success * - ESP_ERR_INVALID_ARG when bad tcpip_if is given @@ -56,20 +90,18 @@ typedef struct mdns_result_s { * - ESP_ERR_NO_MEM on memory error * - ESP_ERR_WIFI_NOT_INIT when WiFi is not initialized by eps_wifi_init */ -esp_err_t mdns_init(tcpip_adapter_if_t tcpip_if, mdns_server_t ** server); +esp_err_t mdns_init(); /** * @brief Stop and free mDNS server * - * @param server mDNS Server to free - * */ -void mdns_free(mdns_server_t * server); +void mdns_free(); /** * @brief Set the hostname for mDNS server + * required if you want to advertise services * - * @param server mDNS Server * @param hostname Hostname to set * * @return @@ -77,41 +109,42 @@ void mdns_free(mdns_server_t * server); * - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname); +esp_err_t mdns_hostname_set(const char * hostname); /** * @brief Set the default instance name for mDNS server * - * @param server mDNS Server - * @param instance Instance name to set + * @param instance_name Instance name to set * * @return * - ESP_OK success * - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance); +esp_err_t mdns_instance_name_set(const char * instance_name); /** * @brief Add service to mDNS server * - * @param server mDNS Server - * @param service service type (_http, _ftp, etc) - * @param proto service protocol (_tcp, _udp) - * @param port service port + * @param instance_name instance name to set. If NULL, + * global instance name or hostname will be used + * @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"}}) * * @return * - ESP_OK success * - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_service_add(mdns_server_t * server, const char * service, const char * proto, uint16_t port); +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); /** * @brief Remove service from mDNS server * - * @param server mDNS Server - * @param service service type (_http, _ftp, etc) + * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * * @return @@ -120,15 +153,14 @@ esp_err_t mdns_service_add(mdns_server_t * server, const char * service, const c * - ESP_ERR_NOT_FOUND Service not found * - ESP_FAIL unknown error */ -esp_err_t mdns_service_remove(mdns_server_t * server, const char * service, const char * proto); +esp_err_t mdns_service_remove(const char * service_type, const char * proto); /** * @brief Set instance name for service * - * @param server mDNS Server - * @param service service type (_http, _ftp, etc) - * @param proto service protocol (_tcp, _udp) - * @param instance instance name to set + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param instance_name instance name to set * * @return * - ESP_OK success @@ -136,30 +168,12 @@ esp_err_t mdns_service_remove(mdns_server_t * server, const char * service, cons * - ESP_ERR_NOT_FOUND Service not found * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_service_instance_set(mdns_server_t * server, const char * service, const char * proto, const char * instance); - -/** - * @brief Set TXT data for service - * - * @param server mDNS Server - * @param service service type (_http, _ftp, etc) - * @param proto service protocol (_tcp, _udp) - * @param num_items number of items in TXT data - * @param txt string array of TXT data (eg. {"var=val","other=2"}) - * - * @return - * - 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_txt_set(mdns_server_t * server, const char * service, const char * proto, uint8_t num_items, const char ** txt); +esp_err_t mdns_service_instance_name_set(const char * service_type, const char * proto, const char * instance_name); /** * @brief Set service port * - * @param server mDNS Server - * @param service service type (_http, _ftp, etc) + * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param port service port * @@ -168,69 +182,182 @@ esp_err_t mdns_service_txt_set(mdns_server_t * server, const char * service, con * - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_NOT_FOUND Service not found */ -esp_err_t mdns_service_port_set(mdns_server_t * server, const char * service, const char * proto, uint16_t port); +esp_err_t mdns_service_port_set(const char * service_type, const char * proto, uint16_t port); + +/** + * @brief Replace all TXT items for service + * + * @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"}}) + * + * @return + * - 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_txt_set(const char * service_type, const char * proto, mdns_txt_item_t txt[], uint8_t num_items); + +/** + * @brief Set/Add TXT item for service TXT record + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param key the key that you want to add/update + * @param value the new value of the key + * + * @return + * - 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_txt_item_set(const char * service_type, const char * proto, const char * key, const char * value); + +/** + * @brief Remove TXT item for service TXT record + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param key the key that you want to remove + * + * @return + * - 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_txt_item_remove(const char * service_type, const char * proto, const char * key); /** * @brief Remove and free all services from mDNS server * - * @param server mDNS Server - * * @return * - ESP_OK success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t mdns_service_remove_all(mdns_server_t * server); +esp_err_t mdns_service_remove_all(); /** * @brief Query mDNS for host or service + * All following query methods are derived from this one * - * @param server mDNS Server - * @param service service type or host name - * @param proto service protocol or NULL if searching for host - * @param timeout time to wait for answers. If 0, mdns_query_end MUST be called to end the search - * - * @return the number of results found - */ -size_t mdns_query(mdns_server_t * server, const char * service, const char * proto, uint32_t timeout); - -/** - * @brief Stop mDNS Query started with timeout = 0 - * - * @param server mDNS Server - * - * @return the number of results found - */ -size_t mdns_query_end(mdns_server_t * server); - -/** - * @brief get the number of results currently in memoty - * - * @param server mDNS Server - * - * @return the number of results - */ -size_t mdns_result_get_count(mdns_server_t * server); - -/** - * @brief Get mDNS Search result with given index - * - * @param server mDNS Server - * @param num the index of the result - * - * @return the result or NULL if error - */ -const mdns_result_t * mdns_result_get(mdns_server_t * server, size_t num); - -/** - * @brief Remove and free all search results from mDNS server - * - * @param server mDNS Server + * @param name service instance or host name (NULL for PTR queries) + * @param service_type service type (_http, _arduino, _ftp etc.) (NULL for host queries) + * @param proto service protocol (_tcp, _udp, etc.) (NULL for host queries) + * @param type type of query (MDNS_TYPE_*) + * @param timeout time in milliseconds to wait for answers. + * @param max_results maximum results to be collected + * @param results pointer to the results of the query + * results must be freed using mdns_query_results_free below * * @return * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG timeout was not given */ -esp_err_t mdns_result_free(mdns_server_t * server); +esp_err_t mdns_query(const char * name, const char * service_type, const char * proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t ** results); + +/** + * @brief Free query results + * + * @param results linked list of results to be freed + */ +void mdns_query_results_free(mdns_result_t * results); + +/** + * @brief Query mDNS for service + * + * @param service_type service type (_http, _arduino, _ftp etc.) + * @param proto service protocol (_tcp, _udp, etc.) + * @param timeout time in milliseconds to wait for answer. + * @param max_results maximum results to be collected + * @param results pointer to the results of the query + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_query_ptr(const char * service_type, const char * proto, uint32_t timeout, size_t max_results, mdns_result_t ** results); + +/** + * @brief Query mDNS for SRV record + * + * @param instance_name service instance name + * @param service_type service type (_http, _arduino, _ftp etc.) + * @param proto service protocol (_tcp, _udp, etc.) + * @param timeout time in milliseconds to wait for answer. + * @param result pointer to the result of the query + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_query_srv(const char * instance_name, const char * service_type, const char * proto, uint32_t timeout, mdns_result_t ** result); + +/** + * @brief Query mDNS for TXT record + * + * @param instance_name service instance name + * @param service_type service type (_http, _arduino, _ftp etc.) + * @param proto service protocol (_tcp, _udp, etc.) + * @param timeout time in milliseconds to wait for answer. + * @param result pointer to the result of the query + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_query_txt(const char * instance_name, const char * service_type, const char * proto, uint32_t timeout, mdns_result_t ** result); + +/** + * @brief Query mDNS for A record + * + * @param host_name host name to look for + * @param timeout time in milliseconds to wait for answer. + * @param addr pointer to the resulting IP4 address + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_query_a(const char * host_name, uint32_t timeout, ip4_addr_t * addr); + +/** + * @brief Query mDNS for A record + * + * @param host_name host name to look for + * @param timeout time in milliseconds to wait for answer. If 0, max_results needs to be defined + * @param addr pointer to the resulting IP6 address + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, ip6_addr_t * addr); + +/** + * @brief System event handler + * This method controls the service state on all active interfaces and applications are required + * to call it from the system event handler for normal operation of mDNS service. + * + * @param ctx The system event context + * @param event The system event + */ +esp_err_t mdns_handle_system_event(void *ctx, system_event_t *event); #ifdef __cplusplus } diff --git a/components/mdns/include/mdns_console.h b/components/mdns/include/mdns_console.h new file mode 100644 index 000000000..5c8b0b5a4 --- /dev/null +++ b/components/mdns/include/mdns_console.h @@ -0,0 +1,22 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _MDNS_CONSOLE_H_ +#define _MDNS_CONSOLE_H_ + +/** + * @brief Register MDNS functions with the console component + */ +void mdns_console_register(); + +#endif /* _MDNS_CONSOLE_H_ */ diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 171da177c..061c63148 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -14,7 +14,6 @@ #include "mdns.h" #include -#ifndef MDNS_TEST_MODE #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/queue.h" @@ -23,316 +22,359 @@ #include "lwip/pbuf.h" #include "lwip/igmp.h" #include "lwip/udp.h" -#include "lwip/tcpip.h" +#include "lwip/mld6.h" #include "lwip/priv/tcpip_priv.h" #include "esp_wifi.h" +#include "esp_system.h" +#include "esp_timer.h" +#include "esp_event_loop.h" + +#include "mdns_private.h" + +#ifdef MDNS_ENABLE_DEBUG +void mdns_debug_packet(const uint8_t * data, size_t len); #endif -#define MDNS_FLAGS_AUTHORITATIVE 0x8400 - -#define MDNS_NAME_REF 0xC000 - -#define MDNS_TYPE_AAAA 0x001C -#define MDNS_TYPE_A 0x0001 -#define MDNS_TYPE_PTR 0x000C -#define MDNS_TYPE_SRV 0x0021 -#define MDNS_TYPE_TXT 0x0010 -#define MDNS_TYPE_NSEC 0x002F -#define MDNS_TYPE_ANY 0x00FF - -#define MDNS_CLASS_IN 0x0001 -#define MDNS_CLASS_IN_FLUSH_CACHE 0x8001 - -#define MDNS_ANSWER_ALL 0x3F -#define MDNS_ANSWER_PTR 0x08 -#define MDNS_ANSWER_TXT 0x04 -#define MDNS_ANSWER_SRV 0x02 -#define MDNS_ANSWER_A 0x01 -#define MDNS_ANSWER_AAAA 0x10 -#define MDNS_ANSWER_NSEC 0x20 -#define MDNS_ANSWER_SDPTR 0x80 - -#define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on -#define MDNS_SERVICE_STACK_DEPTH 4096 // Stack size for the service thread -#define MDNS_PACKET_QUEUE_LEN 16 // Maximum packets that can be queued for parsing -#define MDNS_TXT_MAX_LEN 1024 // Maximum string length of text data in TXT record -#define MDNS_NAME_MAX_LEN 64 // Maximum string length of hostname, instance, service and proto -#define MDNS_NAME_BUF_LEN (MDNS_NAME_MAX_LEN+1) // Maximum char buffer size to hold hostname, instance, service or proto -#define MDNS_MAX_PACKET_SIZE 1460 // Maximum size of mDNS outgoing packet - -#define MDNS_ANSWER_PTR_TTL 4500 -#define MDNS_ANSWER_TXT_TTL 4500 -#define MDNS_ANSWER_SRV_TTL 120 -#define MDNS_ANSWER_A_TTL 120 -#define MDNS_ANSWER_AAAA_TTL 120 - -#define MDNS_HEAD_LEN 12 -#define MDNS_HEAD_ID_OFFSET 0 -#define MDNS_HEAD_FLAGS_OFFSET 2 -#define MDNS_HEAD_QUESTIONS_OFFSET 4 -#define MDNS_HEAD_ANSWERS_OFFSET 6 -#define MDNS_HEAD_SERVERS_OFFSET 8 -#define MDNS_HEAD_ADDITIONAL_OFFSET 10 - -#define MDNS_TYPE_OFFSET 0 -#define MDNS_CLASS_OFFSET 2 -#define MDNS_TTL_OFFSET 4 -#define MDNS_LEN_OFFSET 8 -#define MDNS_DATA_OFFSET 10 - -#define MDNS_SRV_PRIORITY_OFFSET 0 -#define MDNS_SRV_WEIGHT_OFFSET 2 -#define MDNS_SRV_PORT_OFFSET 4 -#define MDNS_SRV_FQDN_OFFSET 6 - -typedef struct { - char host[MDNS_NAME_BUF_LEN]; - char service[MDNS_NAME_BUF_LEN]; - char proto[MDNS_NAME_BUF_LEN]; - char domain[MDNS_NAME_BUF_LEN]; - uint8_t parts; - uint8_t sub; -} mdns_name_t; - -typedef struct { - char host[MDNS_NAME_BUF_LEN]; - char instance[MDNS_NAME_BUF_LEN]; - char txt[MDNS_TXT_MAX_LEN]; - uint16_t priority; - uint16_t weight; - uint16_t port; - uint32_t addr; - uint8_t addrv6[16]; - uint8_t ptr; -} mdns_result_temp_t; - -typedef struct { - const char * host; - const char * sub; - const char * service; - const char * proto; - const char * domain; - uint8_t parts; - uint8_t done; -} mdns_string_t; - -typedef struct mdns_service_s { - const char * instance; - const char * service; - const char * proto; - uint16_t priority; - uint16_t weight; - uint16_t port; - uint8_t txt_num_items; - const char ** txt; -} mdns_service_t; - -typedef struct mdns_srv_item_s { - mdns_service_t * service; - struct mdns_srv_item_s * next; -} mdns_srv_item_t; - -typedef struct mdns_answer_item_s { - mdns_service_t * service; - uint8_t answer; - struct mdns_answer_item_s * next; -} mdns_answer_item_t; - -struct mdns_server_s { - tcpip_adapter_if_t tcpip_if; - struct udp_pcb * pcb; - const char * hostname; - const char * instance; - mdns_srv_item_t * services; - xSemaphoreHandle lock; - xQueueHandle queue; - struct { - char host[MDNS_NAME_BUF_LEN]; - char service[MDNS_NAME_BUF_LEN]; - char proto[MDNS_NAME_BUF_LEN]; - bool running; - xSemaphoreHandle lock; - mdns_result_t * results; - } search; -}; - -typedef struct { - struct tcpip_api_call call; - mdns_server_t *server; - uint8_t *data; - size_t len; - esp_err_t err; -} mdns_api_call_t; - -#define MDNS_MUTEX_LOCK() xSemaphoreTake(server->lock, portMAX_DELAY) -#define MDNS_MUTEX_UNLOCK() xSemaphoreGive(server->lock) - -#define MDNS_SEARCH_LOCK() xSemaphoreTake(server->search.lock, portMAX_DELAY) -#define MDNS_SEARCH_UNLOCK() xSemaphoreGive(server->search.lock) - static const char * MDNS_DEFAULT_DOMAIN = "local"; static const char * MDNS_SUB_STR = "_sub"; -static mdns_server_t * _mdns_servers[TCPIP_ADAPTER_IF_MAX] = {0, 0, 0}; +static mdns_server_t * _mdns_server = NULL; -#ifndef MDNS_TEST_MODE +static volatile TaskHandle_t _mdns_service_task_handle = NULL; +static SemaphoreHandle_t _mdns_service_semaphore = NULL; -static TaskHandle_t _mdns_service_task_handle = NULL; -static QueueSetHandle_t _mdns_queue_set = NULL; +static void _mdns_search_finish_done(); +static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * search, mdns_name_t * name, uint16_t type, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, ip_addr_t * ip, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static xSemaphoreHandle _mdns_service_semaphore = NULL; -#define MDNS_SERVICE_LOCK() xSemaphoreTake(_mdns_service_semaphore, portMAX_DELAY) -#define MDNS_SERVICE_UNLOCK() xSemaphoreGive(_mdns_service_semaphore) +/* + * @brief Appends/increments a number to name/instance in case of collision + * */ +static char * _mdns_mangle_name(char* in) { + char *p = strrchr(in, '-'); + int suffix = 0; + if (p == NULL) { + //No - in ``in`` + suffix = 2; + } else { + char *endp = NULL; + suffix = strtol(p + 1, &endp, 10); + if (*endp != 0) { + //suffix is not numerical + suffix = 2; + p = NULL; //so we append -suffix to the entire string + } + } + char *ret; + if (p == NULL) { + //need to add -2 to string + ret = malloc(strlen(in) + 3); + if (ret == NULL) { + return NULL; + } + sprintf(ret, "%s-2", in); + } else { + ret = malloc(strlen(in) + 2); //one extra byte in case 9-10 or 99-100 etc + strcpy(ret, in); + int baseLen = p - in; //length of 'bla' in 'bla-123' + //overwrite suffix with new suffix + sprintf(ret + baseLen, "-%d", suffix + 1); + } + return ret; +} + +/** + * @brief finds service from given service type + * @param server the server + * @param service service type to match + * @param proto proto to match + * + * @return the service item if found or NULL on error + */ +static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto) +{ + mdns_srv_item_t * s = _mdns_server->services; + while (s) { + if (!strcasecmp(s->service->service, service) && !strcasecmp(s->service->proto, proto)) { + return s; + } + s = s->next; + } + return NULL; +} /* * MDNS Server Networking * */ +/** + * @brief Queue RX packet action + */ +static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet) +{ + mdns_action_t * action = NULL; + + action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + return ESP_ERR_NO_MEM; + } + + action->type = ACTION_RX_HANDLE; + action->data.rx_handle.packet = packet; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + /** * @brief the receive callback of the raw udp api. Packets are received here * */ -static void _mdns_server_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *addr, uint16_t port) +static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport) { + uint8_t i; while (pb != NULL) { struct pbuf * this_pb = pb; pb = pb->next; this_pb->next = NULL; - mdns_server_t * server = (mdns_server_t *)arg; - if (!server || !server->queue || xQueueSend(server->queue, &this_pb, (portTickType)0) != pdPASS) { + + mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t)); + if (!packet) { + //missed packet - no memory pbuf_free(this_pb); + continue; + } + + packet->tcpip_if = TCPIP_ADAPTER_IF_MAX; + packet->pb = this_pb; + packet->src_port = rport; + memcpy(&packet->src, raddr, sizeof(ip_addr_t)); + packet->dest.type = packet->src.type; + + if (packet->src.type == IPADDR_TYPE_V4) { + packet->ip_protocol = MDNS_IP_PROTOCOL_V4; + struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN); + packet->dest.u_addr.ip4.addr = iphdr->dest.addr; + } else { + packet->ip_protocol = MDNS_IP_PROTOCOL_V6; + struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN); + memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16); + } + packet->multicast = ip_addr_ismulticast(&(packet->dest)); + + //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces) + struct netif * netif = NULL; + void * nif = NULL; + struct udp_pcb * pcb = NULL; + for (i=0; iinterfaces[i].pcbs[packet->ip_protocol].pcb; + tcpip_adapter_get_netif (i, &nif); + netif = (struct netif *)nif; + if (pcb && netif && netif == ip_current_input_netif ()) { + if (packet->src.type == IPADDR_TYPE_V4) { + if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) { + //packet source is not in the same subnet + pcb = NULL; + break; + } + } + packet->tcpip_if = i; + break; + } + pcb = NULL; + } + + if (!pcb || !_mdns_server || !_mdns_server->action_queue + || _mdns_send_rx_action(packet) != ESP_OK) { + pbuf_free(this_pb); + free(packet); } } } /** - * @brief init the network of MDNS server (called in tcpip thread context) + * @brief Stop PCB Main code */ -static err_t _mdns_server_init_api(struct tcpip_api_call *api_call_msg) +static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { - mdns_api_call_t *msg = (mdns_api_call_t*)api_call_msg; - mdns_server_t *server = msg->server; - esp_err_t err = ESP_OK; + if (!_mdns_server) { + return; + } + mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; + if (_pcb->pcb) { + _pcb->state = PCB_OFF; + udp_recv(_pcb->pcb, NULL, NULL); + udp_disconnect(_pcb->pcb); + udp_remove(_pcb->pcb); + free(_pcb->probe_services); + _pcb->pcb = NULL; + _pcb->probe_ip = false; + _pcb->probe_services = NULL; + _pcb->probe_services_len = 0; + _pcb->probe_running = false; + _pcb->failed_probes = 0; + } +} +/** + * @brief Start PCB V4 + */ +static esp_err_t _udp_pcb_v4_init(tcpip_adapter_if_t tcpip_if) +{ tcpip_adapter_ip_info_t if_ip_info; - err = tcpip_adapter_get_ip_info(server->tcpip_if, &if_ip_info); - if (err) { - msg->err = err; - return ERR_OK; + + if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) { + return ESP_ERR_INVALID_STATE; } - ip_addr_t laddr; - IP_ADDR4(&laddr, 224, 0, 0, 251); - - ip_addr_t multicast_if_addr = IPADDR4_INIT(if_ip_info.ip.addr); - - if (igmp_joingroup((const struct ip4_addr *)&multicast_if_addr.u_addr.ip4, (const struct ip4_addr *)&laddr.u_addr.ip4)) { - msg->err = ESP_ERR_INVALID_STATE; - return ERR_OK; + if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info) || if_ip_info.ip.addr == 0) { + return ESP_ERR_INVALID_ARG; } - struct udp_pcb * pcb = udp_new(); + ip_addr_t interface_addr = IPADDR4_INIT(if_ip_info.ip.addr); + + ip_addr_t multicast_addr; + IP_ADDR4(&multicast_addr, 224, 0, 0, 251); + + if (igmp_joingroup((const struct ip4_addr *)&interface_addr.u_addr.ip4, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) { + return ESP_ERR_INVALID_STATE; + } + + struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V4); if (!pcb) { - msg->err = ESP_ERR_NO_MEM; - return ERR_OK; + return ESP_ERR_NO_MEM; } - pcb->remote_port = MDNS_SERVICE_PORT; - - if (udp_bind(pcb, &multicast_if_addr, pcb->remote_port) != 0) { + if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { udp_remove(pcb); - msg->err = ESP_ERR_INVALID_STATE; - return ERR_OK; + return ESP_ERR_INVALID_STATE; } pcb->mcast_ttl = 1; - ip_addr_copy(pcb->multicast_ip, multicast_if_addr); - ip_addr_copy(pcb->remote_ip, laddr); + pcb->remote_port = MDNS_SERVICE_PORT; + ip_addr_copy(pcb->multicast_ip, interface_addr); + ip_addr_copy(pcb->remote_ip, multicast_addr); - server->pcb = pcb; - udp_recv(pcb, &_mdns_server_recv, server); - msg->err = err; - return ERR_OK; + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb = pcb; + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].failed_probes = 0; + udp_recv(pcb, &_udp_recv, _mdns_server); + + return ESP_OK; } /** - * @brief init the network of MDNS server - * - * @param server The server - * - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_STATE on igmp/bind error - * - ESP_ERR_NO_MEM on memory error + * @brief Start PCB V6 */ -esp_err_t _mdns_server_init(mdns_server_t * server) +static esp_err_t _udp_pcb_v6_init(tcpip_adapter_if_t tcpip_if) +{ + ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); + ip_addr_t interface_addr; + interface_addr.type = IPADDR_TYPE_V6; + + if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) { + return ESP_ERR_INVALID_STATE; + } + + if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &interface_addr.u_addr.ip6)) { + return ESP_ERR_INVALID_ARG; + } + + if (mld6_joingroup(&(interface_addr.u_addr.ip6), &(multicast_addr.u_addr.ip6))) { + return ESP_ERR_INVALID_STATE; + } + + struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V6); + if (!pcb) { + return ESP_ERR_NO_MEM; + } + + if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { + udp_remove(pcb); + return ESP_ERR_INVALID_STATE; + } + + pcb->remote_port = MDNS_SERVICE_PORT; + ip_addr_copy(pcb->remote_ip, multicast_addr); + + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb = pcb; + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].failed_probes = 0; + udp_recv(pcb, &_udp_recv, _mdns_server); + + return ESP_OK; +} + +/** + * @brief Start PCB Main code + */ +static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (ip_protocol == MDNS_IP_PROTOCOL_V4) { + return _udp_pcb_v4_init(tcpip_if); + } else if (ip_protocol == MDNS_IP_PROTOCOL_V6) { + return _udp_pcb_v6_init(tcpip_if); + } + return ESP_ERR_INVALID_ARG; +} + +typedef struct { + struct tcpip_api_call call; + tcpip_adapter_if_t tcpip_if; + mdns_ip_protocol_t ip_protocol; + esp_err_t err; +} mdns_api_call_t; + +/** + * @brief Start PCB from LwIP thread + */ +static err_t _mdns_pcb_init_api(struct tcpip_api_call *api_call_msg) +{ + mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; + msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol); + return msg->err; +} + +/** + * @brief Start PCB + */ +static esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_api_call_t msg = { - .server = server, + .tcpip_if = tcpip_if, + .ip_protocol = ip_protocol }; - tcpip_api_call(_mdns_server_init_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call*)&msg); return msg.err; } /** - * @brief stop the network of MDNS server (called in tcpip thread context) + * @brief Stop PCB from LwIP thread */ -static err_t _mdns_server_deinit_api(struct tcpip_api_call *api_call_msg) +static err_t _mdns_pcb_deinit_api(struct tcpip_api_call *api_call_msg) { - mdns_api_call_t *msg = (mdns_api_call_t*)api_call_msg; - mdns_server_t *server = msg->server; - - if (server->pcb) { - udp_recv(server->pcb, NULL, NULL); - udp_disconnect(server->pcb); - udp_remove(server->pcb); - server->pcb = NULL; - } + mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; + _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol); msg->err = ESP_OK; - return ERR_OK; + return ESP_OK; } /** - * @brief stop the network of MDNS server - * - * @param server The server - * - * @return ESP_OK + * @brief Stop PCB */ -esp_err_t _mdns_server_deinit(mdns_server_t * server) +static esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_api_call_t msg = { - .server = server, + .tcpip_if = tcpip_if, + .ip_protocol = ip_protocol }; - tcpip_api_call(_mdns_server_deinit_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call*)&msg); return msg.err; } -#endif -/** - * @brief send packet over UDP (called in tcpip thread context) - */ -static err_t _mdns_server_write_api(struct tcpip_api_call *api_call_msg) -{ - mdns_api_call_t *msg = (mdns_api_call_t*)api_call_msg; - mdns_server_t *server = msg->server; - - struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, msg->len, PBUF_RAM); - if (pbt == NULL) { - msg->len = 0; - return ERR_OK; - } - uint8_t* dst = (uint8_t *)pbt->payload; - memcpy(dst, msg->data, msg->len); - err_t err = udp_sendto(server->pcb, pbt, &(server->pcb->remote_ip), server->pcb->remote_port); - pbuf_free(pbt); - if (err) { - msg->len = 0; - return ERR_OK; - } - - return ERR_OK; -} /** * @brief send packet over UDP @@ -343,197 +385,30 @@ static err_t _mdns_server_write_api(struct tcpip_api_call *api_call_msg) * * @return length of sent packet or 0 on error */ -static size_t _mdns_server_write(mdns_server_t * server, uint8_t * data, size_t len) { -#ifndef MDNS_TEST_MODE - mdns_api_call_t msg = { - .server = server, - .data = data, - .len = len, - }; - tcpip_api_call(_mdns_server_write_api, (struct tcpip_api_call*)&msg); - return msg.len; -#else - return len; -#endif -} - -/* - * MDNS Servers - * */ - -#ifndef MDNS_TEST_MODE -void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len); - -/** - * @brief the main MDNS service task. Packets are received and parsed here - */ -static void _mdns_service_task(void *pvParameters) -{ - uint8_t i; - struct pbuf * pb; - QueueSetMemberHandle_t queue; - - for (;;) { - queue = xQueueSelectFromSet(_mdns_queue_set, portMAX_DELAY); - if (queue && xQueueReceive(queue, &pb, 0) == pdTRUE) { - for (i = 0; i < TCPIP_ADAPTER_IF_MAX; i++) { - mdns_server_t * server = _mdns_servers[i]; - if (server && server->queue == queue) { - MDNS_MUTEX_LOCK(); - mdns_parse_packet(server, (uint8_t*)pb->payload, pb->len); - MDNS_MUTEX_UNLOCK(); - break; - } - } - pbuf_free(pb); - } - } -} -#endif - -/** - * @brief get the server assigned to particular interface - * - * @param tcpip_if The interface - * - * @return reference to the server from the server list or NULL if not found - */ -static mdns_server_t * _mdns_server_get(tcpip_adapter_if_t tcpip_if) -{ - if (tcpip_if < TCPIP_ADAPTER_IF_MAX) { - return _mdns_servers[tcpip_if]; - } - return NULL; -} - -/** - * @brief add server to the server list. Start the service thread if not running - * - * @param server The server to add - * - * @return - * - ESP_OK on success - * - ESP_FAIL on error - * - ESP_ERR_* on network error - */ -static esp_err_t _mdns_server_add(mdns_server_t * server) +static size_t _udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len) { #ifndef MDNS_TEST_MODE - if (!_mdns_service_semaphore) { - _mdns_service_semaphore = xSemaphoreCreateMutex(); - if (!_mdns_service_semaphore) { - return ESP_FAIL; - } - } - MDNS_SERVICE_LOCK(); - if (!_mdns_service_task_handle) { - _mdns_queue_set = xQueueCreateSet(TCPIP_ADAPTER_IF_MAX * MDNS_PACKET_QUEUE_LEN); - if (!_mdns_queue_set) { - MDNS_SERVICE_UNLOCK(); - return ESP_FAIL; - } - xTaskCreatePinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, 1, &_mdns_service_task_handle, 0); - if (!_mdns_service_task_handle) { - vQueueDelete(_mdns_queue_set); - _mdns_queue_set = NULL; - MDNS_SERVICE_UNLOCK(); - return ESP_FAIL; - } - } - MDNS_SERVICE_UNLOCK(); - - if (xQueueAddToSet(server->queue, _mdns_queue_set) != pdPASS) { - return ESP_FAIL; - } - - //start UDP - esp_err_t err = _mdns_server_init(server); + struct netif * netif = NULL; + void * nif = NULL; + esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif); + netif = (struct netif *)nif; if (err) { - return err; + return 0; + } + + struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pbt == NULL) { + return 0; + } + memcpy((uint8_t *)pbt->payload, data, len); + + err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif); + pbuf_free(pbt); + if (err) { + return 0; } #endif - _mdns_servers[server->tcpip_if] = server; - - return ESP_OK; -} - -/** - * @brief remove server from server list. Stop the service thread in no more servers are running - * - * @param server The server to remove - * - * @return - * - ESP_OK on success - * - ESP_FAIL on error - */ -static esp_err_t _mdns_server_remove(mdns_server_t * server) -{ - _mdns_servers[server->tcpip_if] = NULL; -#ifndef MDNS_TEST_MODE - //stop UDP - _mdns_server_deinit(server); - - if (xQueueRemoveFromSet(server->queue, _mdns_queue_set) != pdPASS) { - return ESP_FAIL; - } - - uint8_t i; - for (i = 0; i < TCPIP_ADAPTER_IF_MAX; i++) { - if (_mdns_servers[i]) { - break; - } - } - if (i == TCPIP_ADAPTER_IF_MAX) { - //none of the servers are running - MDNS_SERVICE_LOCK(); - if (_mdns_service_task_handle) { - vTaskDelete(_mdns_service_task_handle); - vQueueDelete(_mdns_queue_set); - _mdns_queue_set = NULL; - _mdns_service_task_handle = NULL; - } - MDNS_SERVICE_UNLOCK(); - } -#endif - return ESP_OK; -} - - -/* - * PARSING - * */ - -/** - * @brief queues service for answer (if service is already added, append the new answer type) - * - * @param answers Linked list of answers - * @param service Service to add to the answers - * @param type Type of the answer - * - * @return the new linked list of answers - */ -static mdns_answer_item_t * _mdns_add_answer(mdns_answer_item_t * answers, mdns_service_t * service, uint8_t type) -{ - //see if we already have the service queued - mdns_answer_item_t * a = answers; - while (a) { - if (a->service == service) { - //just add the new answer type to it - a->answer |= type; - return answers; - } - a = a->next; - } - //prepend the q with this new answer - a = (mdns_answer_item_t *)malloc(sizeof(mdns_answer_item_t)); - if (!a) { - return answers;//fail! - } - a->service = service; - a->answer = type; - a->next = answers; - answers = a; - return a; + return len; } /** @@ -561,20 +436,21 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s return NULL; } uint8_t i; - for (i = 0; i < len; i++) { + for (i=0; iparts == 1 && buf[0] != '_' - && (strcmp(buf, MDNS_DEFAULT_DOMAIN) != 0) - && (strcmp(buf, "ip6") != 0) - && (strcmp(buf, "in-addr") != 0)) { + && (strcasecmp(buf, MDNS_DEFAULT_DOMAIN) != 0) + && (strcasecmp(buf, "ip6") != 0) + && (strcasecmp(buf, "in-addr") != 0)) { strlcat(name->host, ".", sizeof(name->host)); strlcat(name->host, buf, sizeof(name->host)); - } else if (strcmp(buf, MDNS_SUB_STR) == 0) { + } else if (strcasecmp(buf, MDNS_SUB_STR) == 0) { name->sub = 1; } else { - memcpy((uint8_t*)name + (name->parts++ * (MDNS_NAME_BUF_LEN)), buf, len + 1); + char* mdns_name_ptrs[]={name->host, name->service, name->proto, name->domain}; + memcpy(mdns_name_ptrs[name->parts++], buf, len+1); } } else { size_t address = (((uint16_t)len & 0x3F) << 8) | start[index++]; @@ -591,48 +467,6 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s return start + index + 1; } -/** - * @brief reads and formats MDNS FQDN into mdns_name_t structure - * - * @param packet MDNS packet - * @param start Starting point of FQDN - * @param name mdns_name_t structure to populate - * - * @return the address after the parsed FQDN in the packet or NULL on error - */ -static const uint8_t * _mdns_parse_fqdn(const uint8_t * packet, const uint8_t * start, mdns_name_t * name) -{ - name->parts = 0; - name->sub = 0; - name->host[0] = 0; - name->service[0] = 0; - name->proto[0] = 0; - name->domain[0] = 0; - - static char buf[MDNS_NAME_BUF_LEN]; - - const uint8_t * next_data = (uint8_t*)_mdns_read_fqdn(packet, start, name, buf); - if (!next_data || name->parts < 2) { - return 0; - } - if (name->parts == 3) { - memmove((uint8_t*)name + (MDNS_NAME_BUF_LEN), (uint8_t*)name, 3 * (MDNS_NAME_BUF_LEN)); - name->host[0] = 0; - } else if (name->parts == 2) { - memmove((uint8_t*)(name->domain), (uint8_t*)(name->service), (MDNS_NAME_BUF_LEN)); - name->service[0] = 0; - name->proto[0] = 0; - } - if (strcmp(name->domain, MDNS_DEFAULT_DOMAIN) == 0 || strcmp(name->domain, "arpa") == 0) { - return next_data; - } - return 0; -} - -/* - * Packet construction - * */ - /** * @brief sets uint16_t value in a packet * @@ -646,7 +480,7 @@ static inline void _mdns_set_u16(uint8_t * packet, uint16_t index, uint16_t valu return; } packet[index] = (value >> 8) & 0xFF; - packet[index + 1] = value & 0xFF; + packet[index+1] = value & 0xFF; } /** @@ -718,26 +552,30 @@ static inline uint8_t _mdns_append_u32(uint8_t * packet, uint16_t * index, uint3 * * @return length of added data: 0 on error or 10 on success */ -static inline uint8_t _mdns_append_type(uint8_t * packet, uint16_t * index, uint8_t type, uint32_t ttl) +static inline uint8_t _mdns_append_type(uint8_t * packet, uint16_t * index, uint8_t type, bool flush, uint32_t ttl) { if ((*index + 10) >= MDNS_MAX_PACKET_SIZE) { return 0; } + uint16_t clas = MDNS_CLASS_IN; + if (flush) { + clas = MDNS_CLASS_IN_FLUSH_CACHE; + } if (type == MDNS_ANSWER_PTR) { _mdns_append_u16(packet, index, MDNS_TYPE_PTR); - _mdns_append_u16(packet, index, MDNS_CLASS_IN); + _mdns_append_u16(packet, index, clas); } else if (type == MDNS_ANSWER_TXT) { _mdns_append_u16(packet, index, MDNS_TYPE_TXT); - _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE); + _mdns_append_u16(packet, index, clas); } else if (type == MDNS_ANSWER_SRV) { _mdns_append_u16(packet, index, MDNS_TYPE_SRV); - _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE); + _mdns_append_u16(packet, index, clas); } else if (type == MDNS_ANSWER_A) { _mdns_append_u16(packet, index, MDNS_TYPE_A); - _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE); + _mdns_append_u16(packet, index, clas); } else if (type == MDNS_ANSWER_AAAA) { _mdns_append_u16(packet, index, MDNS_TYPE_AAAA); - _mdns_append_u16(packet, index, MDNS_CLASS_IN_FLUSH_CACHE); + _mdns_append_u16(packet, index, clas); } else { return 0; } @@ -768,7 +606,8 @@ static inline uint8_t _mdns_append_string(uint8_t * packet, uint16_t * index, co } /** - * @brief appends FQDN to a packet, incrementing the index + * @brief appends FQDN to a packet, incrementing the index and + * compressing the output if previous occurrence of the string (or part of it) has been found * * @param packet MDNS packet * @param index offset in the packet @@ -780,19 +619,24 @@ static inline uint8_t _mdns_append_string(uint8_t * packet, uint16_t * index, co static uint16_t _mdns_append_fqdn(uint8_t * packet, uint16_t * index, const char * strings[], uint8_t count) { if (!count) { + //empty string so terminate return _mdns_append_u8(packet, index, 0); } mdns_name_t name; static char buf[MDNS_NAME_BUF_LEN]; uint8_t len = strlen(strings[0]); + //try to find first the string length in the packet (if it exists) uint8_t * len_location = (uint8_t *)memchr(packet, (char)len, *index); while (len_location) { - if (memcmp(len_location + 1, strings[0], len)) { //not continuing with our string + //check if the string after len_location is the string that we are looking for + if (memcmp(len_location+1, strings[0], len)) { //not continuing with our string search_next: - len_location = (uint8_t *)memchr(len_location + 1, (char)len, *index - (len_location + 1 - packet)); + //try and find the length byte further in the packet + len_location = (uint8_t *)memchr(len_location+1, (char)len, *index - (len_location+1 - packet)); continue; } - //read string into name and compare + //seems that we might have found the string that we are looking for + //read the destination into name and compare name.parts = 0; name.sub = 0; name.host[0] = 0; @@ -801,13 +645,14 @@ search_next: name.domain[0] = 0; const uint8_t * content = _mdns_read_fqdn(packet, len_location, &name, buf); if (!content) { + //not a readable fqdn? return 0; } if (name.parts == count) { uint8_t i; - for (i = 0; i < count; i++) { - if (strcmp(strings[i], (const char *)&name + (i * (MDNS_NAME_BUF_LEN)))) { - //not our string + for (i=0; iinstance) ? service->instance - : (server->instance) ? server->instance - : server->hostname; - str[1] = service->service; - str[2] = service->proto; + str[0] = instance; + str[1] = service; + str[2] = proto; str[3] = MDNS_DEFAULT_DOMAIN; part_length = _mdns_append_fqdn(packet, index, str + 1, 3); @@ -859,7 +705,7 @@ static uint16_t _mdns_append_ptr_record(uint8_t * packet, uint16_t * index, mdns } record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, MDNS_ANSWER_PTR_TTL); + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, bye?0:MDNS_ANSWER_PTR_TTL); if (!part_length) { return 0; } @@ -885,7 +731,7 @@ static uint16_t _mdns_append_ptr_record(uint8_t * packet, uint16_t * index, mdns * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_sdptr_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, mdns_service_t * service) +static uint16_t _mdns_append_sdptr_record(uint8_t * packet, uint16_t * index, mdns_service_t * service, bool flush, bool bye) { const char * str[3]; const char * sd_str[4]; @@ -905,7 +751,7 @@ static uint16_t _mdns_append_sdptr_record(uint8_t * packet, uint16_t * index, md record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, MDNS_ANSWER_PTR_TTL); + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, flush, MDNS_ANSWER_PTR_TTL); if (!part_length) { return 0; } @@ -931,15 +777,15 @@ static uint16_t _mdns_append_sdptr_record(uint8_t * packet, uint16_t * index, md * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, mdns_service_t * service) +static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns_service_t * service, bool flush, bool bye) { const char * str[4]; uint16_t record_length = 0; uint8_t part_length; - str[0] = (service->instance) ? service->instance - : (server->instance) ? server->instance - : server->hostname; + str[0] = (service->instance)?service->instance + :(_mdns_server->instance)?_mdns_server->instance + :_mdns_server->hostname; str[1] = service->service; str[2] = service->proto; str[3] = MDNS_DEFAULT_DOMAIN; @@ -950,26 +796,33 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns } record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_TXT, MDNS_ANSWER_TXT_TTL); + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_TXT, flush, bye?0:MDNS_ANSWER_TXT_TTL); if (!part_length) { return 0; } record_length += part_length; uint16_t data_len_location = *index - 2; - uint16_t data_len = 0; - if (service->txt_num_items) { - uint8_t len = service->txt_num_items; - const char ** txt = service->txt; - uint8_t i, l; - for (i = 0; i < len; i++) { - l = _mdns_append_string(packet, index, txt[i]); + uint16_t data_len = 1; + + char * tmp; + mdns_txt_linked_item_t * txt = service->txt; + while (txt) { + tmp = (char *)malloc(2 + strlen(txt->key) + strlen(txt->value)); + if (tmp) { + sprintf(tmp, "%s=%s", txt->key, txt->value); + uint8_t l = _mdns_append_string(packet, index, tmp); + free(tmp); if (!l) { return 0; } data_len += l; } + txt = txt->next; } + + packet[*index] = 0; + *index = *index + 1; _mdns_set_u16(packet, data_len_location, data_len); record_length += data_len; return record_length; @@ -985,15 +838,15 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, mdns_service_t * service) +static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns_service_t * service, bool flush, bool bye) { const char * str[4]; uint16_t record_length = 0; uint8_t part_length; - str[0] = (service->instance) ? service->instance - : (server->instance) ? server->instance - : server->hostname; + str[0] = (service->instance)?service->instance + :(_mdns_server->instance)?_mdns_server->instance + :_mdns_server->hostname; str[1] = service->service; str[2] = service->proto; str[3] = MDNS_DEFAULT_DOMAIN; @@ -1004,7 +857,7 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns } record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_SRV, MDNS_ANSWER_SRV_TTL); + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_SRV, flush, bye?0:MDNS_ANSWER_SRV_TTL); if (!part_length) { return 0; } @@ -1020,7 +873,7 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns return 0; } - str[0] = server->hostname; + str[0] = _mdns_server->hostname; str[1] = MDNS_DEFAULT_DOMAIN; part_length = _mdns_append_fqdn(packet, index, str, 2); if (!part_length) { @@ -1042,13 +895,13 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, uint32_t ip) +static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, uint32_t ip, bool flush, bool bye) { const char * str[2]; uint16_t record_length = 0; uint8_t part_length; - str[0] = server->hostname; + str[0] = _mdns_server->hostname; str[1] = MDNS_DEFAULT_DOMAIN; part_length = _mdns_append_fqdn(packet, index, str, 2); @@ -1057,7 +910,7 @@ static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, mdns_s } record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_A, MDNS_ANSWER_A_TTL); + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_A, flush, bye?0:MDNS_ANSWER_A_TTL); if (!part_length) { return 0; } @@ -1083,18 +936,17 @@ static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, mdns_s * * @param packet MDNS packet * @param index offset in the packet - * @param server the server * @param ipv6 the IPv6 address to add * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, mdns_server_t * server, uint8_t * ipv6) +static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, uint8_t * ipv6, bool flush, bool bye) { const char * str[2]; uint16_t record_length = 0; uint8_t part_length; - str[0] = server->hostname; + str[0] = _mdns_server->hostname; str[1] = MDNS_DEFAULT_DOMAIN; part_length = _mdns_append_fqdn(packet, index, str, 2); @@ -1103,7 +955,7 @@ static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, mdn } record_length += part_length; - part_length = _mdns_append_type(packet, index, MDNS_ANSWER_AAAA, MDNS_ANSWER_AAAA_TTL); + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_AAAA, flush, bye?0:MDNS_ANSWER_AAAA_TTL); if (!part_length) { return 0; } @@ -1124,194 +976,1051 @@ static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, mdn } /** - * @brief sends all collected answers - * - * @param server the server - * @param answers linked list of answers + * @brief Append question to packet */ -static void _mdns_send_answers(mdns_server_t * server, mdns_answer_item_t * answers) +static uint16_t _mdns_append_question(uint8_t * packet, uint16_t * index, mdns_out_question_t * q) +{ + const char * str[4]; + uint8_t str_index = 0; + uint8_t part_length; + if (q->host) { + str[str_index++] = q->host; + } + if (q->service) { + str[str_index++] = q->service; + } + if (q->proto) { + str[str_index++] = q->proto; + } + if (q->domain) { + str[str_index++] = q->domain; + } + + part_length = _mdns_append_fqdn(packet, index, str, str_index); + if (!part_length) { + return 0; + } + + part_length += _mdns_append_u16(packet, index, q->type); + part_length += _mdns_append_u16(packet, index, q->unicast?0x8001:0x0001); + return part_length; +} + +/** + * @brief Helper to get either ETH or STA if the other is provided + * Used when two interfaces are on the same subnet + */ +static tcpip_adapter_if_t _mdns_get_other_if (tcpip_adapter_if_t tcpip_if) +{ + if (tcpip_if == TCPIP_ADAPTER_IF_STA) { + return TCPIP_ADAPTER_IF_ETH; + } else if (tcpip_if == TCPIP_ADAPTER_IF_ETH) { + return TCPIP_ADAPTER_IF_STA; + } + return TCPIP_ADAPTER_IF_MAX; +} + +/** + * @brief Check if interface is duplicate (two interfaces on the same subnet) + */ +static bool _mdns_if_is_dup(tcpip_adapter_if_t tcpip_if) +{ + tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); + if (other_if == TCPIP_ADAPTER_IF_MAX) { + return false; + } + if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP + || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state == PCB_DUP + || _mdns_server->interfaces[other_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP + || _mdns_server->interfaces[other_if].pcbs[MDNS_IP_PROTOCOL_V6].state == PCB_DUP + ) { + return true; + } + return false; +} + +/** + * @brief Check if IPv6 address is NULL + */ +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++) { + if (data[i]) { + return false; + } + } + return true; +} + +/** + * @brief Append answer to packet + * + * @return number of answers added to the packet + */ +static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_answer_t * answer, tcpip_adapter_if_t tcpip_if) +{ + if (answer->type == MDNS_TYPE_PTR) { + + if (answer->service) { + return _mdns_append_ptr_record(packet, index, + (answer->service->instance)?answer->service->instance + :(_mdns_server->instance)?_mdns_server->instance + :_mdns_server->hostname, + answer->service->service, answer->service->proto, + answer->flush, answer->bye) > 0; + } else { + return _mdns_append_ptr_record(packet, index, + answer->custom_instance, answer->custom_service, answer->custom_proto, + answer->flush, answer->bye) > 0; + } + } else if (answer->type == MDNS_TYPE_SRV) { + return _mdns_append_srv_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + } else if (answer->type == MDNS_TYPE_TXT) { + return _mdns_append_txt_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + } else if (answer->type == MDNS_TYPE_SDPTR) { + return _mdns_append_sdptr_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + } else if (answer->type == MDNS_TYPE_A) { + tcpip_adapter_ip_info_t if_ip_info; + if (!_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state != PCB_DUP) { + return 0; + } + if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info)) { + return 0; + } + if (_mdns_append_a_record(packet, index, if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { + return 0; + } + if (!_mdns_if_is_dup(tcpip_if)) { + return 1; + } + tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); + if (tcpip_adapter_get_ip_info(other_if, &if_ip_info)) { + return 1; + } + if (_mdns_append_a_record(packet, index, if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { + return 2; + } + return 1; + } else if (answer->type == MDNS_TYPE_AAAA) { + struct ip6_addr if_ip6; + if (!_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state != PCB_DUP) { + return 0; + } + if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &if_ip6)) { + return 0; + } + if (_ipv6_address_is_zero(if_ip6)) { + return 0; + } + if (_mdns_append_aaaa_record(packet, index, (uint8_t*)if_ip6.addr, answer->flush, answer->bye) <= 0) { + return 0; + } + if (!_mdns_if_is_dup(tcpip_if)) { + return 1; + } + tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); + if (tcpip_adapter_get_ip6_linklocal(other_if, &if_ip6)) { + return 1; + } + if (_mdns_append_aaaa_record(packet, index, (uint8_t*)if_ip6.addr, answer->flush, answer->bye) > 0) { + return 2; + } + return 1; + } + return 0; +} + +/** + * @brief sends a packet + * + * @param p the packet + */ +static void _mdns_dispatch_tx_packet(mdns_tx_packet_t * p) { - bool send_ip = false; static uint8_t packet[MDNS_MAX_PACKET_SIZE]; uint16_t index = MDNS_HEAD_LEN; - uint8_t answer_count = 0; - memset(packet, 0, MDNS_HEAD_LEN); + mdns_out_question_t * q; + mdns_out_answer_t * a; + uint8_t count; - _mdns_set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, MDNS_FLAGS_AUTHORITATIVE); + _mdns_set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, p->flags); - while (answers) { - if (answers->answer & MDNS_ANSWER_A) { - answers->answer &= ~MDNS_ANSWER_A; - send_ip = true; + count = 0; + q = p->questions; + while (q) { + if (_mdns_append_question(packet, &index, q)) { + count++; } - if (answers->service) { - - if (answers->answer & MDNS_ANSWER_PTR) { - if (!_mdns_append_ptr_record(packet, &index, server, answers->service)) { - return; - } - answer_count += 1; - } - - if (answers->answer & MDNS_ANSWER_TXT) { - if (!_mdns_append_txt_record(packet, &index, server, answers->service)) { - return; - } - answer_count += 1; - } - - if (answers->answer & MDNS_ANSWER_SRV) { - if (!_mdns_append_srv_record(packet, &index, server, answers->service)) { - return; - } - answer_count += 1; - } - - if (answers->answer & MDNS_ANSWER_SDPTR) { - if (!_mdns_append_sdptr_record(packet, &index, server, answers->service)) { - return; - } - answer_count += 1; - } - } - mdns_answer_item_t * a = answers; - answers = answers->next; - free(a); + q = q->next; } - if (send_ip) { - tcpip_adapter_ip_info_t if_ip_info; - tcpip_adapter_get_ip_info(server->tcpip_if, &if_ip_info); + _mdns_set_u16(packet, MDNS_HEAD_QUESTIONS_OFFSET, count); - if (!_mdns_append_a_record(packet, &index, server, if_ip_info.ip.addr)) { - return; - } - answer_count += 1; - - //add ipv6 if available - struct ip6_addr if_ip6; - if (!tcpip_adapter_get_ip6_linklocal(server->tcpip_if, &if_ip6)) { - uint8_t * v6addr = (uint8_t*)if_ip6.addr; - //check if not 0 - int i; - for (i = 0; i < sizeof(ip6_addr_t); i++) { - if (v6addr[i]) { - break; - } - } - if (i < sizeof(ip6_addr_t)) { - if (!_mdns_append_aaaa_record(packet, &index, server, v6addr)) { - return; - } - answer_count += 1; - } - } + count = 0; + a = p->answers; + while (a) { + count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + a = a->next; } + _mdns_set_u16(packet, MDNS_HEAD_ANSWERS_OFFSET, count); - _mdns_set_u16(packet, MDNS_HEAD_ANSWERS_OFFSET, answer_count); - _mdns_server_write(server, packet, index); + count = 0; + a = p->servers; + while (a) { + count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + a = a->next; + } + _mdns_set_u16(packet, MDNS_HEAD_SERVERS_OFFSET, count); + + count = 0; + a = p->additional; + while (a) { + count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + a = a->next; + } + _mdns_set_u16(packet, MDNS_HEAD_ADDITIONAL_OFFSET, count); + +#ifdef MDNS_ENABLE_DEBUG + _mdns_dbg_printf("\nTX[%u][%u]: ", p->tcpip_if, p->ip_protocol); + if (p->dst.type == IPADDR_TYPE_V4) { + _mdns_dbg_printf("To: " IPSTR ":%u, ", IP2STR(&p->dst.u_addr.ip4), p->port); + } else { + _mdns_dbg_printf("To: " IPV6STR ":%u, ", IPV62STR(p->dst.u_addr.ip6), p->port); + } + mdns_debug_packet(packet, index); +#endif + + _udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); } /** - * @brief appends search result from query + * @brief frees a packet * - * @param server the server - * @param r the temporary result to copy + * @param packet the packet */ -static void _mdns_add_result(mdns_server_t * server, mdns_result_temp_t * r) +static void _mdns_free_tx_packet(mdns_tx_packet_t * packet) { - mdns_result_t * n = (mdns_result_t *)malloc(sizeof(mdns_result_t)); - if (!n) { + if (!packet) { return; } - n->priority = r->priority; - n->weight = r->weight; - n->port = r->port; - n->addr.addr = r->addr; - - size_t hlen = strlen(r->host); - if (hlen) { - n->host = strdup(r->host); - if (!n->host) { - free(n); - return; - } - } else { - n->host = NULL; - } - - size_t ilen = strlen(r->instance); - if (ilen) { - n->instance = strdup(r->instance); - if (!n->instance) { - free((char *)n->host); - free(n); - return; - } - } else { - n->instance = NULL; - } - - size_t tlen = strlen(r->txt); - if (tlen) { - n->txt = strdup(r->txt); - if (!n->txt) { - free((char *)n->host); - free((char *)n->instance); - free(n); - return; - } - } else { - n->txt = NULL; - } - - memcpy((uint8_t *)n->addrv6.addr, r->addrv6, sizeof(ip6_addr_t)); - - mdns_result_t * o = server->search.results; - server->search.results = n; - n->next = o; + queueFree(mdns_out_question_t, packet->questions); + queueFree(mdns_out_answer_t, packet->answers); + queueFree(mdns_out_answer_t, packet->servers); + queueFree(mdns_out_answer_t, packet->additional); + free(packet); } /** - * @brief finds service from given service type - * @param server the server - * @param service service type to match - * @param proto proto to match + * @brief schedules a packet to be sent after given milliseconds * - * @return the service item if found or NULL on error + * @param packet the packet + * @param ms_after number of milliseconds after which the packet should be dispatched */ -static mdns_srv_item_t * _mdns_get_service_item(mdns_server_t * server, const char * service, const char * proto) +static void _mdns_schedule_tx_packet(mdns_tx_packet_t * packet, uint32_t ms_after) { - mdns_srv_item_t * s = server->services; - while (s) { - if (!strcmp(s->service->service, service) && !strcmp(s->service->proto, proto)) { - return s; + if (!packet) { + return; + } + packet->send_at = (xTaskGetTickCount() * portTICK_PERIOD_MS) + ms_after; + packet->next = NULL; + if (!_mdns_server->tx_queue_head || _mdns_server->tx_queue_head->send_at > packet->send_at) { + packet->next = _mdns_server->tx_queue_head; + _mdns_server->tx_queue_head = packet; + return; + } + mdns_tx_packet_t * q = _mdns_server->tx_queue_head; + while (q->next && q->next->send_at <= packet->send_at) { + q = q->next; + } + packet->next = q->next; + q->next = packet; +} + +/** + * @brief free all packets scheduled for sending + */ +static void _mdns_clear_tx_queue_head() +{ + mdns_tx_packet_t * q; + while (_mdns_server->tx_queue_head) { + q = _mdns_server->tx_queue_head; + _mdns_server->tx_queue_head = _mdns_server->tx_queue_head->next; + _mdns_free_tx_packet(q); + } +} + +/** + * @brief clear packets scheduled for sending on a specific interface + * + * @param tcpip_if the interface + * @param ip_protocol pcb type V4/V6 + */ +static void _mdns_clear_pcb_tx_queue_head(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t * q, * p; + while (_mdns_server->tx_queue_head && _mdns_server->tx_queue_head->tcpip_if == tcpip_if && _mdns_server->tx_queue_head->ip_protocol == ip_protocol) { + q = _mdns_server->tx_queue_head; + _mdns_server->tx_queue_head = _mdns_server->tx_queue_head->next; + _mdns_free_tx_packet(q); + } + if (_mdns_server->tx_queue_head) { + q = _mdns_server->tx_queue_head; + while (q->next) { + if (q->next->tcpip_if == tcpip_if && q->next->ip_protocol == ip_protocol) { + p = q->next; + q->next = p->next; + _mdns_free_tx_packet(p); + } else { + q = q->next; + } } - s = s->next; + } +} + +/** + * @brief get the next packet scheduled for sending on a specific interface + * + * @param tcpip_if the interface + * @param ip_protocol pcb type V4/V6 + */ +static mdns_tx_packet_t * _mdns_get_next_pcb_packet(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t * q = _mdns_server->tx_queue_head; + while (q) { + if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol) { + return q; + } + q = q->next; } return NULL; } +/** + * @brief Find, remove and free answer from the scheduled packets + */ +static void _mdns_remove_scheduled_answer(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t * service) +{ + mdns_tx_packet_t * q = _mdns_server->tx_queue_head; + while (q) { + if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol && q->distributed) { + mdns_out_answer_t * a = q->answers; + if (a->type == type && a->service == service->service) { + q->answers = q->answers->next; + free(a); + } else { + while (a->next) { + if (a->next->type == type && a->next->service == service->service) { + mdns_out_answer_t * b = a->next; + a->next = b->next; + free(b); + break; + } + a = a->next; + } + } + } + q = q->next; + } +} + +/** + * @brief Remove and free answer from answer list (destination) + */ +static void _mdns_dealloc_answer(mdns_out_answer_t ** destnation, uint16_t type, mdns_srv_item_t * service) +{ + mdns_out_answer_t * d = *destnation; + if (!d) { + return; + } + if (d->type == type && d->service == service->service) { + *destnation = d->next; + free(d); + return; + } + while (d->next) { + mdns_out_answer_t * a = d->next; + if (a->type == type && a->service == service->service) { + d->next = a->next; + free(a); + return; + } + d = d->next; + } +} + +/** + * @brief Allocate new answer and add it to answer list (destination) + */ +static bool _mdns_alloc_answer(mdns_out_answer_t ** destnation, uint16_t type, mdns_service_t * service, bool flush, bool bye) +{ + mdns_out_answer_t * d = *destnation; + while (d) { + if (d->type == type && d->service == service) { + return true; + } + d = d->next; + } + + mdns_out_answer_t * a = (mdns_out_answer_t *)malloc(sizeof(mdns_out_answer_t)); + if (!a) { + return false; + } + a->type = type; + a->service = service; + a->bye = bye; + a->flush = flush; + a->next = NULL; + queueToEnd(mdns_out_answer_t, *destnation, a); + return true; +} + +/** + * @brief Allocate new packet for sending + */ +static mdns_tx_packet_t * _mdns_alloc_packet_default(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t * packet = (mdns_tx_packet_t*)malloc(sizeof(mdns_tx_packet_t)); + if (!packet) { + return NULL; + } + memset((uint8_t*)packet, 0, sizeof(mdns_tx_packet_t)); + packet->tcpip_if = tcpip_if; + packet->ip_protocol = ip_protocol; + packet->port = MDNS_SERVICE_PORT; + if (ip_protocol == MDNS_IP_PROTOCOL_V4) { + IP_ADDR4(&packet->dst, 224, 0, 0, 251); + } else { + ip_addr_t addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); + memcpy(&packet->dst, &addr, sizeof(ip_addr_t)); + } + return packet; +} + +/** + * @brief Create answer packet to questions from parsed packet + */ +static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed_packet) +{ + if (!parsed_packet->questions) { + return; + } + bool send_flush = parsed_packet->src_port == MDNS_SERVICE_PORT; + bool unicast = false; + bool shared = false; + mdns_tx_packet_t * packet = _mdns_alloc_packet_default(parsed_packet->tcpip_if, parsed_packet->ip_protocol); + if (!packet) { + return; + } + packet->flags = MDNS_FLAGS_AUTHORITATIVE; + packet->distributed = parsed_packet->distributed; + + mdns_parsed_question_t * q = parsed_packet->questions; + while (q) { + mdns_srv_item_t * service = NULL; + if (q->service && q->proto) { + service = _mdns_get_service_item(q->service, q->proto); + if (!service) { + continue; + } + } + if (q->unicast) { + unicast = true; + } + if (service) { + if (q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_ANY) { + if (q->type == MDNS_TYPE_PTR) { + shared = true; + } + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service->service, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service->service, send_flush, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service->service, send_flush, false) + || !_mdns_alloc_answer(shared?&packet->additional:&packet->answers, MDNS_TYPE_A, NULL, send_flush, false) + || !_mdns_alloc_answer(shared?&packet->additional:&packet->answers, MDNS_TYPE_AAAA, NULL, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } + } else if (q->type == MDNS_TYPE_SRV) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service->service, send_flush, false) + || !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_A, NULL, send_flush, false) + || !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_AAAA, NULL, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } + } else if (q->type == MDNS_TYPE_TXT) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service->service, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } + } else if (q->type == MDNS_TYPE_SDPTR) { + shared = true; + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service->service, false, false)) { + _mdns_free_tx_packet(packet); + return; + } + } + } else { + if (q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, send_flush, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } + } else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } + } + q = q->next; + } + if (unicast || !send_flush) { + memcpy(&packet->dst, &parsed_packet->src, sizeof(ip_addr_t)); + packet->port = parsed_packet->src_port; + } + + static uint8_t share_step = 0; + if (shared) { + _mdns_schedule_tx_packet(packet, 25 + (share_step * 25)); + share_step = (share_step + 1) & 0x03; + } else { + _mdns_dispatch_tx_packet(packet); + _mdns_free_tx_packet(packet); + } +} + +/** + * @brief Check if question is already in the list + */ +static bool _mdns_question_exists(mdns_out_question_t * needle, mdns_out_question_t * haystack) +{ + while (haystack) { + if (haystack->type == needle->type + && haystack->host == needle->host + && haystack->service == needle->service + && haystack->proto == needle->proto) { + return true; + } + haystack = haystack->next; + } + return false; +} + +/** + * @brief Create probe packet for particular services on particular PCB + */ +static mdns_tx_packet_t * _mdns_create_probe_packet(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t * services[], size_t len, bool first, bool include_ip) +{ + mdns_tx_packet_t * packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return NULL; + } + + size_t i; + for (i=0; inext = NULL; + q->unicast = first; + q->type = MDNS_TYPE_ANY; + q->host = (services[i]->service->instance)?services[i]->service->instance + :(_mdns_server->instance)?_mdns_server->instance + :_mdns_server->hostname; + q->service = services[i]->service->service; + q->proto = services[i]->service->proto; + q->domain = MDNS_DEFAULT_DOMAIN; + if (_mdns_question_exists(q, packet->questions)) { + free(q); + } else { + queueToEnd(mdns_out_question_t, packet->questions, q); + } + + if (!_mdns_alloc_answer(&packet->servers, MDNS_TYPE_SRV, services[i]->service, false, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + + if (include_ip) { + mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); + if (!q) { + _mdns_free_tx_packet(packet); + return NULL; + } + q->next = NULL; + q->unicast = first; + q->type = MDNS_TYPE_ANY; + q->host = _mdns_server->hostname; + q->service = NULL; + q->proto = NULL; + q->domain = MDNS_DEFAULT_DOMAIN; + if (_mdns_question_exists(q, packet->questions)) { + free(q); + } else { + queueToEnd(mdns_out_question_t, packet->questions, q); + } + + if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) { + if (!_mdns_alloc_answer(&packet->servers, MDNS_TYPE_A, NULL, false, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + + if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) { + if (!_mdns_alloc_answer(&packet->servers, MDNS_TYPE_AAAA, NULL, false, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + } + + return packet; +} + +/** + * @brief Create announce packet for particular services on particular PCB + */ +static mdns_tx_packet_t * _mdns_create_announce_packet(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t * services[], size_t len, bool include_ip) +{ + mdns_tx_packet_t * packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return NULL; + } + packet->flags = MDNS_FLAGS_AUTHORITATIVE; + + uint8_t i; + for (i=0; ianswers, MDNS_TYPE_SDPTR, services[i]->service, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, services[i]->service, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, services[i]->service, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + if (include_ip) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + return packet; +} + +/** + * @brief Convert probe packet to announce + */ +static mdns_tx_packet_t * _mdns_create_announce_from_probe(mdns_tx_packet_t * probe) +{ + + mdns_tx_packet_t * packet = _mdns_alloc_packet_default(probe->tcpip_if, probe->ip_protocol); + if (!packet) { + return NULL; + } + packet->flags = MDNS_FLAGS_AUTHORITATIVE; + + mdns_out_answer_t * s = probe->servers; + while (s) { + if (s->type == MDNS_TYPE_SRV) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, s->service, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, s->service, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, s->service, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, s->service, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + + } else if (s->type == MDNS_TYPE_A || s->type == MDNS_TYPE_AAAA) { + if (!_mdns_alloc_answer(&packet->answers, s->type, NULL, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + + s = s->next; + } + return packet; +} + +/** + * @brief Send by for particular services on particular PCB + */ +static void _mdns_pcb_send_bye(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool include_ip) +{ + mdns_tx_packet_t * packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return; + } + size_t i; + for (i=0; ianswers, MDNS_TYPE_PTR, services[i]->service, true, true)) { + _mdns_free_tx_packet(packet); + return; + } + } + if (include_ip && (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, true, true) || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, true, true))) { + _mdns_free_tx_packet(packet); + return; + } + _mdns_dispatch_tx_packet(packet); + _mdns_free_tx_packet(packet); +} + +/** + * @brief Send probe for particular services on particular PCB + */ +static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) +{ + mdns_pcb_t * pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; + size_t services_final_len = len; + + _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); + + if (!_mdns_server->hostname || !_mdns_server->hostname[0]) { + pcb->state = PCB_RUNNING; + return; + } + + if (PCB_STATE_IS_PROBING(pcb)) { + services_final_len += pcb->probe_services_len; + } + mdns_srv_item_t ** _services = NULL; + if (services_final_len) { + _services = (mdns_srv_item_t **)malloc(sizeof(mdns_srv_item_t *) * services_final_len); + if (!_services) { + return; + } + + size_t i; + for (i=0; iprobe_services) { + for (i=0; iprobe_services_len; i++) { + _services[len+i] = pcb->probe_services[i]; + } + free(pcb->probe_services); + } + } + + probe_ip = pcb->probe_ip || probe_ip; + + pcb->probe_ip = false; + pcb->probe_services = NULL; + pcb->probe_services_len = 0; + pcb->probe_running = false; + + mdns_tx_packet_t * packet = _mdns_create_probe_packet(tcpip_if, ip_protocol, _services, services_final_len, true, probe_ip); + if (!packet) { + free(_services); + return; + } + + pcb->probe_ip = probe_ip; + pcb->probe_services = _services; + pcb->probe_services_len = services_final_len; + pcb->probe_running = true; + _mdns_schedule_tx_packet(packet, ((pcb->failed_probes > 5)?1000:120) + (esp_random() & 0x7F)); + pcb->state = PCB_PROBE_1; +} + +/** + * @brief Restart the responder on particular PCB + */ +static void _mdns_restart_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + size_t srv_count = 0; + mdns_srv_item_t * a = _mdns_server->services; + while (a) { + srv_count++; + a = a->next; + } + mdns_srv_item_t * services[srv_count]; + size_t i = 0; + a = _mdns_server->services; + while (a) { + services[i++] = a; + a = a->next; + } + _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, srv_count, true); +} + +/** + * @brief Send by for particular services + */ +static void _mdns_send_bye(mdns_srv_item_t ** services, size_t len, bool include_ip) +{ + uint8_t i, j; + if (!_mdns_server->hostname || !_mdns_server->hostname[0]) { + return; + } + + for (i=0; iinterfaces[i].pcbs[j].pcb && _mdns_server->interfaces[i].pcbs[j].state == PCB_RUNNING) { + _mdns_pcb_send_bye((tcpip_adapter_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); + } + } + } +} + +/** + * @brief Send announcement on particular PCB + */ +static void _mdns_announce_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool include_ip) +{ + mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; + size_t i; + if (_pcb->pcb) { + if (PCB_STATE_IS_PROBING(_pcb)) { + _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, len, include_ip); + } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { + mdns_tx_packet_t * p = _mdns_get_next_pcb_packet(tcpip_if, ip_protocol); + if (p) { + for (i=0; ianswers, MDNS_TYPE_SDPTR, services[i]->service, false, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_PTR, services[i]->service, false, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_SRV, services[i]->service, true, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_TXT, services[i]->service, true, false)) { + break; + } + } + if (include_ip) { + _mdns_dealloc_answer(&p->additional, MDNS_TYPE_A, NULL); + _mdns_dealloc_answer(&p->additional, MDNS_TYPE_AAAA, NULL); + _mdns_alloc_answer(&p->answers, MDNS_TYPE_A, NULL, true, false); + _mdns_alloc_answer(&p->answers, MDNS_TYPE_AAAA, NULL, true, false); + } + _pcb->state = PCB_ANNOUNCE_1; + } + } else if (_pcb->state == PCB_RUNNING) { + + if (!_mdns_server->hostname || !_mdns_server->hostname[0]) { + return; + } + + _pcb->state = PCB_ANNOUNCE_1; + mdns_tx_packet_t * p = _mdns_create_announce_packet(tcpip_if, ip_protocol, services, len, include_ip); + if (p) { + _mdns_schedule_tx_packet(p, 0); + } + } + } +} + +/** + * @brief Send probe on all active PCBs + */ +static void _mdns_probe_all_pcbs(mdns_srv_item_t ** services, size_t len, bool probe_ip, bool clear_old_probe) +{ + uint8_t i, j; + for (i=0; iinterfaces[i].pcbs[j].pcb) { + mdns_pcb_t * _pcb = &_mdns_server->interfaces[i].pcbs[j]; + if (clear_old_probe) { + free(_pcb->probe_services); + _pcb->probe_services = NULL; + _pcb->probe_services_len = 0; + _pcb->probe_running = false; + } + _mdns_init_pcb_probe((tcpip_adapter_if_t)i, (mdns_ip_protocol_t)j, services, len, probe_ip); + } + } + } +} + +/** + * @brief Send announcement on all active PCBs + */ +static void _mdns_announce_all_pcbs(mdns_srv_item_t ** services, size_t len, bool include_ip) +{ + uint8_t i, j; + for (i=0; iservices; + while (a) { + if (!a->service->instance) { + srv_count++; + } + a = a->next; + } + if (!srv_count) { + return; + } + mdns_srv_item_t * services[srv_count]; + size_t i = 0; + a = _mdns_server->services; + while (a) { + if (!a->service->instance) { + services[i++] = a; + } + a = a->next; + } + _mdns_send_bye(services, srv_count, include_ip); +} + +/** + * @brief Stop the responder on all services without instance + */ +static void _mdns_send_bye_all_pcbs_no_instance() +{ + size_t srv_count = 0; + mdns_srv_item_t * a = _mdns_server->services; + while (a) { + if (!a->service->instance) { + srv_count++; + } + a = a->next; + } + if (!srv_count) { + return; + } + mdns_srv_item_t * services[srv_count]; + size_t i = 0; + a = _mdns_server->services; + while (a) { + if (!a->service->instance) { + services[i++] = a; + } + a = a->next; + } + _mdns_send_bye(services, srv_count, false); +} + +/** + * @brief Restart the responder on all services without instance + */ +static void _mdns_restart_all_pcbs_no_instance() +{ + size_t srv_count = 0; + mdns_srv_item_t * a = _mdns_server->services; + while (a) { + if (!a->service->instance) { + srv_count++; + } + a = a->next; + } + if (!srv_count) { + return; + } + mdns_srv_item_t * services[srv_count]; + size_t i = 0; + a = _mdns_server->services; + while (a) { + if (!a->service->instance) { + services[i++] = a; + } + a = a->next; + } + _mdns_probe_all_pcbs(services, srv_count, false, true); +} + +/** + * @brief Restart the responder on all active PCBs + */ +static void _mdns_restart_all_pcbs() +{ + _mdns_clear_tx_queue_head(); + size_t srv_count = 0; + mdns_srv_item_t * a = _mdns_server->services; + while (a) { + srv_count++; + a = a->next; + } + mdns_srv_item_t * services[srv_count]; + size_t l = 0; + a = _mdns_server->services; + while (a) { + services[l++] = a; + a = a->next; + } + + _mdns_probe_all_pcbs(services, srv_count, true, true); +} + + + +/** + * @brief creates/allocates new text item list + * @param num_items service number of txt items or 0 + * @param txt service txt items array or NULL + * + * @return pointer to the linked txt item list or NULL + */ +static mdns_txt_linked_item_t * _mdns_allocate_txt(size_t num_items, mdns_txt_item_t txt[]) +{ + mdns_txt_linked_item_t * new_txt = NULL; + size_t i = 0; + if (num_items) { + for (i=0; ikey = strdup(txt[i].key); + if (!new_item->key) { + free(new_item); + break; + } + new_item->value = strdup(txt[i].value); + if (!new_item->value) { + free((char *)new_item->key); + free(new_item); + break; + } + new_item->next = new_txt; + new_txt = new_item; + } + } + return new_txt; +} + /** * @brief creates/allocates new service * @param service service type * @param proto service proto * @param port service port + * @param instance service instance + * @param num_items service number of txt items or 0 + * @param txt service txt items array or NULL * * @return pointer to the service or NULL on error */ -static mdns_service_t * _mdns_create_service(const char * service, const char * proto, uint16_t port) +static mdns_service_t * _mdns_create_service(const char * service, const char * proto, uint16_t port, const char * instance, size_t num_items, mdns_txt_item_t txt[]) { mdns_service_t * s = (mdns_service_t *)malloc(sizeof(mdns_service_t)); if (!s) { return NULL; } + mdns_txt_linked_item_t * new_txt = _mdns_allocate_txt(num_items, txt); + if (num_items && new_txt == NULL) { + free(s); + return NULL; + } + s->priority = 0; s->weight = 0; - s->txt_num_items = 0; - s->instance = NULL; - s->txt = NULL; + s->instance = instance?strndup(instance, MDNS_NAME_BUF_LEN - 1):NULL; + s->txt = new_txt; s->port = port; s->service = strndup(service, MDNS_NAME_BUF_LEN - 1); @@ -1343,16 +2052,282 @@ static void _mdns_free_service(mdns_service_t * service) free((char *)service->instance); free((char *)service->service); free((char *)service->proto); - if (service->txt_num_items) { - uint8_t i; - for (i = 0; i < service->txt_num_items; i++) { - free((char *)service->txt[i]); - } + while (service->txt) { + mdns_txt_linked_item_t * s = service->txt; + service->txt = service->txt->next; + free((char *)s->key); + free((char *)s->value); + free(s); } free(service->txt); free(service); } + +/* + * Received Packet Handling + * */ + +/** + * @brief Detect SRV collision + */ +static int _mdns_check_srv_collision(mdns_service_t * service, uint16_t priority, uint16_t weight, uint16_t port, const char * host, const char * domain) +{ + size_t our_host_len = strlen(_mdns_server->hostname); + size_t our_len = 14 + our_host_len; + + size_t their_host_len = strlen(host); + size_t their_domain_len = strlen(domain); + size_t their_len = 9 + their_host_len + their_domain_len; + + if (their_len > our_len) { + return 1;//they win + } else if (their_len < our_len) { + return -1;//we win + } + + uint16_t our_index = 0; + uint8_t our_data[our_len]; + _mdns_append_u16(our_data, &our_index, service->priority); + _mdns_append_u16(our_data, &our_index, service->weight); + _mdns_append_u16(our_data, &our_index, service->port); + our_data[our_index++] = our_host_len; + memcpy(our_data + our_index, _mdns_server->hostname, our_host_len); + our_index += our_host_len; + our_data[our_index++] = 5; + memcpy(our_data + our_index, MDNS_DEFAULT_DOMAIN, 5); + our_index += 5; + our_data[our_index++] = 0; + + uint16_t their_index = 0; + uint8_t their_data[their_len]; + _mdns_append_u16(their_data, &their_index, priority); + _mdns_append_u16(their_data, &their_index, weight); + _mdns_append_u16(their_data, &their_index, port); + their_data[their_index++] = their_host_len; + memcpy(their_data + their_index, host, their_host_len); + their_index += their_host_len; + their_data[their_index++] = their_domain_len; + memcpy(their_data + their_index, domain, their_domain_len); + their_index += their_domain_len; + their_data[their_index++] = 0; + + int ret = memcmp(our_data, their_data, our_len); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + return 1;//they win + } + return 0;//same +} + +/** + * @brief Detect TXT collision + */ +static int _mdns_check_txt_collision(mdns_service_t * service, const uint8_t * data, size_t len) +{ + size_t data_len = 1; + if (len == 1 && service->txt) { + return -1;//we win + } else if (len > 1 && !service->txt) { + return 1;//they win + } else if (len == 1 && !service->txt) { + return 0;//same + } + + mdns_txt_linked_item_t * txt = service->txt; + while (txt) { + data_len += 2 + strlen(service->txt->key) + strlen(service->txt->value); + txt = txt->next; + } + + if (len > data_len) { + return 1;//they win + } else if (len < data_len) { + return -1;//we win + } + + uint8_t ours[len]; + uint16_t index = 0; + char * tmp; + + txt = service->txt; + while (txt) { + tmp = (char *)malloc(2 + strlen(txt->key) + strlen(txt->value)); + if (tmp) { + sprintf(tmp, "%s=%s", txt->key, txt->value); + _mdns_append_string(ours, &index, tmp); + free(tmp); + } + txt = txt->next; + } + + int ret = memcmp(ours, data, len); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + return 1;//they win + } + return 0;//same +} + +/** + * @brief Set interface as duplicate if another is found on the same subnet + */ +static void _mdns_dup_interface(tcpip_adapter_if_t tcpip_if) +{ + uint8_t i; + tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); + for (i=0; iinterfaces[other_if].pcbs[i].pcb) { + //stop this interface and mark as dup + if (_mdns_server->interfaces[tcpip_if].pcbs[i].pcb) { + _mdns_clear_pcb_tx_queue_head(tcpip_if, i); + _mdns_pcb_deinit(tcpip_if, i); + } + _mdns_server->interfaces[tcpip_if].pcbs[i].state = PCB_DUP; + _mdns_announce_pcb(other_if, i, NULL, 0, true); + } + } +} + +/** + * @brief Detect IPv4 address collision + */ +static int _mdns_check_a_collision(ip4_addr_t * ip, tcpip_adapter_if_t tcpip_if) +{ + tcpip_adapter_ip_info_t if_ip_info; + tcpip_adapter_ip_info_t other_ip_info; + if (!ip->addr) { + return 1;//denial! they win + } + if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info)) { + return 1;//they win + } + + int ret = memcmp((uint8_t*)&if_ip_info.ip.addr, (uint8_t*)&ip->addr, sizeof(ip4_addr_t)); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + //is it the other interface? + tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); + if (other_if == TCPIP_ADAPTER_IF_MAX) { + return 1;//AP interface! They win + } + if (tcpip_adapter_get_ip_info(other_if, &other_ip_info)) { + return 1;//IPv4 not active! They win + } + if (ip->addr != other_ip_info.ip.addr) { + return 1;//IPv4 not ours! They win + } + _mdns_dup_interface(tcpip_if); + return 2;//they win + } + return 0;//same +} + +/** + * @brief Detect IPv6 address collision + */ +static int _mdns_check_aaaa_collision(ip6_addr_t * ip, tcpip_adapter_if_t tcpip_if) +{ + struct ip6_addr if_ip6; + struct ip6_addr other_ip6; + if (_ipv6_address_is_zero(*ip)) { + return 1;//denial! they win + } + 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)); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + //is it the other interface? + tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); + if (other_if == TCPIP_ADAPTER_IF_MAX) { + return 1;//AP interface! They win + } + 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))) { + return 1;//IPv6 not ours! They win + } + _mdns_dup_interface(tcpip_if); + return 2;//they win + } + return 0;//same +} + +/** + * @brief Check if parsed name is discovery + */ +static bool _mdns_name_is_discovery(mdns_name_t * name, uint16_t type) +{ + return ( + (name->host && name->host[0] && !strcasecmp(name->host, "_services")) + && (name->service && name->service[0] && !strcasecmp(name->service, "_dns-sd")) + && (name->proto && name->proto[0] && !strcasecmp(name->proto, "_udp")) + && (name->domain && name->domain[0] && !strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN)) + && type == MDNS_TYPE_PTR + ); +} + +/** + * @brief Check if the parsed name is ours (matches service or host name) + */ +static bool _mdns_name_is_ours(mdns_name_t * name) +{ + //domain have to be "local" + if (!name->domain || !name->domain[0] || strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN)) { + return false; + } + + //if service and proto are empty, host must match out hostname + if ((!name->service || !name->service[0]) && (!name->proto || !name->proto[0])) { + if (name->host && name->host[0] && strcasecmp(name->host, _mdns_server->hostname) == 0) { + return true; + } + return false; + } + + //if service or proto is empty, name is invalid + if ((!name->service || !name->service[0]) || (!name->proto || !name->proto[0])) { + return false; + } + + //find the service + mdns_srv_item_t * service = _mdns_get_service_item(name->service, name->proto); + if (!service) { + return false; + } + + //if host is empty and we have service, we have success + if (!name->host || !name->host[0]) { + return true; + } + + //OK we have host in the name. find what is the instance of the service + const char * instance = service->service->instance; + if (instance == NULL) { + if (_mdns_server->instance && _mdns_server->instance[0]) { + instance = _mdns_server->instance; + } else if (_mdns_server->hostname && _mdns_server->hostname[0]) { + instance = _mdns_server->hostname; + } else { + return false; + } + } + + //compare the instance against the name + if (strcasecmp(name->host, instance) == 0) { + return true; + } + + return false; +} + /** * @brief read uint16_t from a packet * @param packet the packet @@ -1362,374 +2337,1928 @@ static void _mdns_free_service(mdns_service_t * service) */ static inline uint16_t _mdns_read_u16(const uint8_t * packet, uint16_t index) { - return (uint16_t)(packet[index]) << 8 | packet[index + 1]; + return (uint16_t)(packet[index]) << 8 | packet[index+1]; +} + +/** + * @brief read uint32_t from a packet + * @param packet the packet + * @param index index in the packet where the value starts + * + * @return the value + */ +static inline uint32_t _mdns_read_u32(const uint8_t * packet, uint16_t index) +{ + return (uint32_t)(packet[index]) << 24 | (uint32_t)(packet[index+1]) << 16 | (uint32_t)(packet[index+2]) << 8 | packet[index+3]; +} + +/** + * @brief reads and formats MDNS FQDN into mdns_name_t structure + * + * @param packet MDNS packet + * @param start Starting point of FQDN + * @param name mdns_name_t structure to populate + * + * @return the address after the parsed FQDN in the packet or NULL on error + */ +static const uint8_t * _mdns_parse_fqdn(const uint8_t * packet, const uint8_t * start, mdns_name_t * name) +{ + name->parts = 0; + name->sub = 0; + name->host[0] = 0; + name->service[0] = 0; + name->proto[0] = 0; + name->domain[0] = 0; + + static char buf[MDNS_NAME_BUF_LEN]; + + const uint8_t * next_data = (uint8_t*)_mdns_read_fqdn(packet, start, name, buf); + if (!next_data) { + return 0; + } + if (!name->parts) { + return next_data; + } + if (name->parts == 3) { + memmove((uint8_t*)name + (MDNS_NAME_BUF_LEN), (uint8_t*)name, 3*(MDNS_NAME_BUF_LEN)); + name->host[0] = 0; + } else if (name->parts == 2) { + memmove((uint8_t*)(name->domain), (uint8_t*)(name->service), (MDNS_NAME_BUF_LEN)); + name->service[0] = 0; + name->proto[0] = 0; + } + if (strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN) == 0 || strcasecmp(name->domain, "arpa") == 0) { + return next_data; + } + return 0; +} + +/** + * @brief Called from parser to check if question matches particular service + */ +static bool _mdns_question_matches(mdns_parsed_question_t * question, uint16_t type, mdns_srv_item_t * service) +{ + if (question->type != type) { + return false; + } + if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { + return true; + } else if (type == MDNS_TYPE_PTR || type == MDNS_TYPE_SDPTR) { + if (!strcasecmp(service->service->service, question->service) + && !strcasecmp(service->service->proto, question->proto) + && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { + return true; + } + } else if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { + const char * name = service->service->instance; + if (!name) { + name = _mdns_server->instance; + } + if (!name) { + name = _mdns_server->hostname; + } + if (!strcasecmp(name, question->host) + && !strcasecmp(service->service->service, question->service) + && !strcasecmp(service->service->proto, question->proto) + && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { + return true; + } + } + + return false; +} + +/** + * @brief Removes saved question from parsed data + */ +static void _mdns_remove_parsed_question(mdns_parsed_packet_t * parsed_packet, uint16_t type, mdns_srv_item_t * service) +{ + mdns_parsed_question_t * q = parsed_packet->questions; + + if (_mdns_question_matches(q, type, service)) { + parsed_packet->questions = q->next; + free(q->host); + free(q->service); + free(q->proto); + free(q->domain); + free(q); + return; + } + + while (q->next) { + mdns_parsed_question_t * p = q->next; + if (_mdns_question_matches(p, type, service)) { + q->next = p->next; + free(p->host); + free(p->service); + free(p->proto); + free(p->domain); + free(p); + return; + } + q = q->next; + } +} + +/** + * @brief Get number of items in TXT parsed data + */ +static int _mdns_txt_items_count_get(const uint8_t * data, size_t len) +{ + if (len == 1) { + return 0; + } + + int num_items = 0; + uint16_t i=0; + size_t partLen = 0; + + while (i < len) { + partLen = data[i++]; + if (!partLen) { + break; + } + if ((i+partLen) > len) { + return -1;//error + } + i+=partLen; + num_items++; + } + return num_items; +} + +/** + * @brief Get the length of TXT item's key name + */ +static int _mdns_txt_item_name_get_len(const uint8_t * data, size_t len) +{ + int i; + if (*data == '=') { + return -1; + } + for (i = 0; i < len; i++) { + if (data[i] == '=') { + return i; + } + } + return len; +} + +/** + * @brief Create TXT result array from parsed TXT data + */ +static void _mdns_result_txt_create(const uint8_t * data, size_t len, mdns_txt_item_t ** out_txt, size_t * out_count) +{ + *out_txt = NULL; + *out_count = 0; + uint16_t i=0, y; + size_t partLen = 0; + int num_items = _mdns_txt_items_count_get(data, len); + if (num_items < 0) { + return;//error + } + + if (!num_items) { + return; + } + + mdns_txt_item_t * txt = (mdns_txt_item_t *)malloc(sizeof(mdns_txt_item_t) * num_items); + memset(txt, 0, sizeof(mdns_txt_item_t) * num_items); + size_t txt_num = 0; + + while (i < len) { + partLen = data[i++]; + if (!partLen) { + break; + } + + if ((i+partLen) > len) { + goto handle_error;//error + } + + int name_len = _mdns_txt_item_name_get_len(data+i, partLen); + if (name_len < 0) {//invalid item (no name) + i += partLen; + continue; + } + char * key = (char *)malloc(name_len + 1); + if (!key) { + goto handle_error;//error + } + + mdns_txt_item_t * t = &txt[txt_num++]; + + memcpy(key, data + i, name_len); + key[name_len] = 0; + i += name_len + 1; + t->key = key; + + int value_len = partLen - name_len - 1; + if (value_len > 0) { + char * value = (char *)malloc(value_len + 1); + memcpy(value, data + i, value_len); + value[value_len] = 0; + i += value_len; + t->value = value; + } + } + + *out_txt = txt; + *out_count = txt_num; + return; + +handle_error : + for (y=0; ykey); + free((char *)t->value); + } + free(txt); +} + +/** + * @brief Duplicate string or return error + */ +static esp_err_t _mdns_strdup_check(char ** out, char * in) +{ + if (in && in[0]) { + *out = strdup(in); + if (!*out) { + return ESP_FAIL; + } + return ESP_OK; + } + *out = NULL; + return ESP_OK; } /** * @brief main packet parser * - * @param server the server - * @param data byte array holding the packet data - * @param len length of the byte array + * @param packet the packet */ -void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len) +void mdns_parse_packet(mdns_rx_packet_t * packet) { static mdns_name_t n; - static mdns_result_temp_t a; - + mdns_header_t header; + const uint8_t * data = (const uint8_t*)packet->pb->payload; + size_t len = packet->pb->len; const uint8_t * content = data + MDNS_HEAD_LEN; + bool do_not_reply = false; + mdns_search_once_t * search_result = NULL; + +#ifdef MDNS_ENABLE_DEBUG + _mdns_dbg_printf("\nRX[%u][%u]: ", packet->tcpip_if, (uint32_t)packet->ip_protocol); + if (packet->src.type == IPADDR_TYPE_V4) { + _mdns_dbg_printf("From: " IPSTR ":%u, To: " IPSTR ", ", IP2STR(&packet->src.u_addr.ip4), packet->src_port, IP2STR(&packet->dest.u_addr.ip4)); + } else { + _mdns_dbg_printf("From: " IPV6STR ":%u, To: " IPV6STR ", ", IPV62STR(packet->src.u_addr.ip6), packet->src_port, IPV62STR(packet->dest.u_addr.ip6)); + } + mdns_debug_packet(data, len); +#endif + + mdns_parsed_packet_t * parsed_packet = (mdns_parsed_packet_t *)malloc(sizeof(mdns_parsed_packet_t)); + if (!parsed_packet) { + return; + } + memset(parsed_packet, 0, sizeof(mdns_parsed_packet_t)); + mdns_name_t * name = &n; memset(name, 0, sizeof(mdns_name_t)); - uint16_t questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); - uint16_t answers = _mdns_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); - uint16_t additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); + header.id = _mdns_read_u16(data, MDNS_HEAD_ID_OFFSET); + header.flags.value = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); + header.questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); + header.answers = _mdns_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); + header.servers = _mdns_read_u16(data, MDNS_HEAD_SERVERS_OFFSET); + header.additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); - if (questions) { - uint8_t qs = questions; - mdns_answer_item_t * answer_items = NULL; + if (header.flags.value == MDNS_FLAGS_AUTHORITATIVE && packet->src_port != MDNS_SERVICE_PORT) { + free(parsed_packet); + return; + } + + parsed_packet->tcpip_if = packet->tcpip_if; + parsed_packet->ip_protocol = packet->ip_protocol; + parsed_packet->multicast = packet->multicast; + parsed_packet->authoritative = header.flags.value == MDNS_FLAGS_AUTHORITATIVE; + parsed_packet->distributed = header.flags.value == MDNS_FLAGS_DISTRIBUTED; + ip_addr_copy(parsed_packet->src, packet->src); + parsed_packet->src_port = packet->src_port; + + if (header.questions) { + uint8_t qs = header.questions; while (qs--) { content = _mdns_parse_fqdn(data, content, name); if (!content) { - answers = 0; - additional = 0; - break;//error + header.answers = 0; + header.additional = 0; + header.servers = 0; + goto clear_rx_packet;//error } uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t clas = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + bool unicast = !!(clas & 0x8000); + clas &= 0x7FFF; content = content + 4; - if (!name->service[0] || !name->proto[0]) { - if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA || type == MDNS_TYPE_ANY) {//send A + AAAA - if (name->host[0] && server->hostname && server->hostname[0] && !strcmp(name->host, server->hostname)) { - answer_items = _mdns_add_answer(answer_items, NULL, MDNS_ANSWER_A); + if (clas != 0x0001) {//bad class + continue; + } + + if (_mdns_name_is_discovery(name, type)) { + //service discovery + parsed_packet->discovery = true; + mdns_srv_item_t * a = _mdns_server->services; + while (a) { + mdns_parsed_question_t * question = (mdns_parsed_question_t *)malloc(sizeof(mdns_parsed_question_t)); + if (!question) { + goto clear_rx_packet; } - } - continue; - } + question->next = parsed_packet->questions; + parsed_packet->questions = question; - //is this a dns-sd service discovery meta query? - if (!strcmp(name->host, "_services") && !strcmp(name->service, "_dns-sd") && !strcmp(name->proto, "_udp") && !strcmp(name->domain, MDNS_DEFAULT_DOMAIN) && type == MDNS_TYPE_PTR) - { - //add answers for all services - mdns_srv_item_t * s = server->services; - while (s) { - if (s->service->service && s->service->proto) { - answer_items = _mdns_add_answer(answer_items, s->service, MDNS_ANSWER_SDPTR); + question->unicast = unicast; + question->type = MDNS_TYPE_SDPTR; + question->host = NULL; + question->service = strdup(a->service->service); + question->proto = strdup(a->service->proto); + question->domain = strdup(MDNS_DEFAULT_DOMAIN); + if (!question->service || !question->proto || !question->domain) { + goto clear_rx_packet; } - s = s->next; + a = a->next; } continue; + } else if (name->sub || !_mdns_name_is_ours(name)) { + continue; } - if (name->sub) { - continue; + if (type == MDNS_TYPE_ANY) { + parsed_packet->probe = true; } - mdns_srv_item_t * si = _mdns_get_service_item(server, name->service, name->proto); - if (!si) { - //service not found - continue; + mdns_parsed_question_t * question = (mdns_parsed_question_t *)malloc(sizeof(mdns_parsed_question_t)); + if (!question) { + goto clear_rx_packet; } + question->next = parsed_packet->questions; + parsed_packet->questions = question; - if (type == MDNS_TYPE_PTR) { - answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_ALL); - } else if (type == MDNS_TYPE_TXT) { - //match instance/host - const char * host = (si->service->instance) ? si->service->instance - : (server->instance) ? server->instance - : server->hostname; - if (!host || !host[0] || !name->host[0] || strcmp(name->host, host)) { - continue; - } - answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_TXT); - } else if (type == MDNS_TYPE_SRV) { - //match instance/host - const char * host = (si->service->instance) ? si->service->instance - : (server->instance) ? server->instance - : server->hostname; - if (!host || !host[0] || !name->host[0] || strcmp(name->host, host)) { - continue; - } - answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_SRV | MDNS_ANSWER_A); - } else if (type == MDNS_TYPE_ANY) {//send all - //match host - if (!name->host[0] || !server->hostname || !server->hostname[0] || strcmp(name->host, server->hostname)) { - answer_items = _mdns_add_answer(answer_items, si->service, MDNS_ANSWER_ALL); - } + question->unicast = unicast; + question->type = type; + if (_mdns_strdup_check(&(question->host), name->host) + || _mdns_strdup_check(&(question->service), name->service) + || _mdns_strdup_check(&(question->proto), name->proto) + || _mdns_strdup_check(&(question->domain), name->domain)) { + goto clear_rx_packet; } } - if (answer_items) { - _mdns_send_answers(server, answer_items); - } } - if (server->search.running && (answers || additional)) { - mdns_result_temp_t * answer = &a; - memset(answer, 0, sizeof(mdns_result_temp_t)); + if (header.questions && !parsed_packet->questions && !parsed_packet->discovery) { + goto clear_rx_packet; + } else if (header.answers || header.servers || header.additional) { + uint16_t recordIndex = 0; while (content < (data + len)) { + content = _mdns_parse_fqdn(data, content, name); if (!content) { - return;//error + goto clear_rx_packet;//error } + uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t clas = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + uint32_t ttl = _mdns_read_u32(content, MDNS_TTL_OFFSET); uint16_t data_len = _mdns_read_u16(content, MDNS_LEN_OFFSET); const uint8_t * data_ptr = content + MDNS_DATA_OFFSET; + clas &= 0x7FFF; content = data_ptr + data_len; if (content > (data + len)) { - return; + goto clear_rx_packet; + } + + bool discovery = false; + bool ours = false; + mdns_srv_item_t * service = NULL; + mdns_parsed_recort_type_t record_type = MDNS_ANSWER; + + if (recordIndex >= (header.answers + header.servers)) { + record_type = MDNS_EXTRA; + } else if (recordIndex >= (header.answers)) { + record_type = MDNS_NS; + } + recordIndex++; + + if (type == MDNS_TYPE_NSEC || type == MDNS_TYPE_OPT) { + //skip NSEC and OPT + continue; + } + + if (parsed_packet->discovery && _mdns_name_is_discovery(name, type)) { + discovery = true; + } else if (!name->sub && _mdns_name_is_ours(name)) { + ours = true; + if (name->service && name->service[0] && name->proto && name->proto[0]) { + service = _mdns_get_service_item(name->service, name->proto); + } + } else { + if (header.questions || !parsed_packet->authoritative || record_type == MDNS_NS) { + //skip this record + continue; + } + search_result = _mdns_search_find_from(_mdns_server->search_once, name, type, packet->tcpip_if, packet->ip_protocol); } if (type == MDNS_TYPE_PTR) { if (!_mdns_parse_fqdn(data, data_ptr, name)) { continue;//error } -#ifndef MDNS_TEST_MODE - if (server->search.host[0] || - (strcmp(name->service, server->search.service) != 0) || - (strcmp(name->proto, server->search.proto) != 0)) { - continue;//not searching for service or wrong service/proto - } -#endif - strlcpy(answer->instance, name->host, MDNS_NAME_BUF_LEN); - } else if (type == MDNS_TYPE_SRV) { -#ifndef MDNS_TEST_MODE - if (server->search.host[0] || - (strcmp(name->service, server->search.service) != 0) || - (strcmp(name->proto, server->search.proto) != 0)) { - continue;//not searching for service or wrong service/proto - } -#endif - if (answer->instance[0]) { - if (strcmp(answer->instance, name->host) != 0) { - continue;//instance name is not the same as the one in the PTR record + if (search_result) { + _mdns_search_result_add_ptr(search_result, name->host, packet->tcpip_if, packet->ip_protocol); + } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { + if (discovery) { + service = _mdns_get_service_item(name->service, name->proto); + _mdns_remove_parsed_question(parsed_packet, MDNS_TYPE_SDPTR, service); + } else if (parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, service); + } else { + //check if TTL is more than half of the full TTL value (4500) + if (ttl > 2250) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + } } - } else { - strlcpy(answer->instance, name->host, MDNS_NAME_BUF_LEN); } - //parse record value + } else if (type == MDNS_TYPE_SRV) { + mdns_result_t * result = NULL; + if (search_result && search_result->type == MDNS_TYPE_PTR) { + result = search_result->result; + while (result) { + if (packet->tcpip_if == result->tcpip_if + && packet->ip_protocol == result->ip_protocol + && result->instance_name && !strcmp(name->host, result->instance_name)) { + break; + } + result = result->next; + } + if (!result) { + result = _mdns_search_result_add_ptr(search_result, name->host, packet->tcpip_if, packet->ip_protocol); + if (!result) { + continue;//error + } + } + } + if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name)) { continue;//error } + uint16_t priority = _mdns_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); + uint16_t weight = _mdns_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); + uint16_t port = _mdns_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); - answer->ptr = 1; - answer->priority = _mdns_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); - answer->weight = _mdns_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); - answer->port = _mdns_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); - if (answer->host[0]) { - if (strcmp(answer->host, name->host) != 0) { - answer->addr = 0; - strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN); + if (search_result) { + if (search_result->type == MDNS_TYPE_PTR) { + result->port = port; + result->hostname = strdup(name->host); + } else { + _mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol); + } + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, service); + continue; + } else if (parsed_packet->distributed) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + continue; + } + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (clas > 1) { + col = 1; + } else if (!clas) { + col = -1; + } else { + col = _mdns_check_srv_collision(service->service, priority, weight, port, name->host, name->domain); + } + if (col && (parsed_packet->probe || parsed_packet->authoritative)) { + if (col > 0 || !port) { + do_not_reply = true; + if (_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; + if (service->service->instance) { + char * new_instance = _mdns_mangle_name((char *)service->service->instance); + if (new_instance) { + free((char *)service->service->instance); + service->service->instance = new_instance; + } + _mdns_probe_all_pcbs(&service, 1, false, false); + } else if (_mdns_server->instance) { + char * new_instance = _mdns_mangle_name((char *)_mdns_server->instance); + if (new_instance) { + free((char *)_mdns_server->instance); + _mdns_server->instance = new_instance; + } + _mdns_restart_all_pcbs_no_instance(); + } else { + char * new_host = _mdns_mangle_name((char *)_mdns_server->hostname); + if (new_host) { + free((char *)_mdns_server->hostname); + _mdns_server->hostname = new_host; + } + _mdns_restart_all_pcbs(); + } + } else { + _mdns_pcb_send_bye(packet->tcpip_if, packet->ip_protocol, &service, 1, false); + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, false); + } + } + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); } - } else { - strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN); } } else if (type == MDNS_TYPE_TXT) { - uint16_t i = 0, b = 0, y; - while (i < data_len) { - uint8_t partLen = data_ptr[i++]; - if ((i + partLen) > data_len) { - break;//error + if (search_result) { + mdns_txt_item_t * txt = NULL; + size_t txt_count = 0; + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_count); + if (!txt_count) { + continue; } - //check if partLen will fit in the buffer - if (partLen > (MDNS_TXT_MAX_LEN - b - 1)) { - break; + + mdns_result_t * result = NULL; + if (search_result->type == MDNS_TYPE_PTR) { + result = search_result->result; + while (result) { + if (packet->tcpip_if == result->tcpip_if + && packet->ip_protocol == result->ip_protocol + && result->instance_name && !strcmp(name->host, result->instance_name)) { + break; + } + result = result->next; + } + if (!result) { + result = _mdns_search_result_add_ptr(search_result, name->host, packet->tcpip_if, packet->ip_protocol); + if (!result) { + continue;//error + } + } + if (!result->txt) { + result->txt = txt; + result->txt_count = txt_count; + } + } else { + _mdns_search_result_add_txt(search_result, txt, txt_count, packet->tcpip_if, packet->ip_protocol); } - for (y = 0; y < partLen; y++) { - char d = data_ptr[i++]; - answer->txt[b++] = d; + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, service); + continue; } - if (i < data_len) { - answer->txt[b++] = '&'; + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (clas > 1) { + col = 1; + } else if (!clas) { + col = -1; + } else { + 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) { + do_not_reply = true; + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); + } else if (ttl > 2250 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); } } - answer->txt[b] = 0; - } else if (type == MDNS_TYPE_AAAA) { - if (server->search.host[0]) { -#ifndef MDNS_TEST_MODE - if (strcmp(name->host, server->search.host) != 0) { - continue;//wrong host + + } 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); + if (search_result) { + //check for more applicable searches (PTR & A/AAAA at the same time) + while (search_result) { + _mdns_search_result_add_ip(search_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol); + search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); + } + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, NULL); + continue; + } + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (clas > 1) { + col = 1; + } else if (!clas) { + col = -1; + } else { + col = _mdns_check_aaaa_collision(&(ip6.u_addr.ip6), packet->tcpip_if); + } + if (col == 2) { + goto clear_rx_packet; + } else if (col == 1) { + do_not_reply = true; + if (_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + if (col && (parsed_packet->probe || parsed_packet->authoritative)) { + _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; + char * new_host = _mdns_mangle_name((char *)_mdns_server->hostname); + if (new_host) { + free((char *)_mdns_server->hostname); + _mdns_server->hostname = new_host; + } + _mdns_restart_all_pcbs(); + } + } else { + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); + } + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); } -#endif - } else if (!answer->ptr) { - strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN); - } else if (strcmp(answer->host, name->host) != 0) { - continue;//wrong host } - memcpy(answer->addrv6, data_ptr, sizeof(ip6_addr_t)); + } else if (type == MDNS_TYPE_A) { - if (server->search.host[0]) { -#ifndef MDNS_TEST_MODE - if (strcmp(name->host, server->search.host) != 0) { - continue;//wrong host + ip_addr_t ip; + ip.type = IPADDR_TYPE_V4; + memcpy(&(ip.u_addr.ip4.addr), data_ptr, 4); + if (search_result) { + //check for more applicable searches (PTR & A/AAAA at the same time) + while (search_result) { + _mdns_search_result_add_ip(search_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol); + search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); + } + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, NULL); + continue; + } + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (clas > 1) { + col = 1; + } else if (!clas) { + col = -1; + } else { + col = _mdns_check_a_collision(&(ip.u_addr.ip4), packet->tcpip_if); + } + if (col == 2) { + goto clear_rx_packet; + } else if (col == 1) { + do_not_reply = true; + if (_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + if (col && (parsed_packet->probe || parsed_packet->authoritative)) { + _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; + char * new_host = _mdns_mangle_name((char *)_mdns_server->hostname); + if (new_host) { + free((char *)_mdns_server->hostname); + _mdns_server->hostname = new_host; + } + _mdns_restart_all_pcbs(); + } + } else { + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); + } + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); } -#endif - } else if (!answer->ptr) { - strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN); - } else if (strcmp(answer->host, name->host) != 0) { - continue;//wrong host } - if (server->search.running && answer->addr) { - _mdns_add_result(server, answer);//another IP for our host - } - IP4_ADDR(answer, data_ptr[0], data_ptr[1], data_ptr[2], data_ptr[3]); + } } - if (server->search.running && (server->search.host[0] || answer->ptr) && answer->addr) { - _mdns_add_result(server, answer); - } //end while + if (parsed_packet->authoritative) { + _mdns_search_finish_done(); + } + } + + if (!do_not_reply && _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].state > PCB_PROBE_3 && (parsed_packet->questions || parsed_packet->discovery)) { + _mdns_create_answer_from_parsed_packet(parsed_packet); + } + + +clear_rx_packet: + while (parsed_packet->questions) { + mdns_parsed_question_t * question = parsed_packet->questions; + parsed_packet->questions = parsed_packet->questions->next; + free(question->host); + free(question->service); + free(question->proto); + free(question->domain); + free(question); + } + free(parsed_packet); +} + +/** + * @brief Enable mDNS interface + */ +void _mdns_enable_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (!_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) { + if (_mdns_pcb_init(tcpip_if, ip_protocol)) { + return; + } + } + _mdns_restart_pcb(tcpip_if, ip_protocol); +} + +/** + * @brief Disable mDNS interface + */ +void _mdns_disable_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) { + _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); + _mdns_pcb_deinit(tcpip_if, ip_protocol); + tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); + if (other_if != TCPIP_ADAPTER_IF_MAX && _mdns_server->interfaces[other_if].pcbs[ip_protocol].state == PCB_DUP) { + _mdns_server->interfaces[other_if].pcbs[ip_protocol].state = PCB_OFF; + _mdns_enable_pcb(other_if, ip_protocol); + } + } + _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state = PCB_OFF; +} + +/** + * @brief Dispatch interface changes based on system events + */ +void _mdns_handle_system_event(system_event_id_t event, 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) { + _mdns_enable_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V4); + } + } + 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; } } - - /* - * Public Methods + * MDNS Search * */ -esp_err_t mdns_init(tcpip_adapter_if_t tcpip_if, mdns_server_t ** mdns_server) + +/** + * @brief Free search structure (except the results) + */ +static void _mdns_search_free(mdns_search_once_t * search) { - esp_err_t err = ESP_OK; + free(search->instance); + free(search->service); + free(search->proto); + vSemaphoreDelete(search->lock); + free(search); +} - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - return ESP_ERR_INVALID_ARG; +/** + * @brief Allocate new search structure + */ +static mdns_search_once_t * _mdns_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) +{ + mdns_search_once_t * search = (mdns_search_once_t *)malloc(sizeof(mdns_search_once_t)); + if (!search) { + return NULL; + } + memset(search, 0, sizeof(mdns_search_once_t)); + + search->lock = xSemaphoreCreateMutex(); + if (!search->lock) { + free(search); + return NULL; } - if (_mdns_server_get(tcpip_if)) { - return ESP_ERR_INVALID_STATE; + if (name) { + search->instance = strndup(name, MDNS_NAME_BUF_LEN-1); + if (!search->instance) { + _mdns_search_free(search); + return NULL; + } } - uint8_t mode; - err = esp_wifi_get_mode((wifi_mode_t*)&mode); + if (service) { + search->service = strndup(service, MDNS_NAME_BUF_LEN-1); + if (!search->service) { + _mdns_search_free(search); + return NULL; + } + } + + if (proto) { + search->proto = strndup(proto, MDNS_NAME_BUF_LEN-1); + if (!search->proto) { + _mdns_search_free(search); + return NULL; + } + } + + search->type = type; + search->timeout = timeout; + search->num_results = 0; + search->max_results = max_results; + search->result = NULL; + search->state = SEARCH_INIT; + search->sent_at = 0; + search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS; + search->next = NULL; + + xSemaphoreTake(search->lock, 0); + + return search; +} + +/** + * @brief Mark search as finished and remove it from search chain + */ +static void _mdns_search_finish(mdns_search_once_t * search) +{ + search->state = SEARCH_OFF; + queueDetach(mdns_search_once_t, _mdns_server->search_once, search); + xSemaphoreGive(search->lock); +} + +/** + * @brief Add new search to the search chain + */ +static void _mdns_search_add(mdns_search_once_t * search) +{ + search->next = _mdns_server->search_once; + _mdns_server->search_once = search; +} + +/** + * @brief Called from parser to finish any searches that have reached maximum results + */ +static void _mdns_search_finish_done() +{ + mdns_search_once_t * search = _mdns_server->search_once; + mdns_search_once_t * s = NULL; + while (search) { + s = search; + search = search->next; + if (s->max_results && s->num_results >= s->max_results) { + _mdns_search_finish(s); + } + } +} + +/** + * @brief Create linked IP (copy) from parsed one + */ +static mdns_ip_addr_t * _mdns_result_addr_create_ip(ip_addr_t * ip) +{ + mdns_ip_addr_t * a = (mdns_ip_addr_t *)malloc(sizeof(mdns_ip_addr_t)); + if (!a) { + return NULL; + } + memset(a, 0 , sizeof(mdns_ip_addr_t)); + a->addr.type = ip->type; + if (ip->type == IPADDR_TYPE_V6) { + memcpy(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16); + } else { + a->addr.u_addr.ip4.addr = ip->u_addr.ip4.addr; + } + return a; +} + +/** + * @brief Chain new IP to search result + */ +static void _mdns_result_add_ip(mdns_result_t * r, ip_addr_t * ip) +{ + mdns_ip_addr_t * a = r->addr; + while (a) { + if (a->addr.type == ip->type) { + if (a->addr.type == IPADDR_TYPE_V4 && a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { + return; + } + if (a->addr.type == IPADDR_TYPE_V6 && !memcmp(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { + return; + } + } + a = a->next; + } + a = _mdns_result_addr_create_ip(ip); + if (!a) { + return; + } + a->next = r->addr; + r->addr = a; +} + +/** + * @brief Called from parser to add A/AAAA data to search result + */ +static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, ip_addr_t * ip, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_result_t * r = NULL; + mdns_ip_addr_t * a = NULL; + + if ((search->type == MDNS_TYPE_A && ip->type == IPADDR_TYPE_V4) + || (search->type == MDNS_TYPE_AAAA && ip->type == IPADDR_TYPE_V6) + || search->type == MDNS_TYPE_ANY) { + r = search->result; + while (r) { + if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol) { + _mdns_result_add_ip(r, ip); + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); + if (!r) { + return; + } + + memset(r, 0 , sizeof(mdns_result_t)); + + a = _mdns_result_addr_create_ip(ip); + if (!a) { + free(r); + return; + } + a->next = r->addr; + r->addr = a; + r->tcpip_if = tcpip_if; + r->ip_protocol = ip_protocol; + r->next = search->result; + search->result = r; + search->num_results++; + } + } else if (search->type == MDNS_TYPE_PTR) { + r = search->result; + while (r) { + if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && r->hostname && !strcasecmp(hostname, r->hostname)) { + _mdns_result_add_ip(r, ip); + break; + } + r = r->next; + } + } +} + +/** + * @brief Called from parser to add PTR data to search result + */ +static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_result_t * r = search->result; + while (r) { + if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && r->instance_name && !strcasecmp(instance, r->instance_name)) { + return r; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); + if (!r) { + return NULL; + } + + memset(r, 0 , sizeof(mdns_result_t)); + r->instance_name = strdup(instance); + if (!r->instance_name) { + free(r); + return NULL; + } + + r->tcpip_if = tcpip_if; + r->ip_protocol = ip_protocol; + r->next = search->result; + search->result = r; + search->num_results++; + return r; + } + return NULL; +} + +/** + * @brief Called from parser to add SRV data to search result + */ +static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_result_t * r = search->result; + while (r) { + if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && r->hostname && !strcasecmp(hostname, r->hostname)) { + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); + if (!r) { + return; + } + + memset(r, 0 , sizeof(mdns_result_t)); + r->hostname = strdup(hostname); + if (!r->hostname) { + free(r); + return; + } + r->port = port; + r->tcpip_if = tcpip_if; + r->ip_protocol = ip_protocol; + r->next = search->result; + search->result = r; + search->num_results++; + } +} + +/** + * @brief Called from parser to add TXT data to search result + */ +static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + int i; + mdns_result_t * r = search->result; + while (r) { + if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol) { + if (r->txt) { + return; + } + r->txt = txt; + r->txt_count = txt_count; + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); + if (!r) { + for (i=0; itxt = txt; + r->txt_count = txt_count; + r->tcpip_if = tcpip_if; + r->ip_protocol = ip_protocol; + r->next = search->result; + search->result = r; + search->num_results++; + } +} + +/** + * @brief Called from packet parser to find matching running search + */ +static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * s, mdns_name_t * name, uint16_t type, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_result_t * r = NULL; + while (s) { + if (s->state == SEARCH_OFF) { + s = s->next; + continue; + } + + if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { + if ((s->type == MDNS_TYPE_ANY && s->service != NULL) + || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR)) + { + s = s->next; + continue; + } + if (s->type != MDNS_TYPE_PTR) { + if (!strcasecmp(name->host, s->instance)) { + return s; + } + s = s->next; + continue; + } + r = s->result; + while (r) { + if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && r->hostname && !strcasecmp(name->host, r->hostname)) { + return s; + } + r = r->next; + } + s = s->next; + continue; + } + + if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { + if ((s->type == MDNS_TYPE_ANY && s->service == NULL) + || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR)) + { + s = s->next; + continue; + } + if (strcasecmp(name->service, s->service) + || strcasecmp(name->proto, s->proto)) + { + s = s->next; + continue; + } + if (s->type != MDNS_TYPE_PTR) { + if (!strcasecmp(name->host, s->instance)) { + return s; + } + s = s->next; + continue; + } + return s; + } + + if (type == MDNS_TYPE_PTR && type == s->type && !strcasecmp(name->service, s->service) && !strcasecmp(name->proto, s->proto)) { + return s; + } + + s = s->next; + } + + return NULL; +} + +/** + * @brief Create search packet for partidular interface + */ +static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_result_t * r = NULL; + mdns_tx_packet_t * packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return NULL; + } + + mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); + if (!q) { + _mdns_free_tx_packet(packet); + return NULL; + } + q->next = NULL; + q->unicast = search->type != MDNS_TYPE_PTR; + q->type = search->type; + q->host = search->instance; + q->service = search->service; + q->proto = search->proto; + q->domain = MDNS_DEFAULT_DOMAIN; + queueToEnd(mdns_out_question_t, packet->questions, q); + + if (search->type == MDNS_TYPE_PTR) { + r = search->result; + while (r) { + //full record on the same interface is available + if (r->tcpip_if != tcpip_if || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { + r = r->next; + continue; + } + mdns_out_answer_t * a = (mdns_out_answer_t *)malloc(sizeof(mdns_out_answer_t)); + if (!a) { + _mdns_free_tx_packet(packet); + return NULL; + } + a->type = MDNS_TYPE_PTR; + a->service = NULL; + a->custom_instance = r->instance_name; + a->custom_service = search->service; + a->custom_proto = search->proto; + a->bye = false; + a->flush = false; + a->next = NULL; + queueToEnd(mdns_out_answer_t, packet->answers, a); + r = r->next; + } + } + + return packet; +} + +/** + * @brief Send search packet to particular interface + */ +static void _mdns_search_send_pcb(mdns_search_once_t * search, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t * packet = NULL; + if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb && _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state == PCB_RUNNING) { + packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol); + if (!packet) { + return; + } + _mdns_dispatch_tx_packet(packet); + _mdns_free_tx_packet(packet); + } +} + +/** + * @brief Send search packet to all available interfaces + */ +static void _mdns_search_send(mdns_search_once_t * search) +{ + uint8_t i, j; + for (i=0; iinterfaces[p->tcpip_if].pcbs[p->ip_protocol]; + uint32_t send_after = 1000; + + if (pcb->state == PCB_OFF) { + _mdns_free_tx_packet(p); + return; + } + _mdns_dispatch_tx_packet(p); + + switch(pcb->state) { + case PCB_PROBE_1: + q = p->questions; + while (q) { + q->unicast = false; + q = q->next; + } + //fallthrough + case PCB_PROBE_2: + _mdns_schedule_tx_packet(p, 250); + pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); + break; + case PCB_PROBE_3: + a = _mdns_create_announce_from_probe(p); + if (!a) { + _mdns_schedule_tx_packet(p, 250); + break; + } + pcb->probe_running = false; + pcb->probe_ip = false; + pcb->probe_services_len = 0; + pcb->failed_probes = 0; + free(pcb->probe_services); + pcb->probe_services = NULL; + _mdns_free_tx_packet(p); + p = a; + send_after = 250; + //fallthrough + case PCB_ANNOUNCE_1: + //fallthrough + case PCB_ANNOUNCE_2: + _mdns_schedule_tx_packet(p, send_after); + pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); + break; + case PCB_ANNOUNCE_3: + pcb->state = PCB_RUNNING; + _mdns_free_tx_packet(p); + break; + default: + _mdns_free_tx_packet(p); + break; + } +} + +/** + * @brief Free action data + */ +static void _mdns_free_action(mdns_action_t * action) +{ + switch(action->type) { + case ACTION_HOSTNAME_SET: + free(action->data.hostname); + break; + case ACTION_INSTANCE_SET: + free(action->data.instance); + break; + case ACTION_SERVICE_ADD: + _mdns_free_service(action->data.srv_add.service->service); + free(action->data.srv_add.service); + break; + case ACTION_SERVICE_INSTANCE_SET: + free(action->data.srv_instance.instance); + break; + case ACTION_SERVICE_TXT_REPLACE: + free(action->data.srv_txt_replace.txt); + break; + case ACTION_SERVICE_TXT_SET: + free(action->data.srv_txt_set.key); + free(action->data.srv_txt_set.value); + break; + case ACTION_SERVICE_TXT_DEL: + free(action->data.srv_txt_del.key); + break; + case ACTION_SEARCH_ADD: + //fallthrough + case ACTION_SEARCH_SEND: + //fallthrough + case ACTION_SEARCH_END: + _mdns_search_free(action->data.search_add.search); + break; + case ACTION_TX_HANDLE: + _mdns_free_tx_packet(action->data.tx_handle.packet); + break; + case ACTION_RX_HANDLE: + pbuf_free(action->data.rx_handle.packet->pb); + free(action->data.rx_handle.packet); + break; + default: + break; + } + free(action); +} + +/** + * @brief Called from service thread to execute given action + */ +static void _mdns_execute_action(mdns_action_t * action) +{ + mdns_srv_item_t * a = NULL; + mdns_service_t * service; + char * key; + char * value; + mdns_txt_linked_item_t * txt, * t; + + switch(action->type) { + case ACTION_SYSTEM_EVENT: + _mdns_handle_system_event(action->data.sys_event.event_id, action->data.sys_event.interface); + break; + case ACTION_HOSTNAME_SET: + _mdns_send_final_bye(true); + free((char*)_mdns_server->hostname); + _mdns_server->hostname = action->data.hostname; + _mdns_restart_all_pcbs(); + + break; + case ACTION_INSTANCE_SET: + _mdns_send_bye_all_pcbs_no_instance(); + free((char*)_mdns_server->instance); + _mdns_server->instance = action->data.instance; + _mdns_restart_all_pcbs_no_instance(); + + break; + case ACTION_SERVICE_ADD: + action->data.srv_add.service->next = _mdns_server->services; + _mdns_server->services = action->data.srv_add.service; + _mdns_probe_all_pcbs(&action->data.srv_add.service, 1, false, false); + + break; + case ACTION_SERVICE_INSTANCE_SET: + if (action->data.srv_port.service->service->instance) { + _mdns_send_bye(&action->data.srv_instance.service, 1, false); + free((char*)action->data.srv_instance.service->service->instance); + } + action->data.srv_instance.service->service->instance = action->data.srv_instance.instance; + _mdns_probe_all_pcbs(&action->data.srv_instance.service, 1, false, false); + + break; + case ACTION_SERVICE_PORT_SET: + action->data.srv_port.service->service->port = action->data.srv_port.port; + _mdns_announce_all_pcbs(&action->data.srv_port.service, 1, true); + + break; + case ACTION_SERVICE_TXT_REPLACE: + service = action->data.srv_txt_replace.service->service; + txt = service->txt; + service->txt = NULL; + while (txt) { + t = txt; + txt = txt->next; + free((char *)t->value); + free((char *)t->key); + free(t); + } + service->txt = _mdns_allocate_txt(action->data.srv_txt_replace.num_items, action->data.srv_txt_replace.txt); + _mdns_announce_all_pcbs(&action->data.srv_txt_replace.service, 1, false); + + break; + case ACTION_SERVICE_TXT_SET: + service = action->data.srv_txt_set.service->service; + key = action->data.srv_txt_set.key; + value = action->data.srv_txt_set.value; + txt = service->txt; + while (txt) { + if (strcmp(txt->key, key) == 0) { + free((char *)txt->value); + free(key); + txt->value = value; + break; + } + txt = txt->next; + } + if (!txt) { + txt = (mdns_txt_linked_item_t *)malloc(sizeof(mdns_txt_linked_item_t)); + if (!txt) { + _mdns_free_action(action); + return; + } + txt->key = key; + txt->value = value; + txt->next = service->txt; + service->txt = txt; + } + + _mdns_announce_all_pcbs(&action->data.srv_txt_set.service, 1, false); + + break; + case ACTION_SERVICE_TXT_DEL: + service = action->data.srv_txt_del.service->service; + key = action->data.srv_txt_del.key; + txt = service->txt; + if (!txt) { + break; + } + if (strcmp(txt->key, key) == 0) { + service->txt = txt->next; + free((char *)txt->key); + free((char *)txt->value); + free(txt); + } else { + while (txt->next) { + if (strcmp(txt->next->key, key) == 0) { + t = txt->next; + txt->next = t->next; + free((char *)t->key); + free((char *)t->value); + free(t); + break; + } else { + txt = txt->next; + } + } + } + free(key); + + _mdns_announce_all_pcbs(&action->data.srv_txt_set.service, 1, false); + + 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_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; + a->next = a->next->next; + _mdns_send_bye(&b, 1, false); + _mdns_free_service(b->service); + free(b); + } + } + + break; + case ACTION_SERVICES_CLEAR: + _mdns_send_final_bye(false); + a = _mdns_server->services; + _mdns_server->services = NULL; + while (a) { + mdns_srv_item_t * s = a; + a = a->next; + _mdns_free_service(s->service); + free(s); + } + + break; + case ACTION_SEARCH_ADD: + _mdns_search_add(action->data.search_add.search); + break; + case ACTION_SEARCH_SEND: + _mdns_search_send(action->data.search_add.search); + break; + case ACTION_SEARCH_END: + _mdns_search_finish(action->data.search_add.search); + break; + case ACTION_TX_HANDLE: + _mdns_tx_handle_packet(action->data.tx_handle.packet); + break; + case ACTION_RX_HANDLE: + mdns_parse_packet(action->data.rx_handle.packet); + pbuf_free(action->data.rx_handle.packet->pb); + free(action->data.rx_handle.packet); + break; + default: + break; + } + free(action); +} + +/** + * @brief Queue search action + */ +static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t * search) +{ + mdns_action_t * action = NULL; + + action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + return ESP_ERR_NO_MEM; + } + + action->type = type; + action->data.search_add.search = search; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +/** + * @brief Called from timer task to run mDNS responder + */ +static void _mdns_scheduler_run() +{ + mdns_tx_packet_t * p = _mdns_server->tx_queue_head; + mdns_action_t * action = NULL; + + if (!p) { + return; + } + MDNS_SERVICE_LOCK(); + if ((int32_t)(p->send_at - (xTaskGetTickCount() * portTICK_PERIOD_MS)) < 0) { + action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (action) { + _mdns_server->tx_queue_head = p->next; + action->type = ACTION_TX_HANDLE; + action->data.tx_handle.packet = p; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(action); + _mdns_server->tx_queue_head = p; + } + } + } + MDNS_SERVICE_UNLOCK(); +} + +/** + * @brief Called from timer task to run active searches + */ +static void _mdns_search_run() +{ + mdns_search_once_t * s = _mdns_server->search_once; + uint32_t now = xTaskGetTickCount() * portTICK_PERIOD_MS; + if (!s) { + return; + } + MDNS_SERVICE_LOCK(); + while (s) { + if (s->state != SEARCH_OFF) { + if (now > (s->started_at + s->timeout)) { + s->state = SEARCH_OFF; + if (_mdns_send_search_action(ACTION_SEARCH_END, s) != ESP_OK) { + s->state = SEARCH_RUNNING; + } + } else if (s->state == SEARCH_INIT || (now - s->sent_at) > 1000) { + s->state = SEARCH_RUNNING; + s->sent_at = now; + if (_mdns_send_search_action(ACTION_SEARCH_SEND, s) != ESP_OK) { + s->sent_at -= 1000; + } + } + } + s = s->next; + } + MDNS_SERVICE_UNLOCK(); +} + +/** + * @brief the main MDNS service task. Packets are received and parsed here + */ +static void _mdns_service_task(void *pvParameters) +{ + mdns_action_t * a = NULL; + for (;;) { + if (_mdns_server && _mdns_server->action_queue) { + if (xQueueReceive(_mdns_server->action_queue, &a, portMAX_DELAY) == pdTRUE) { + if (a->type == ACTION_TASK_STOP) { + break; + } + MDNS_SERVICE_LOCK(); + _mdns_execute_action(a); + MDNS_SERVICE_UNLOCK(); + } + } else { + vTaskDelay(500 * portTICK_PERIOD_MS); + } + } + _mdns_service_task_handle = NULL; + vTaskDelete(NULL); +} + +static void _mdns_timer_cb(void * arg) +{ + _mdns_scheduler_run(); + _mdns_search_run(); +} + +static esp_err_t _mdns_start_timer(){ + esp_timer_create_args_t timer_conf = { + .callback = _mdns_timer_cb, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "mdns_timer" + }; + esp_err_t err = esp_timer_create(&timer_conf, &(_mdns_server->timer_handle)); if (err) { return err; } + return esp_timer_start_periodic(_mdns_server->timer_handle, MDNS_TIMER_PERIOD_US); +} - if ((tcpip_if == TCPIP_ADAPTER_IF_STA && !(mode & WIFI_MODE_STA)) - || (tcpip_if == TCPIP_ADAPTER_IF_AP && !(mode & WIFI_MODE_AP))) { - return ESP_ERR_INVALID_ARG; +static esp_err_t _mdns_stop_timer(){ + esp_err_t err = ESP_OK; + if (_mdns_server->timer_handle) { + err = esp_timer_stop(_mdns_server->timer_handle); + if (err) { + return err; + } + err = esp_timer_delete(_mdns_server->timer_handle); } + return err; +} - mdns_server_t * server = (mdns_server_t *)malloc(sizeof(mdns_server_t)); - if (!server) { - return ESP_ERR_NO_MEM; +/** + * @brief Start the service thread if not running + * + * @return + * - ESP_OK on success + * - ESP_FAIL on error + */ +static esp_err_t _mdns_service_task_start() +{ +#ifndef MDNS_TEST_MODE + if (!_mdns_service_semaphore) { + _mdns_service_semaphore = xSemaphoreCreateMutex(); + if (!_mdns_service_semaphore) { + return ESP_FAIL; + } } - - server->tcpip_if = tcpip_if; - server->hostname = NULL; - server->instance = NULL; - server->services = NULL; - server->search.host[0] = 0; - server->search.service[0] = 0; - server->search.proto[0] = 0; - server->search.running = false; - server->search.results = NULL; - server->pcb = NULL; - - server->lock = xSemaphoreCreateMutex(); - if (!server->lock) { - free(server); - return ESP_ERR_NO_MEM; - } - - server->search.lock = xSemaphoreCreateMutex(); - if (!server->search.lock) { - vSemaphoreDelete(server->lock); - free(server); - return ESP_ERR_NO_MEM; - } - - server->queue = xQueueCreate(MDNS_PACKET_QUEUE_LEN, sizeof(struct pbuf *)); - if (!server->queue) { - vSemaphoreDelete(server->lock); - vSemaphoreDelete(server->search.lock); - free(server); - return ESP_ERR_NO_MEM; - } - - if (_mdns_server_add(server)) { - //service start failed! - vSemaphoreDelete(server->lock); - vSemaphoreDelete(server->search.lock); - vQueueDelete(server->queue); - free(server); + MDNS_SERVICE_LOCK(); + if (_mdns_start_timer()) { + MDNS_SERVICE_UNLOCK(); return ESP_FAIL; } - - const char * hostname = NULL; - tcpip_adapter_get_hostname(server->tcpip_if, &hostname); - mdns_set_hostname(server, hostname); - - *mdns_server = server; + if (!_mdns_service_task_handle) { + xTaskCreatePinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, 1, (TaskHandle_t * const)(&_mdns_service_task_handle), 0); + if (!_mdns_service_task_handle) { + MDNS_SERVICE_UNLOCK(); + return ESP_FAIL; + } + } + MDNS_SERVICE_UNLOCK(); +#endif return ESP_OK; } -void mdns_free(mdns_server_t * server) +/** + * @brief Stop the service thread + * + * @return + * - ESP_OK + */ +static esp_err_t _mdns_service_task_stop() { - if (!server) { - return; - } - _mdns_server_remove(server); - mdns_service_remove_all(server); - MDNS_MUTEX_LOCK(); - free((char*)server->hostname); - free((char*)server->instance); - if (server->queue) { - struct pbuf * c; - while (xQueueReceive(server->queue, &c, 0) == pdTRUE) { - pbuf_free(c); +#ifndef MDNS_TEST_MODE + MDNS_SERVICE_LOCK(); + _mdns_stop_timer(); + if (_mdns_service_task_handle) { + mdns_action_t action; + mdns_action_t * a = &action; + action.type = ACTION_TASK_STOP; + if (xQueueSend(_mdns_server->action_queue, &a, (portTickType)0) != pdPASS) { + vTaskDelete(_mdns_service_task_handle); + _mdns_service_task_handle = NULL; + } + while (_mdns_service_task_handle) { + vTaskDelay(10 / portTICK_PERIOD_MS); } - vQueueDelete(server->queue); } - if (server->search.running) { - mdns_query_end(server); - } - mdns_result_free(server); - vSemaphoreDelete(server->search.lock); - MDNS_MUTEX_UNLOCK(); - vSemaphoreDelete(server->lock); - free(server); + MDNS_SERVICE_UNLOCK(); +#endif + return ESP_OK; } -esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname) +/* + * Public Methods + * */ + +esp_err_t mdns_handle_system_event(void *ctx, system_event_t *event) { - if (!server) { + if (!_mdns_server) { + return ESP_OK; + } + + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + return ESP_OK; + } + 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; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(action); + } + return ESP_OK; +} + +esp_err_t mdns_init() +{ + esp_err_t err = ESP_OK; + + if (_mdns_server) { + return err; + } + + _mdns_server = (mdns_server_t *)malloc(sizeof(mdns_server_t)); + if (!_mdns_server) { + return ESP_ERR_NO_MEM; + } + memset((uint8_t*)_mdns_server, 0, sizeof(mdns_server_t)); + + _mdns_server->lock = xSemaphoreCreateMutex(); + if (!_mdns_server->lock) { + err = ESP_ERR_NO_MEM; + goto free_server; + } + + _mdns_server->action_queue = xQueueCreate(MDNS_ACTION_QUEUE_LEN, sizeof(mdns_action_t *)); + if (!_mdns_server->action_queue) { + err = ESP_ERR_NO_MEM; + goto free_lock; + } + + if (_mdns_service_task_start()) { + //service start failed! + err = ESP_FAIL; + goto free_all; + } + + uint8_t i; + ip6_addr_t tmp_addr6; + tcpip_adapter_ip_info_t if_ip_info; + + for (i=0; iaction_queue); +free_lock: + vSemaphoreDelete(_mdns_server->lock); +free_server: + free(_mdns_server); + _mdns_server = NULL; + return err; +} + +void mdns_free() +{ + uint8_t i, j; + if (!_mdns_server) { + return; + } + _mdns_service_task_stop(); + mdns_service_remove_all(_mdns_server); + for (i=0; ihostname); + free((char*)_mdns_server->instance); + if (_mdns_server->action_queue) { + mdns_action_t * c; + while (xQueueReceive(_mdns_server->action_queue, &c, 0) == pdTRUE) { + _mdns_free_action(c); + } + vQueueDelete(_mdns_server->action_queue); + } + _mdns_clear_tx_queue_head(); + while (_mdns_server->search_once) { + mdns_search_once_t * h = _mdns_server->search_once; + _mdns_server->search_once = h->next; + free(h->instance); + free(h->service); + free(h->proto); + vSemaphoreDelete(h->lock); + if (h->result) { + mdns_query_results_free(h->result); + } + free(h); + } + vSemaphoreDelete(_mdns_server->lock); + free(_mdns_server); + _mdns_server = NULL; +} + +esp_err_t mdns_hostname_set(const char * hostname) +{ + if (!_mdns_server) { return ESP_ERR_INVALID_ARG; } if (strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } - MDNS_MUTEX_LOCK(); - free((char*)server->hostname); - server->hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); - if (!server->hostname) { - MDNS_MUTEX_UNLOCK(); + char * new_hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); + if (!new_hostname) { + return ESP_ERR_NO_MEM; + } + + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + free(new_hostname); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_HOSTNAME_SET; + action->data.hostname = new_hostname; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(new_hostname); + free(action); return ESP_ERR_NO_MEM; } - MDNS_MUTEX_UNLOCK(); return ERR_OK; } -esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance) +esp_err_t mdns_instance_name_set(const char * instance) { - if (!server) { + if (!_mdns_server) { return ESP_ERR_INVALID_ARG; } if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } - MDNS_MUTEX_LOCK(); - free((char*)server->instance); - server->instance = strndup(instance, MDNS_NAME_BUF_LEN - 1); - if (!server->instance) { - MDNS_MUTEX_UNLOCK(); + char * new_instance = strndup(instance, MDNS_NAME_BUF_LEN - 1); + if (!new_instance) { + return ESP_ERR_NO_MEM; + } + + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + free(new_instance); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_INSTANCE_SET; + action->data.instance = new_instance; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(new_instance); + free(action); return ESP_ERR_NO_MEM; } - MDNS_MUTEX_UNLOCK(); return ERR_OK; } @@ -1737,167 +4266,257 @@ esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance) * MDNS SERVICES * */ -esp_err_t mdns_service_add(mdns_server_t * server, const char * service, const char * proto, uint16_t port) +esp_err_t mdns_service_add(const char * instance, const char * service, const char * proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!server || !service || !proto || !port) { - //bad argument + if (!_mdns_server || !service || !proto || !port) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * item = _mdns_get_service_item(server, service, proto); + mdns_srv_item_t * item = _mdns_get_service_item(service, proto); if (item) { - //we already have that service - return mdns_service_port_set(server, service, proto, port); + return ESP_ERR_INVALID_ARG; } - mdns_service_t * s = _mdns_create_service(service, proto, port); + mdns_service_t * s = _mdns_create_service(service, proto, port, instance, num_items, txt); if (!s) { return ESP_ERR_NO_MEM; } item = (mdns_srv_item_t *)malloc(sizeof(mdns_srv_item_t)); if (!item) { - free(s); + _mdns_free_service(s); return ESP_ERR_NO_MEM; } item->service = s; - item->next = server->services; - server->services = item; + item->next = NULL; + + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + _mdns_free_service(s); + free(item); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_SERVICE_ADD; + action->data.srv_add.service = item; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + _mdns_free_service(s); + free(item); + free(action); + return ESP_ERR_NO_MEM; + } + + uint8_t i = 0; + while (_mdns_get_service_item(service, proto) == NULL && i++ < 200) { + vTaskDelay(1); + } + if (i >= 200) { + return ESP_FAIL; + } + return ESP_OK; } -esp_err_t mdns_service_port_set(mdns_server_t * server, const char * service, const char * proto, uint16_t port) +esp_err_t mdns_service_port_set(const char * service, const char * proto, uint16_t port) { - if (!server || !server->services || !service || !proto || !port) { + if (!_mdns_server || !_mdns_server->services || !service || !proto || !port) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto); + mdns_srv_item_t * s = _mdns_get_service_item(service, proto); if (!s) { return ESP_ERR_NOT_FOUND; } - MDNS_MUTEX_LOCK(); - s->service->port = port; - MDNS_MUTEX_UNLOCK(); + + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + return ESP_ERR_NO_MEM; + } + action->type = ACTION_SERVICE_PORT_SET; + action->data.srv_port.service = s; + action->data.srv_port.port = port; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(action); + return ESP_ERR_NO_MEM; + } return ESP_OK; } -esp_err_t mdns_service_txt_set(mdns_server_t * server, const char * service, const char * proto, uint8_t num_items, const char ** txt) +esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_txt_item_t txt[], uint8_t num_items) { - if (!server || !server->services || !service || !proto) { + if (!_mdns_server || !_mdns_server->services || !service || !proto || (num_items && txt == NULL)) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto); + mdns_srv_item_t * s = _mdns_get_service_item(service, proto); if (!s) { return ESP_ERR_NOT_FOUND; } - MDNS_MUTEX_LOCK(); - if (s->service->txt_num_items) { - uint8_t i; - for (i = 0; i < s->service->txt_num_items; i++) { - free((char *)s->service->txt[i]); + + mdns_txt_item_t * txt_copy = NULL; + if (num_items){ + txt_copy = (mdns_txt_item_t *)malloc(num_items * sizeof(mdns_txt_item_t)); + if (!txt_copy) { + return ESP_ERR_NO_MEM; } + memcpy(txt_copy, txt, num_items * sizeof(mdns_txt_item_t)); } - free(s->service->txt); - if (num_items) { - s->service->txt = (const char **)malloc(sizeof(char *) * num_items); - if (!s->service->txt) { - s->service->txt_num_items = 0; - goto fail; - } - uint8_t i; - s->service->txt_num_items = num_items; - for (i = 0; i < num_items; i++) { - s->service->txt[i] = strdup(txt[i]); - if (!s->service->txt[i]) { - s->service->txt_num_items = i; - goto fail; - } - } + + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + free(txt_copy); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_SERVICE_TXT_REPLACE; + action->data.srv_txt_replace.service = s; + action->data.srv_txt_replace.num_items = num_items; + action->data.srv_txt_replace.txt = txt_copy; + + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(txt_copy); + free(action); + return ESP_ERR_NO_MEM; } - MDNS_MUTEX_UNLOCK(); return ESP_OK; -fail: - MDNS_MUTEX_UNLOCK(); - return ESP_ERR_NO_MEM; } -esp_err_t mdns_service_instance_set(mdns_server_t * server, const char * service, const char * proto, const char * instance) + +esp_err_t mdns_service_txt_item_set(const char * service, const char * proto, const char * key, const char * value) { - if (!server || !server->services || !service || !proto) { + if (!_mdns_server || !_mdns_server->services || !service || !proto) { + return ESP_ERR_INVALID_ARG; + } + mdns_srv_item_t * s = _mdns_get_service_item(service, proto); + if (!s) { + return ESP_ERR_NOT_FOUND; + } + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + return ESP_ERR_NO_MEM; + } + + action->type = ACTION_SERVICE_TXT_SET; + action->data.srv_txt_set.service = s; + action->data.srv_txt_set.key = strdup(key); + if (!action->data.srv_txt_set.key) { + free(action); + return ESP_ERR_NO_MEM; + } + action->data.srv_txt_set.value = strdup(value); + if (!action->data.srv_txt_set.value) { + free(action->data.srv_txt_set.key); + free(action); + return ESP_ERR_NO_MEM; + } + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(action->data.srv_txt_set.key); + free(action->data.srv_txt_set.value); + free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +esp_err_t mdns_service_txt_item_remove(const char * service, const char * proto, const char * key) +{ + if (!_mdns_server || !_mdns_server->services || !service || !proto) { + return ESP_ERR_INVALID_ARG; + } + mdns_srv_item_t * s = _mdns_get_service_item(service, proto); + if (!s) { + return ESP_ERR_NOT_FOUND; + } + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + return ESP_ERR_NO_MEM; + } + + action->type = ACTION_SERVICE_TXT_DEL; + action->data.srv_txt_del.service = s; + action->data.srv_txt_del.key = strdup(key); + if (!action->data.srv_txt_del.key) { + free(action); + return ESP_ERR_NO_MEM; + } + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(action->data.srv_txt_del.key); + free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +esp_err_t mdns_service_instance_name_set(const char * service, const char * proto, const char * instance) +{ + if (!_mdns_server || !_mdns_server->services || !service || !proto) { return ESP_ERR_INVALID_ARG; } if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto); + mdns_srv_item_t * s = _mdns_get_service_item(service, proto); if (!s) { return ESP_ERR_NOT_FOUND; } - MDNS_MUTEX_LOCK(); - free((char*)s->service->instance); - s->service->instance = strdup(instance); - if (!s->service->instance) { - MDNS_MUTEX_UNLOCK(); + char * new_instance = strndup(instance, MDNS_NAME_BUF_LEN - 1); + if (!new_instance) { + return ESP_ERR_NO_MEM; + } + + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + free(new_instance); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_SERVICE_INSTANCE_SET; + action->data.srv_instance.service = s; + action->data.srv_instance.instance = new_instance; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(new_instance); + free(action); return ESP_ERR_NO_MEM; } - MDNS_MUTEX_UNLOCK(); return ESP_OK; } -esp_err_t mdns_service_remove(mdns_server_t * server, const char * service, const char * proto) +esp_err_t mdns_service_remove(const char * service, const char * proto) { - if (!server || !server->services || !service || !proto) { + if (!_mdns_server || !_mdns_server->services || !service || !proto) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto); + mdns_srv_item_t * s = _mdns_get_service_item(service, proto); if (!s) { return ESP_ERR_NOT_FOUND; } - //first item - if (server->services == s) { - MDNS_MUTEX_LOCK(); - server->services = server->services->next; - MDNS_MUTEX_UNLOCK(); - _mdns_free_service(s->service); - free(s); - return ESP_OK; + + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + return ESP_ERR_NO_MEM; } - //not first item - mdns_srv_item_t * a = server->services; - while (a->next && a->next != s) { - a = a->next; + action->type = ACTION_SERVICE_DEL; + action->data.srv_del.service = s; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(action); + return ESP_ERR_NO_MEM; } - //next item of the current item is our item - if (a->next == s) { - MDNS_MUTEX_LOCK(); - a->next = s->next; - MDNS_MUTEX_UNLOCK(); - _mdns_free_service(s->service); - free(s); - return ESP_OK; - } - //how did we end here? - return ESP_FAIL; + return ESP_OK; } -esp_err_t mdns_service_remove_all(mdns_server_t * server) +esp_err_t mdns_service_remove_all() { - if (!server) { + if (!_mdns_server) { return ESP_ERR_INVALID_ARG; } - if (!server->services) { + if (!_mdns_server->services) { return ESP_OK; } - MDNS_MUTEX_LOCK(); - mdns_srv_item_t * a = server->services; - server->services = NULL; - while (a) { - mdns_srv_item_t * s = a; - a = a->next; - _mdns_free_service(s->service); - free(s); + + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + return ESP_ERR_NO_MEM; + } + action->type = ACTION_SERVICES_CLEAR; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(action); + return ESP_ERR_NO_MEM; } - MDNS_MUTEX_UNLOCK(); return ESP_OK; } @@ -1905,131 +4524,384 @@ esp_err_t mdns_service_remove_all(mdns_server_t * server) * MDNS QUERY * */ -size_t mdns_query(mdns_server_t * server, const char * service, const char * proto, uint32_t timeout) +void mdns_query_results_free(mdns_result_t * results) { - if (!server || !service) { - return 0; - } - MDNS_SEARCH_LOCK(); - uint16_t qtype = MDNS_TYPE_PTR; - mdns_result_free(server); - if (proto) { - server->search.host[0] = 0; - strlcpy(server->search.service, service, MDNS_NAME_BUF_LEN); - strlcpy(server->search.proto, proto, MDNS_NAME_BUF_LEN); - } else { - strlcpy(server->search.host, service, MDNS_NAME_BUF_LEN); - server->search.service[0] = 0; - server->search.proto[0] = 0; - qtype = MDNS_TYPE_A; - } + mdns_result_t * r; + mdns_ip_addr_t * a; + int i; - uint8_t hostname_len = strlen(server->search.host); - uint8_t service_type_len = strlen(server->search.service); - uint8_t protoname_len = strlen(server->search.proto); + while (results) { + r = results; - size_t len = 23; //head+type+class+(strlen(local)+1)+fqdn_end - if (hostname_len) { - len += hostname_len + 1; - } else if (service_type_len) { - len += service_type_len + protoname_len + 2; - } + free((char *)(r->hostname)); + free((char *)(r->instance_name)); - uint8_t * packet = (uint8_t *)malloc(len); - if (!packet) { - return 0; - } - memset(packet, 0, len); - _mdns_set_u16(packet, MDNS_HEAD_QUESTIONS_OFFSET, 1); - uint16_t index = MDNS_HEAD_LEN; - - if (hostname_len) { - _mdns_append_string(packet, &index, server->search.host); - } else if (service_type_len) { - _mdns_append_string(packet, &index, server->search.service); - _mdns_append_string(packet, &index, server->search.proto); - } - - _mdns_append_string(packet, &index, MDNS_DEFAULT_DOMAIN); - _mdns_append_u8(packet, &index, 0); //fqdn_end - - _mdns_append_u16(packet, &index, qtype); - _mdns_append_u16(packet, &index, MDNS_CLASS_IN); - - MDNS_MUTEX_LOCK(); - size_t written = _mdns_server_write(server, packet, index); - MDNS_MUTEX_UNLOCK(); - free(packet); - if (written != index) { - return 0; - } - - server->search.running = true; - if (timeout) { - uint32_t startAt = xTaskGetTickCount() * portTICK_PERIOD_MS; - while (server->search.running && ((xTaskGetTickCount() * portTICK_PERIOD_MS) - startAt) < timeout) { - vTaskDelay(1 / portTICK_PERIOD_MS); + for (i=0; itxt_count; i++) { + free((char *)(r->txt[i].key)); + free((char *)(r->txt[i].value)); } - server->search.running = false; - MDNS_SEARCH_UNLOCK(); - return mdns_result_get_count(server); + free(r->txt); + + while (r->addr) { + a = r->addr; + r->addr = r->addr->next; + free(a); + } + + results = results->next; + free(r); } - return 0; } -size_t mdns_query_end(mdns_server_t * server) +esp_err_t mdns_query(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t ** results) { - if (!server || !server->search.running) { - return 0; - } - server->search.running = false; - MDNS_SEARCH_UNLOCK(); - return mdns_result_get_count(server); -} + mdns_search_once_t * search = NULL; -esp_err_t mdns_result_free(mdns_server_t * server) -{ - if (!server || server->search.running || !server->search.results) { + *results = NULL; + + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + + if (!timeout) { return ESP_ERR_INVALID_ARG; } - while (server->search.results) { - const mdns_result_t * r = server->search.results; - server->search.results = (mdns_result_t *)r->next; - free((char *)r->host); - free((char *)r->instance); - free((char *)r->txt); - free((mdns_result_t *)r); + + search = _mdns_search_init(name, service, proto, type, timeout, max_results); + if (!search) { + return ESP_ERR_NO_MEM; } - server->search.results = NULL; + + if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { + _mdns_search_free(search); + return ESP_ERR_NO_MEM; + } + xSemaphoreTake(search->lock, portMAX_DELAY); + + *results = search->result; + _mdns_search_free(search); + return ESP_OK; } -size_t mdns_result_get_count(mdns_server_t * server) +esp_err_t mdns_query_ptr(const char * service, const char * proto, uint32_t timeout, size_t max_results, mdns_result_t ** results) { - if (!server || !server->search.results) { - return 0; + if (!service || !proto) { + return ESP_ERR_INVALID_ARG; } - size_t len = 0; - const mdns_result_t * r = server->search.results; - while (r) { - len++; - r = r->next; - } - return len; + + return mdns_query(NULL, service, proto, MDNS_TYPE_PTR, timeout, max_results, results); } -const mdns_result_t * mdns_result_get(mdns_server_t * server, size_t num) +esp_err_t mdns_query_srv(const char * instance, const char * service, const char * proto, uint32_t timeout, mdns_result_t ** result) { - if (!server || !server->search.results) { - return NULL; + if (!instance || !service || !proto) { + return ESP_ERR_INVALID_ARG; } - size_t len = 0; - const mdns_result_t * r = server->search.results; - while (r) { - if (len++ == num) { - return r; - } - r = r->next; - } - return NULL; + + return mdns_query(instance, service, proto, MDNS_TYPE_SRV, timeout, 1, result); } + +esp_err_t mdns_query_txt(const char * instance, const char * service, const char * proto, uint32_t timeout, mdns_result_t ** result) +{ + if (!instance || !service || !proto) { + return ESP_ERR_INVALID_ARG; + } + + return mdns_query(instance, service, proto, MDNS_TYPE_TXT, timeout, 1, result); +} + +esp_err_t mdns_query_a(const char * name, uint32_t timeout, ip4_addr_t * addr) +{ + mdns_result_t * result = NULL; + esp_err_t err; + + if (!name) { + return ESP_ERR_INVALID_ARG; + } + + err = mdns_query(name, NULL, NULL, MDNS_TYPE_A, timeout, 1, &result); + + if (err) { + return err; + } + + if (!result) { + return ESP_ERR_NOT_FOUND; + } + + mdns_ip_addr_t * a = result->addr; + while (a) { + if (a->addr.type == IPADDR_TYPE_V4) { + addr->addr = a->addr.u_addr.ip4.addr; + mdns_query_results_free(result); + return ESP_OK; + } + a = a->next; + } + + mdns_query_results_free(result); + return ESP_ERR_NOT_FOUND; +} + +esp_err_t mdns_query_aaaa(const char * name, uint32_t timeout, ip6_addr_t * addr) +{ + mdns_result_t * result = NULL; + esp_err_t err; + + if (!name) { + return ESP_ERR_INVALID_ARG; + } + + err = mdns_query(name, NULL, NULL, MDNS_TYPE_AAAA, timeout, 1, &result); + + if (err) { + return err; + } + + if (!result) { + return ESP_ERR_NOT_FOUND; + } + + mdns_ip_addr_t * a = result->addr; + while (a) { + if (a->addr.type == IPADDR_TYPE_V6) { + memcpy(addr->addr, a->addr.u_addr.ip6.addr, 16); + mdns_query_results_free(result); + return ESP_OK; + } + a = a->next; + } + + mdns_query_results_free(result); + return ESP_ERR_NOT_FOUND; +} + +#ifdef MDNS_ENABLE_DEBUG + +void mdns_debug_packet(const uint8_t * data, size_t len) +{ + static mdns_name_t n; + mdns_header_t header; + const uint8_t * content = data + MDNS_HEAD_LEN; + uint32_t t = xTaskGetTickCount() * portTICK_PERIOD_MS; + mdns_name_t * name = &n; + memset(name, 0, sizeof(mdns_name_t)); + + _mdns_dbg_printf("Packet[%u]: ", t); + + header.id = _mdns_read_u16(data, MDNS_HEAD_ID_OFFSET); + header.flags.value = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); + header.questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); + header.answers = _mdns_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); + header.servers = _mdns_read_u16(data, MDNS_HEAD_SERVERS_OFFSET); + header.additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); + + _mdns_dbg_printf("%s", + (header.flags.value == MDNS_FLAGS_AUTHORITATIVE)?"AUTHORITATIVE\n": + (header.flags.value == MDNS_FLAGS_DISTRIBUTED)?"DISTRIBUTED\n": + (header.flags.value == 0)?"\n":" " + ); + if (header.flags.value && header.flags.value != MDNS_FLAGS_AUTHORITATIVE) { + _mdns_dbg_printf("0x%04X\n", header.flags.value); + } + + if (header.questions) { + uint8_t qs = header.questions; + + while (qs--) { + content = _mdns_parse_fqdn(data, content, name); + if (!content) { + header.answers = 0; + header.additional = 0; + header.servers = 0; + _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + break; + } + + uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t clas = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + bool unicast = !!(clas & 0x8000); + clas &= 0x7FFF; + content = content + 4; + + _mdns_dbg_printf(" Q: "); + if (unicast) { + _mdns_dbg_printf("*U* "); + } + if (type == MDNS_TYPE_PTR) { + _mdns_dbg_printf("%s.%s%s.%s.%s. PTR ", name->host, name->sub?"_sub.":"", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_SRV) { + _mdns_dbg_printf("%s.%s%s.%s.%s. SRV ", name->host, name->sub?"_sub.":"", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_TXT) { + _mdns_dbg_printf("%s.%s%s.%s.%s. TXT ", name->host, name->sub?"_sub.":"", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_A) { + _mdns_dbg_printf("%s.%s. A ", name->host, name->domain); + } else if (type == MDNS_TYPE_AAAA) { + _mdns_dbg_printf("%s.%s. AAAA ", name->host, name->domain); + } else if (type == MDNS_TYPE_NSEC) { + _mdns_dbg_printf("%s.%s%s.%s.%s. NSEC ", name->host, name->sub?"_sub.":"", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_ANY) { + _mdns_dbg_printf("%s.%s%s.%s.%s. ANY ", name->host, name->sub?"_sub.":"", name->service, name->proto, name->domain); + } else { + _mdns_dbg_printf("%s.%s%s.%s.%s. %04X ", name->host, name->sub?"_sub.":"", name->service, name->proto, name->domain, type); + } + + if (clas == 0x0001) { + _mdns_dbg_printf("IN"); + } else { + _mdns_dbg_printf("%04X", clas); + } + _mdns_dbg_printf("\n"); + } + } + + if (header.answers || header.servers || header.additional) { + uint16_t recordIndex = 0; + + while (content < (data + len)) { + + content = _mdns_parse_fqdn(data, content, name); + if (!content) { + _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + break; + } + + uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t clas = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + uint32_t ttl = _mdns_read_u32(content, MDNS_TTL_OFFSET); + uint16_t data_len = _mdns_read_u16(content, MDNS_LEN_OFFSET); + const uint8_t * data_ptr = content + MDNS_DATA_OFFSET; + bool flush = !!(clas & 0x8000); + clas &= 0x7FFF; + + content = data_ptr + data_len; + if (content > (data + len)) { + _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + break; + } + + mdns_parsed_recort_type_t record_type = MDNS_ANSWER; + + if (recordIndex >= (header.answers + header.servers)) { + record_type = MDNS_EXTRA; + } else if (recordIndex >= (header.answers)) { + record_type = MDNS_NS; + } + recordIndex++; + + if (record_type == MDNS_EXTRA) { + _mdns_dbg_printf(" X"); + } else if (record_type == MDNS_NS) { + _mdns_dbg_printf(" S"); + } else { + _mdns_dbg_printf(" A"); + } + + if (type == MDNS_TYPE_PTR) { + _mdns_dbg_printf(": %s%s%s.%s.%s. PTR ", name->host, name->host[0]?".":"", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_SRV) { + _mdns_dbg_printf(": %s.%s.%s.%s. SRV ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_TXT) { + _mdns_dbg_printf(": %s.%s.%s.%s. TXT ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_A) { + _mdns_dbg_printf(": %s.%s. A ", name->host, name->domain); + } else if (type == MDNS_TYPE_AAAA) { + _mdns_dbg_printf(": %s.%s. AAAA ", name->host, name->domain); + } else if (type == MDNS_TYPE_NSEC) { + _mdns_dbg_printf(": %s.%s.%s.%s. NSEC ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_ANY) { + _mdns_dbg_printf(": %s.%s.%s.%s. ANY ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_OPT) { + _mdns_dbg_printf(": . OPT "); + } else { + _mdns_dbg_printf(": %s.%s.%s.%s. %04X ", name->host, name->service, name->proto, name->domain, type); + } + + if (clas == 0x0001) { + _mdns_dbg_printf("IN "); + } else { + _mdns_dbg_printf("%04X ", clas); + } + if (flush) { + _mdns_dbg_printf("FLUSH "); + } + _mdns_dbg_printf("%u ", ttl); + _mdns_dbg_printf("[%u] ", data_len); + if (type == MDNS_TYPE_PTR) { + if (!_mdns_parse_fqdn(data, data_ptr, name)) { + _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + continue; + } + _mdns_dbg_printf("%s.%s.%s.%s.\n", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_SRV) { + if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name)) { + _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + continue; + } + uint16_t priority = _mdns_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); + uint16_t weight = _mdns_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); + uint16_t port = _mdns_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); + _mdns_dbg_printf("%u %u %u %s.%s.\n", priority, weight, port, name->host, name->domain); + } else if (type == MDNS_TYPE_TXT) { + uint16_t i=0, y; + while (i < data_len) { + uint8_t partLen = data_ptr[i++]; + if ((i+partLen) > data_len) { + _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + break; + } + char txt[partLen+1]; + for (y=0; yhost, name->service, name->proto, name->domain); + size_t diff = new_ptr - old_ptr; + data_len -= diff; + data_ptr = new_ptr; + } + size_t i; + for (i=0; i +#include +#include "esp_console.h" +#include "argtable3/argtable3.h" +#include "mdns.h" + +static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; +static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; + +static void mdns_print_results(mdns_result_t * results) +{ + mdns_result_t * r = results; + mdns_ip_addr_t * a = NULL; + int i = 1, t; + while (r) { + printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]); + if (r->instance_name) { + printf(" PTR : %s\n", r->instance_name); + } + if (r->hostname) { + printf(" SRV : %s.local:%u\n", r->hostname, r->port); + } + if (r->txt_count) { + printf(" TXT : [%u] ", r->txt_count); + for (t=0; ttxt_count; t++) { + printf("%s=%s; ", r->txt[t].key, r->txt[t].value); + } + printf("\n"); + } + a = r->addr; + while (a) { + if (a->addr.type == IPADDR_TYPE_V6) { + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + r = r->next; + } +} + +static struct { + struct arg_str *hostname; + struct arg_int *timeout; + struct arg_end *end; +} mdns_query_a_args; + +static int cmd_mdns_query_a(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_query_a_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_a_args.end, argv[0]); + return 1; + } + + const char * hostname = mdns_query_a_args.hostname->sval[0]; + int timeout = mdns_query_a_args.timeout->ival[0]; + + if (!hostname || !hostname[0]) { + printf("ERROR: Hostname not supplied\n"); + return 1; + } + + if (timeout <= 0) { + timeout = 1000; + } + + printf("Query A: %s.local, Timeout: %d\n", hostname, timeout); + + struct ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(hostname, timeout, &addr); + if (err) { + if (err == ESP_ERR_NOT_FOUND) { + printf("ERROR: Host was not found!\n"); + return 0; + } + printf("ERROR: Query Failed\n"); + return 1; + } + + printf(IPSTR "\n", IP2STR(&addr)); + + return 0; +} + +static void register_mdns_query_a() +{ + mdns_query_a_args.hostname = arg_str1(NULL, NULL, "", "Hostname that is searched for"); + mdns_query_a_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_a_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_a", + .help = "Query MDNS for IPv4", + .hint = NULL, + .func = &cmd_mdns_query_a, + .argtable = &mdns_query_a_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) ); +} + +static int cmd_mdns_query_aaaa(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_query_a_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_a_args.end, argv[0]); + return 1; + } + + const char * hostname = mdns_query_a_args.hostname->sval[0]; + int timeout = mdns_query_a_args.timeout->ival[0]; + + if (!hostname || !hostname[0]) { + printf("ERROR: Hostname not supplied\n"); + return 1; + } + + if (timeout <= 0) { + timeout = 1000; + } + + printf("Query AAAA: %s.local, Timeout: %d\n", hostname, timeout); + + struct ip6_addr addr; + memset(addr.addr, 0, 16); + + esp_err_t err = mdns_query_aaaa(hostname, timeout, &addr); + if (err) { + if (err == ESP_ERR_NOT_FOUND) { + printf("Host was not found!\n"); + return 0; + } + printf("ERROR: Query Failed\n"); + return 1; + } + + printf(IPV6STR "\n", IPV62STR(addr)); + + return 0; +} + +static void register_mdns_query_aaaa() +{ + mdns_query_a_args.hostname = arg_str1(NULL, NULL, "", "Hostname that is searched for"); + mdns_query_a_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_a_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_aaaa", + .help = "Query MDNS for IPv6", + .hint = NULL, + .func = &cmd_mdns_query_aaaa, + .argtable = &mdns_query_a_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) ); +} + +static struct { + struct arg_str *instance; + struct arg_str *service; + struct arg_str *proto; + struct arg_int *timeout; + struct arg_end *end; +} mdns_query_srv_args; + +static int cmd_mdns_query_srv(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_query_srv_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_srv_args.end, argv[0]); + return 1; + } + + const char * instance = mdns_query_srv_args.instance->sval[0]; + const char * service = mdns_query_srv_args.service->sval[0]; + const char * proto = mdns_query_srv_args.proto->sval[0]; + int timeout = mdns_query_srv_args.timeout->ival[0]; + + if (timeout <= 0) { + timeout = 1000; + } + + printf("Query SRV: %s.%s.%s.local, Timeout: %d\n", instance, service, proto, timeout); + + mdns_result_t * results = NULL; + esp_err_t err = mdns_query_srv(instance, service, proto, timeout, &results); + if (err) { + printf("ERROR: Query 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_query_srv() +{ + mdns_query_srv_args.instance = arg_str1(NULL, NULL, "", "Instance to search for"); + mdns_query_srv_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); + mdns_query_srv_args.proto = arg_str1(NULL, NULL, "", "Protocol to search for (_tcp, _udp, etc.)"); + mdns_query_srv_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_srv_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_srv", + .help = "Query MDNS for Service SRV", + .hint = NULL, + .func = &cmd_mdns_query_srv, + .argtable = &mdns_query_srv_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) ); +} + +static struct { + struct arg_str *instance; + struct arg_str *service; + struct arg_str *proto; + struct arg_int *timeout; + struct arg_end *end; +} mdns_query_txt_args; + +static int cmd_mdns_query_txt(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_query_txt_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_txt_args.end, argv[0]); + return 1; + } + + const char * instance = mdns_query_txt_args.instance->sval[0]; + const char * service = mdns_query_txt_args.service->sval[0]; + const char * proto = mdns_query_txt_args.proto->sval[0]; + int timeout = mdns_query_txt_args.timeout->ival[0]; + + printf("Query TXT: %s.%s.%s.local, Timeout: %d\n", instance, service, proto, timeout); + + if (timeout <= 0) { + timeout = 5000; + } + + mdns_result_t * results = NULL; + esp_err_t err = mdns_query_txt(instance, service, proto, timeout, &results); + if (err) { + printf("ERROR: Query 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_query_txt() +{ + mdns_query_txt_args.instance = arg_str1(NULL, NULL, "", "Instance to search for"); + mdns_query_txt_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); + mdns_query_txt_args.proto = arg_str1(NULL, NULL, "", "Protocol to search for (_tcp, _udp, etc.)"); + mdns_query_txt_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_txt_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_txt", + .help = "Query MDNS for Service TXT", + .hint = NULL, + .func = &cmd_mdns_query_txt, + .argtable = &mdns_query_txt_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) ); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_int *timeout; + struct arg_int *max_results; + struct arg_end *end; +} mdns_query_ptr_args; + +static int cmd_mdns_query_ptr(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_query_ptr_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_ptr_args.end, argv[0]); + return 1; + } + + const char * service = mdns_query_ptr_args.service->sval[0]; + const char * proto = mdns_query_ptr_args.proto->sval[0]; + int timeout = mdns_query_ptr_args.timeout->ival[0]; + int max_results = mdns_query_ptr_args.max_results->ival[0]; + + if (timeout <= 0) { + timeout = 5000; + } + + if (max_results <= 0 || max_results > 255) { + max_results = 255; + } + + printf("Query PTR: %s.%s.local, Timeout: %d, Max Results: %d\n", service, proto, timeout, max_results); + + mdns_result_t * results = NULL; + esp_err_t err = mdns_query_ptr(service, proto, timeout, max_results, &results); + if (err) { + printf("ERROR: Query 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_query_ptr() +{ + mdns_query_ptr_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); + mdns_query_ptr_args.proto = arg_str1(NULL, NULL, "", "Protocol to search for (_tcp, _udp, etc.)"); + mdns_query_ptr_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_ptr_args.max_results = arg_int0("m", "max_results", "", "Maximum results returned"); + mdns_query_ptr_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_ptr", + .help = "Query MDNS for Service", + .hint = NULL, + .func = &cmd_mdns_query_ptr, + .argtable = &mdns_query_ptr_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) ); +} + +static struct { + struct arg_str *hostname; + struct arg_int *timeout; + struct arg_int *max_results; + struct arg_end *end; +} mdns_query_ip_args; + +static int cmd_mdns_query_ip(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_query_ip_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_ip_args.end, argv[0]); + return 1; + } + + const char * hostname = mdns_query_ip_args.hostname->sval[0]; + int timeout = mdns_query_ip_args.timeout->ival[0]; + int max_results = mdns_query_ip_args.max_results->ival[0]; + + if (!hostname || !hostname[0]) { + printf("ERROR: Hostname not supplied\n"); + return 1; + } + + if (timeout <= 0) { + timeout = 1000; + } + + if (max_results < 0 || max_results > 255) { + max_results = 255; + } + + printf("Query IP: %s.local, Timeout: %d, Max Results: %d\n", hostname, timeout, max_results); + + mdns_result_t * results = NULL; + esp_err_t err = mdns_query(hostname, NULL, NULL, MDNS_TYPE_ANY, timeout, max_results, &results); + if (err) { + printf("ERROR: Query 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_query_ip() +{ + mdns_query_ip_args.hostname = arg_str1(NULL, NULL, "", "Hostname that is searched for"); + mdns_query_ip_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_ip_args.max_results = arg_int0("m", "max_results", "", "Maximum results returned"); + mdns_query_ip_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_ip", + .help = "Query MDNS for IP", + .hint = NULL, + .func = &cmd_mdns_query_ip, + .argtable = &mdns_query_ip_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) ); +} + +static struct { + struct arg_str *instance; + struct arg_str *service; + struct arg_str *proto; + struct arg_int *timeout; + struct arg_int *max_results; + struct arg_end *end; +} mdns_query_svc_args; + +static int cmd_mdns_query_svc(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_query_svc_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_svc_args.end, argv[0]); + return 1; + } + + const char * instance = mdns_query_svc_args.instance->sval[0]; + const char * service = mdns_query_svc_args.service->sval[0]; + const char * proto = mdns_query_svc_args.proto->sval[0]; + int timeout = mdns_query_svc_args.timeout->ival[0]; + int max_results = mdns_query_svc_args.max_results->ival[0]; + + if (timeout <= 0) { + timeout = 5000; + } + + if (max_results < 0 || max_results > 255) { + max_results = 255; + } + + printf("Query SVC: %s.%s.%s.local, Timeout: %d, Max Results: %d\n", instance, service, proto, timeout, max_results); + + mdns_result_t * results = NULL; + esp_err_t err = mdns_query(instance, service, proto, MDNS_TYPE_ANY, timeout, max_results, &results); + if (err) { + printf("ERROR: Query 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_query_svc() +{ + mdns_query_svc_args.instance = arg_str1(NULL, NULL, "", "Instance to search for"); + mdns_query_svc_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); + mdns_query_svc_args.proto = arg_str1(NULL, NULL, "", "Protocol to search for (_tcp, _udp, etc.)"); + mdns_query_svc_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_svc_args.max_results = arg_int0("m", "max_results", "", "Maximum results returned"); + mdns_query_svc_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_svc", + .help = "Query MDNS for Service TXT & SRV", + .hint = NULL, + .func = &cmd_mdns_query_svc, + .argtable = &mdns_query_svc_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) ); +} + +static struct { + struct arg_str *hostname; + struct arg_str *instance; + struct arg_end *end; +} mdns_init_args; + +static int cmd_mdns_init(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_init_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_init_args.end, argv[0]); + return 1; + } + + ESP_ERROR_CHECK( mdns_init() ); + + if (mdns_init_args.hostname->sval[0]) { + ESP_ERROR_CHECK( mdns_hostname_set(mdns_init_args.hostname->sval[0]) ); + printf("MDNS: Hostname: %s\n", mdns_init_args.hostname->sval[0]); + } + + 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]); + } + + return 0; +} + +static void register_mdns_init() +{ + mdns_init_args.hostname = arg_str0("h", "hostname", "", "Hostname that the server will advertise"); + mdns_init_args.instance = arg_str0("i", "instance", "", "Default instance name for services"); + mdns_init_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_init", + .help = "Start MDNS Server", + .hint = NULL, + .func = &cmd_mdns_init, + .argtable = &mdns_init_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) ); +} + +static int cmd_mdns_free(int argc, char** argv) +{ + mdns_free(); + return 0; +} + +static void register_mdns_free() +{ + const esp_console_cmd_t cmd_free = { + .command = "mdns_free", + .help = "Stop MDNS Server", + .hint = NULL, + .func = &cmd_mdns_free, + .argtable = NULL + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_free) ); +} + +static struct { + struct arg_str *hostname; + struct arg_end *end; +} mdns_set_hostname_args; + +static int cmd_mdns_set_hostname(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_set_hostname_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_set_hostname_args.end, argv[0]); + return 1; + } + + if (mdns_set_hostname_args.hostname->sval[0] == NULL) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + ESP_ERROR_CHECK( mdns_hostname_set(mdns_set_hostname_args.hostname->sval[0]) ); + return 0; +} + +static void register_mdns_set_hostname() +{ + mdns_set_hostname_args.hostname = arg_str1(NULL, NULL, "", "Hostname that the server will advertise"); + mdns_set_hostname_args.end = arg_end(2); + + const esp_console_cmd_t cmd_set_hostname = { + .command = "mdns_set_hostname", + .help = "Set MDNS Server hostname", + .hint = NULL, + .func = &cmd_mdns_set_hostname, + .argtable = &mdns_set_hostname_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_set_hostname) ); +} + +static struct { + struct arg_str *instance; + struct arg_end *end; +} mdns_set_instance_args; + +static int cmd_mdns_set_instance(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_set_instance_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_set_instance_args.end, argv[0]); + return 1; + } + + if (mdns_set_instance_args.instance->sval[0] == NULL) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + ESP_ERROR_CHECK( mdns_instance_name_set(mdns_set_instance_args.instance->sval[0]) ); + return 0; +} + +static void register_mdns_set_instance() +{ + mdns_set_instance_args.instance = arg_str1(NULL, NULL, "", "Default instance name for services"); + mdns_set_instance_args.end = arg_end(2); + + const esp_console_cmd_t cmd_set_instance = { + .command = "mdns_set_instance", + .help = "Set MDNS Server Istance Name", + .hint = NULL, + .func = &cmd_mdns_set_instance, + .argtable = &mdns_set_instance_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_set_instance) ); +} + +static mdns_txt_item_t * _convert_items(const char **values, int count) +{ + int i=0,e; + const char * value = NULL; + mdns_txt_item_t * items = (mdns_txt_item_t*) malloc(sizeof(mdns_txt_item_t) * count); + if (!items) { + printf("ERROR: No Memory!\n"); + goto fail; + + } + memset(items, 0, sizeof(mdns_txt_item_t) * count); + + for (i=0; isval[0] || !mdns_add_args.proto->sval[0] || !mdns_add_args.port->ival[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + const char * instance = NULL; + if (mdns_add_args.instance->sval[0] && mdns_add_args.instance->sval[0][0]) { + instance = mdns_add_args.instance->sval[0]; + printf("MDNS: Service Instance: %s\n", instance); + } + 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); + if (!items) { + printf("ERROR: No Memory!\n"); + return 1; + + } + } + + 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; +} + +static void register_mdns_service_add() +{ + mdns_add_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_add_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_add_args.port = arg_int1(NULL, NULL, "", "Service Port"); + mdns_add_args.instance = arg_str0("i", "instance", "", "Instance name"); + mdns_add_args.txt = arg_strn(NULL, NULL, "item", 0, 30, "TXT Items (name=value)"); + mdns_add_args.end = arg_end(2); + + const esp_console_cmd_t cmd_add = { + .command = "mdns_service_add", + .help = "Add service to MDNS", + .hint = NULL, + .func = &cmd_mdns_service_add, + .argtable = &mdns_add_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_add) ); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_end *end; +} mdns_remove_args; + +static int cmd_mdns_service_remove(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_remove_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_remove_args.end, argv[0]); + return 1; + } + + if (!mdns_remove_args.service->sval[0] || !mdns_remove_args.proto->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + ESP_ERROR_CHECK( mdns_service_remove(mdns_remove_args.service->sval[0], mdns_remove_args.proto->sval[0]) ); + return 0; +} + +static void register_mdns_service_remove() +{ + mdns_remove_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_remove_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_remove_args.end = arg_end(2); + + const esp_console_cmd_t cmd_remove = { + .command = "mdns_service_remove", + .help = "Remove service from MDNS", + .hint = NULL, + .func = &cmd_mdns_service_remove, + .argtable = &mdns_remove_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_remove) ); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_str *instance; + struct arg_end *end; +} mdns_service_instance_set_args; + +static int cmd_mdns_service_instance_set(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_service_instance_set_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_service_instance_set_args.end, argv[0]); + return 1; + } + + if (!mdns_service_instance_set_args.service->sval[0] || !mdns_service_instance_set_args.proto->sval[0] || !mdns_service_instance_set_args.instance->sval[0]) { + printf("ERROR: Bad arguments!\n"); + 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; +} + +static void register_mdns_service_instance_set() +{ + mdns_service_instance_set_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_service_instance_set_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_service_instance_set_args.instance = arg_str1(NULL, NULL, "", "Instance name"); + mdns_service_instance_set_args.end = arg_end(2); + + const esp_console_cmd_t cmd_add = { + .command = "mdns_service_instance_set", + .help = "Set MDNS Service Instance Name", + .hint = NULL, + .func = &cmd_mdns_service_instance_set, + .argtable = &mdns_service_instance_set_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_add) ); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_int *port; + struct arg_end *end; +} mdns_service_port_set_args; + +static int cmd_mdns_service_port_set(int argc, char** argv) { + int nerrors = arg_parse(argc, argv, (void**) &mdns_service_port_set_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_service_port_set_args.end, argv[0]); + return 1; + } + + if (!mdns_service_port_set_args.service->sval[0] || !mdns_service_port_set_args.proto->sval[0] || !mdns_service_port_set_args.port->ival[0]) { + printf("ERROR: Bad arguments!\n"); + 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; +} + +static void register_mdns_service_port_set() +{ + mdns_service_port_set_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_service_port_set_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_service_port_set_args.port = arg_int1(NULL, NULL, "", "Service Port"); + mdns_service_port_set_args.end = arg_end(2); + + const esp_console_cmd_t cmd_add = { + .command = "mdns_service_port_set", + .help = "Set MDNS Service port", + .hint = NULL, + .func = &cmd_mdns_service_port_set, + .argtable = &mdns_service_port_set_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_add) ); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_str *txt; + struct arg_end *end; +} mdns_txt_replace_args; + +static int cmd_mdns_service_txt_replace(int argc, char** argv) +{ + mdns_txt_item_t * items = NULL; + int nerrors = arg_parse(argc, argv, (void**) &mdns_txt_replace_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_txt_replace_args.end, argv[0]); + return 1; + } + + if (!mdns_txt_replace_args.service->sval[0] || !mdns_txt_replace_args.proto->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + if (mdns_txt_replace_args.txt->count) { + items = _convert_items(mdns_txt_replace_args.txt->sval, mdns_txt_replace_args.txt->count); + if (!items) { + printf("ERROR: No Memory!\n"); + return 1; + + } + } + 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; +} + +static void register_mdns_service_txt_replace() +{ + mdns_txt_replace_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_txt_replace_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_txt_replace_args.txt = arg_strn(NULL, NULL, "item", 0, 30, "TXT Items (name=value)"); + mdns_txt_replace_args.end = arg_end(2); + + const esp_console_cmd_t cmd_txt_set = { + .command = "mdns_service_txt_replace", + .help = "Replace MDNS service TXT items", + .hint = NULL, + .func = &cmd_mdns_service_txt_replace, + .argtable = &mdns_txt_replace_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_txt_set) ); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_str *var; + struct arg_str *value; + struct arg_end *end; +} mdns_txt_set_args; + +static int cmd_mdns_service_txt_set(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_txt_set_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_txt_set_args.end, argv[0]); + return 1; + } + + if (!mdns_txt_set_args.service->sval[0] || !mdns_txt_set_args.proto->sval[0] || !mdns_txt_set_args.var->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + 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; +} + +static void register_mdns_service_txt_set() +{ + mdns_txt_set_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_txt_set_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_txt_set_args.var = arg_str1(NULL, NULL, "", "Item Name"); + mdns_txt_set_args.value = arg_str1(NULL, NULL, "", "Item Value"); + mdns_txt_set_args.end = arg_end(2); + + const esp_console_cmd_t cmd_txt_set = { + .command = "mdns_service_txt_set", + .help = "Add/Set MDNS service TXT item", + .hint = NULL, + .func = &cmd_mdns_service_txt_set, + .argtable = &mdns_txt_set_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_txt_set) ); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_str *var; + struct arg_end *end; +} mdns_txt_remove_args; + +static int cmd_mdns_service_txt_remove(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mdns_txt_remove_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_txt_remove_args.end, argv[0]); + return 1; + } + + if (!mdns_txt_remove_args.service->sval[0] || !mdns_txt_remove_args.proto->sval[0] || !mdns_txt_remove_args.var->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + ESP_ERROR_CHECK( mdns_service_txt_item_remove(mdns_txt_remove_args.service->sval[0], mdns_txt_remove_args.proto->sval[0], mdns_txt_remove_args.var->sval[0]) ); + return 0; +} + +static void register_mdns_service_txt_remove() +{ + mdns_txt_remove_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_txt_remove_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_txt_remove_args.var = arg_str1(NULL, NULL, "", "Item Name"); + mdns_txt_remove_args.end = arg_end(2); + + const esp_console_cmd_t cmd_txt_remove = { + .command = "mdns_service_txt_remove", + .help = "Remove MDNS service TXT item", + .hint = NULL, + .func = &cmd_mdns_service_txt_remove, + .argtable = &mdns_txt_remove_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_txt_remove) ); +} + +static int cmd_mdns_service_remove_all(int argc, char** argv) +{ + mdns_service_remove_all(); + return 0; +} + +static void register_mdns_service_remove_all() +{ + const esp_console_cmd_t cmd_free = { + .command = "mdns_service_remove_all", + .help = "Remove all MDNS services", + .hint = NULL, + .func = &cmd_mdns_service_remove_all, + .argtable = NULL + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_free) ); +} + +void mdns_console_register() +{ + register_mdns_init(); + register_mdns_free(); + register_mdns_set_hostname(); + register_mdns_set_instance(); + register_mdns_service_add(); + register_mdns_service_remove(); + register_mdns_service_instance_set(); + register_mdns_service_port_set(); + register_mdns_service_txt_replace(); + register_mdns_service_txt_set(); + register_mdns_service_txt_remove(); + register_mdns_service_remove_all(); + + register_mdns_query_a(); + register_mdns_query_aaaa(); + register_mdns_query_txt(); + register_mdns_query_srv(); + register_mdns_query_ptr(); + + register_mdns_query_ip(); + register_mdns_query_svc(); +} + diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h new file mode 100644 index 000000000..a3d9fa279 --- /dev/null +++ b/components/mdns/private_include/mdns_private.h @@ -0,0 +1,388 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef MDNS_PRIVATE_H_ +#define MDNS_PRIVATE_H_ + +//#define MDNS_ENABLE_DEBUG + +#ifdef MDNS_ENABLE_DEBUG +#define _mdns_dbg_printf(...) printf(__VA_ARGS__) +#endif + +#define MDNS_ANSWER_PTR_TTL 4500 +#define MDNS_ANSWER_TXT_TTL 4500 +#define MDNS_ANSWER_SRV_TTL 120 +#define MDNS_ANSWER_A_TTL 120 +#define MDNS_ANSWER_AAAA_TTL 120 + +#define MDNS_FLAGS_AUTHORITATIVE 0x8400 +#define MDNS_FLAGS_DISTRIBUTED 0x0200 + +#define MDNS_NAME_REF 0xC000 + +//custom type! only used by this implementation +//to help manage service discovery handling +#define MDNS_TYPE_SDPTR 0x0032 + +#define MDNS_CLASS_IN 0x0001 +#define MDNS_CLASS_ANY 0x00FF +#define MDNS_CLASS_IN_FLUSH_CACHE 0x8001 + +#define MDNS_ANSWER_ALL 0x3F +#define MDNS_ANSWER_PTR 0x08 +#define MDNS_ANSWER_TXT 0x04 +#define MDNS_ANSWER_SRV 0x02 +#define MDNS_ANSWER_A 0x01 +#define MDNS_ANSWER_AAAA 0x10 +#define MDNS_ANSWER_NSEC 0x20 +#define MDNS_ANSWER_SDPTR 0x80 + +#define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on +#define MDNS_SERVICE_STACK_DEPTH 4096 // Stack size for the service thread +#define MDNS_PACKET_QUEUE_LEN 16 // Maximum packets that can be queued for parsing +#define MDNS_ACTION_QUEUE_LEN 16 // Maximum actions pending to the server +#define MDNS_TXT_MAX_LEN 1024 // Maximum string length of text data in TXT record +#define MDNS_NAME_MAX_LEN 64 // Maximum string length of hostname, instance, service and proto +#define MDNS_NAME_BUF_LEN (MDNS_NAME_MAX_LEN+1) // Maximum char buffer size to hold hostname, instance, service or proto +#define MDNS_MAX_PACKET_SIZE 1460 // Maximum size of mDNS outgoing packet + +#define MDNS_HEAD_LEN 12 +#define MDNS_HEAD_ID_OFFSET 0 +#define MDNS_HEAD_FLAGS_OFFSET 2 +#define MDNS_HEAD_QUESTIONS_OFFSET 4 +#define MDNS_HEAD_ANSWERS_OFFSET 6 +#define MDNS_HEAD_SERVERS_OFFSET 8 +#define MDNS_HEAD_ADDITIONAL_OFFSET 10 + +#define MDNS_TYPE_OFFSET 0 +#define MDNS_CLASS_OFFSET 2 +#define MDNS_TTL_OFFSET 4 +#define MDNS_LEN_OFFSET 8 +#define MDNS_DATA_OFFSET 10 + +#define MDNS_SRV_PRIORITY_OFFSET 0 +#define MDNS_SRV_WEIGHT_OFFSET 2 +#define MDNS_SRV_PORT_OFFSET 4 +#define MDNS_SRV_FQDN_OFFSET 6 + +#define MDNS_TIMER_PERIOD_US 100000 + +#define MDNS_SERVICE_LOCK() xSemaphoreTake(_mdns_service_semaphore, portMAX_DELAY) +#define MDNS_SERVICE_UNLOCK() xSemaphoreGive(_mdns_service_semaphore) + +#define queueToEnd(type, queue, item) \ + if (!queue) { \ + queue = item; \ + } else { \ + type * _q = queue; \ + while (_q->next) { _q = _q->next; } \ + _q->next = item; \ + } + +#define queueDetach(type, queue, item) \ + if (queue) { \ + if (queue == item) { \ + queue = queue->next; \ + } else { \ + type * _q = queue; \ + while (_q->next && _q->next != item) { \ + _q = _q->next; \ + } \ + if (_q->next == item) { \ + _q->next = item->next; \ + item->next = NULL; \ + } \ + } \ + } + +#define queueFree(type, queue) while (queue) { type * _q = queue; queue = queue->next; free(_q); } + +#define PCB_STATE_IS_PROBING(s) (s->state > PCB_OFF && s->state < PCB_ANNOUNCE_1) +#define PCB_STATE_IS_ANNOUNCING(s) (s->state > PCB_PROBE_3 && s->state < PCB_RUNNING) +#define PCB_STATE_IS_RUNNING(s) (s->state == PCB_RUNNING) + +#define MDNS_SEARCH_LOCK() xSemaphoreTake(_mdns_server->search.lock, portMAX_DELAY) +#define MDNS_SEARCH_UNLOCK() xSemaphoreGive(_mdns_server->search.lock) + + +typedef enum { + PCB_OFF, PCB_DUP, PCB_INIT, + PCB_PROBE_1, PCB_PROBE_2, PCB_PROBE_3, + PCB_ANNOUNCE_1, PCB_ANNOUNCE_2, PCB_ANNOUNCE_3, + PCB_RUNNING +} mdns_pcb_state_t; + +typedef enum { + MDNS_ANSWER, MDNS_NS, MDNS_EXTRA +} mdns_parsed_recort_type_t; + +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_SERVICES_CLEAR, + ACTION_SEARCH_ADD, + ACTION_SEARCH_SEND, + ACTION_SEARCH_END, + ACTION_TX_HANDLE, + ACTION_RX_HANDLE, + ACTION_TASK_STOP, + ACTION_MAX +} mdns_action_type_t; + + +typedef struct { + uint16_t id; + union { + struct { + uint16_t qr :1; + uint16_t opCode :4; + uint16_t aa :1; + uint16_t tc :1; + uint16_t rd :1; + uint16_t ra :1; + uint16_t z :1; + uint16_t ad :1; + uint16_t cd :1; + uint16_t rCode :4;//response/error code + }; + uint16_t value; + } flags; + uint16_t questions; //QDCOUNT + uint16_t answers; //ANCOUNT + uint16_t servers; //NSCOUNT + uint16_t additional;//ARCOUNT +} mdns_header_t; + +typedef struct { + char host[MDNS_NAME_BUF_LEN]; + char service[MDNS_NAME_BUF_LEN]; + char proto[MDNS_NAME_BUF_LEN]; + char domain[MDNS_NAME_BUF_LEN]; + uint8_t parts; + uint8_t sub; +} mdns_name_t; + +typedef struct mdns_parsed_question_s { + struct mdns_parsed_question_s * next; + uint16_t type; + bool unicast; + char * host; + char * service; + char * proto; + char * domain; +} mdns_parsed_question_t; + +typedef struct mdns_parsed_record_s { + struct mdns_parsed_record_s * next; + mdns_parsed_recort_type_t record_type; + uint16_t type; + uint16_t clas; + uint8_t flush; + uint32_t ttl; + char * host; + char * service; + char * proto; + char * domain; + uint16_t data_len; + uint8_t *data; +} mdns_parsed_record_t; + +typedef struct { + tcpip_adapter_if_t tcpip_if; + mdns_ip_protocol_t ip_protocol; + //struct udp_pcb *pcb; + ip_addr_t src; + uint16_t src_port; + uint8_t multicast; + uint8_t authoritative; + uint8_t probe; + uint8_t discovery; + uint8_t distributed; + mdns_parsed_question_t * questions; + mdns_parsed_record_t * records; +} mdns_parsed_packet_t; + +typedef struct { + tcpip_adapter_if_t tcpip_if; + mdns_ip_protocol_t ip_protocol; + struct pbuf *pb; + ip_addr_t src; + ip_addr_t dest; + uint16_t src_port; + uint8_t multicast; +} mdns_rx_packet_t; + +typedef struct mdns_txt_linked_item_s { + const char * key; /*!< item key name */ + const char * value; /*!< item value string */ + struct mdns_txt_linked_item_s * next; /*!< next result, or NULL for the last result in the list */ +} mdns_txt_linked_item_t; + +typedef struct { + const char * instance; + const char * service; + const char * proto; + uint16_t priority; + uint16_t weight; + uint16_t port; + mdns_txt_linked_item_t * txt; +} mdns_service_t; + +typedef struct mdns_srv_item_s { + struct mdns_srv_item_s * next; + mdns_service_t * service; +} mdns_srv_item_t; + +typedef struct mdns_out_question_s { + struct mdns_out_question_s * next; + uint16_t type; + uint8_t unicast; + const char * host; + const char * service; + const char * proto; + const char * domain; +} mdns_out_question_t; + +typedef struct mdns_out_answer_s { + struct mdns_out_answer_s * next; + uint16_t type; + uint8_t bye; + uint8_t flush; + mdns_service_t * service; + const char * custom_instance; + const char * custom_service; + const char * custom_proto; +} mdns_out_answer_t; + +typedef struct mdns_tx_packet_s { + struct mdns_tx_packet_s * next; + uint32_t send_at; + tcpip_adapter_if_t tcpip_if; + mdns_ip_protocol_t ip_protocol; + ip_addr_t dst; + uint16_t port; + uint16_t flags; + uint8_t distributed; + mdns_out_question_t * questions; + mdns_out_answer_t * answers; + mdns_out_answer_t * servers; + mdns_out_answer_t * additional; +} mdns_tx_packet_t; + +typedef struct { + mdns_pcb_state_t state; + struct udp_pcb * pcb; + mdns_srv_item_t ** probe_services; + uint8_t probe_services_len; + uint8_t probe_ip; + uint8_t probe_running; + uint16_t failed_probes; +} mdns_pcb_t; + +typedef enum { + SEARCH_OFF, + SEARCH_INIT, + SEARCH_RUNNING, + SEARCH_MAX +} mdns_search_once_state_t; + +typedef struct mdns_search_once_s { + struct mdns_search_once_s * next; + + mdns_search_once_state_t state; + uint32_t started_at; + uint32_t sent_at; + uint32_t timeout; + SemaphoreHandle_t lock; + uint16_t type; + uint8_t max_results; + uint8_t num_results; + char * instance; + char * service; + char * proto; + mdns_result_t * result; +} mdns_search_once_t; + +typedef struct mdns_server_s { + struct { + mdns_pcb_t pcbs[MDNS_IP_PROTOCOL_MAX]; + } interfaces[TCPIP_ADAPTER_IF_MAX]; + const char * hostname; + const char * instance; + mdns_srv_item_t * services; + SemaphoreHandle_t lock; + QueueHandle_t action_queue; + mdns_tx_packet_t * tx_queue_head; + mdns_search_once_t * search_once; + esp_timer_handle_t timer_handle; +} mdns_server_t; + +typedef struct { + mdns_action_type_t type; + union { + char * hostname; + char * instance; + struct { + system_event_id_t event_id; + tcpip_adapter_if_t interface; + } sys_event; + struct { + mdns_srv_item_t * service; + } srv_add; + struct { + mdns_srv_item_t * service; + } 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; + uint8_t num_items; + mdns_txt_item_t * txt; + } srv_txt_replace; + struct { + mdns_srv_item_t * service; + char * key; + char * value; + } srv_txt_set; + struct { + mdns_srv_item_t * service; + char * key; + } srv_txt_del; + struct { + mdns_search_once_t * search; + } search_add; + struct { + mdns_tx_packet_t * packet; + } tx_handle; + struct { + mdns_rx_packet_t * packet; + } rx_handle; + } data; +} mdns_action_t; + +#endif /* MDNS_PRIVATE_H_ */ diff --git a/examples/protocols/mdns/README.md b/examples/protocols/mdns/README.md index 76dbdc17b..8cc56d835 100644 --- a/examples/protocols/mdns/README.md +++ b/examples/protocols/mdns/README.md @@ -2,4 +2,20 @@ Shows how to use mDNS to advertise lookup services and hosts +## Example workflow + +- mDNS is initialized with host name and instance name defined through `make menuconfig` and `_http._tcp` service is added to be advertised +- WiFi STA is started and trying to connect to the access point defined through `make menuconfig` +- The system event handler is used to pass the network events to mDNS so the service is aware when the interface comes up or down +- GPIO0 (BOOT Button) is initialized as pulled-up input that can be monitored for button press +- Example task is started to check if the button is pressed so it can execute the mDNS queries defined + +## Running the example + +- Run `make menuconfig` to configure the access point's SSID and Password and the default device mDNS host name and instance name +- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal +- Wait for WiFi to connec to your access point +- You can now ping the device at `[hostname].local` and browse for `_http._tcp` on the same network to find the advertised service +- Pressing the BOOT button will start quring the local network for the predefined in `check_button` hosts and services + See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c old mode 100644 new mode 100755 index 29e4e9b47..e6495b0eb --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -16,6 +16,9 @@ #include "esp_log.h" #include "nvs_flash.h" #include "mdns.h" +#include "driver/gpio.h" +#include +#include /* The examples use simple WiFi configuration that you can set via 'make menuconfig'. @@ -35,9 +38,11 @@ static EventGroupHandle_t wifi_event_group; /* The event group allows multiple bits for each event, but we only care about one event - are we connected to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; +const int IP4_CONNECTED_BIT = BIT0; +const int IP6_CONNECTED_BIT = BIT1; static const char *TAG = "mdns-test"; +static bool auto_reconnect = true; static esp_err_t event_handler(void *ctx, system_event_t *event) { @@ -50,17 +55,23 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); break; case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); + xEventGroupSetBits(wifi_event_group, IP4_CONNECTED_BIT); + break; + case SYSTEM_EVENT_AP_STA_GOT_IP6: + xEventGroupSetBits(wifi_event_group, IP6_CONNECTED_BIT); break; case SYSTEM_EVENT_STA_DISCONNECTED: /* This is a workaround as ESP32 WiFi libs don't currently auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + if (auto_reconnect) { + esp_wifi_connect(); + } + xEventGroupClearBits(wifi_event_group, IP4_CONNECTED_BIT | IP6_CONNECTED_BIT); break; default: break; } + mdns_handle_system_event(ctx, event); return ESP_OK; } @@ -84,101 +95,150 @@ static void initialise_wifi(void) ESP_ERROR_CHECK( esp_wifi_start() ); } -static void query_mdns_service(mdns_server_t * mdns, const char * service, const char * proto) +static void initialise_mdns(void) { - if(!mdns) { + //initialize mDNS + ESP_ERROR_CHECK( mdns_init() ); + //set mDNS hostname (required if you want to advertise services) + ESP_ERROR_CHECK( mdns_hostname_set(EXAMPLE_MDNS_HOSTNAME) ); + //set default mDNS instance name + ESP_ERROR_CHECK( mdns_instance_name_set(EXAMPLE_MDNS_INSTANCE) ); + + //structure with TXT records + mdns_txt_item_t serviceTxtData[3] = { + {"board","esp32"}, + {"u","user"}, + {"p","password"} + }; + + //initialize service + ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) ); + //add another TXT item + ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") ); + //change TXT item value + ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "u", "admin") ); +} + +static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; +static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; + +static void mdns_print_results(mdns_result_t * results){ + mdns_result_t * r = results; + mdns_ip_addr_t * a = NULL; + int i = 1, t; + while(r){ + printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]); + if(r->instance_name){ + printf(" PTR : %s\n", r->instance_name); + } + if(r->hostname){ + printf(" SRV : %s.local:%u\n", r->hostname, r->port); + } + if(r->txt_count){ + printf(" TXT : [%u] ", r->txt_count); + for(t=0; ttxt_count; t++){ + printf("%s=%s; ", r->txt[t].key, r->txt[t].value); + } + printf("\n"); + } + a = r->addr; + while(a){ + if(a->addr.type == MDNS_IP_PROTOCOL_V6){ + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + r = r->next; + } + +} + +static void query_mdns_service(const char * service_name, const char * proto) +{ + ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); + + mdns_result_t * results = NULL; + esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); + if(err){ + ESP_LOGE(TAG, "Query Failed"); return; } - uint32_t res; - if (!proto) { - ESP_LOGI(TAG, "Host Lookup: %s", service); - res = mdns_query(mdns, service, 0, 1000); - if (res) { - size_t i; - for(i=0; iaddr), IPV62STR(r->addrv6)); - } - } - mdns_result_free(mdns); - } else { - ESP_LOGI(TAG, " Not Found"); - } - } else { - ESP_LOGI(TAG, "Service Lookup: %s.%s ", service, proto); - res = mdns_query(mdns, service, proto, 1000); - if (res) { - size_t i; - for(i=0; ihost)?r->host:"", (r->instance)?r->instance:"", - IP2STR(&r->addr), IPV62STR(r->addrv6), - r->port, (r->txt)?r->txt:""); - } - } - mdns_result_free(mdns); - } + if(!results){ + ESP_LOGW(TAG, "No results found!"); + return; } + + mdns_print_results(results); + mdns_query_results_free(results); +} + +static void query_mdns_host(const char * host_name) +{ + ESP_LOGI(TAG, "Query A: %s.local", host_name); + + struct ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(host_name, 2000, &addr); + if(err){ + if(err == ESP_ERR_NOT_FOUND){ + ESP_LOGW(TAG, "Host was not found!"); + return; + } + ESP_LOGE(TAG, "Query Failed"); + return; + } + + ESP_LOGI(TAG, IPSTR, IP2STR(&addr)); +} + +static void initialise_button(void) +{ + gpio_config_t io_conf; + io_conf.intr_type = GPIO_PIN_INTR_DISABLE; + io_conf.pin_bit_mask = 1; + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pull_up_en = 1; + io_conf.pull_down_en = 0; + gpio_config(&io_conf); +} + +static void check_button(void) +{ + static bool old_level = true; + bool new_level = gpio_get_level(GPIO_NUM_0); + if (!new_level && old_level) { + query_mdns_host("esp32"); + query_mdns_service("_arduino", "_tcp"); + query_mdns_service("_http", "_tcp"); + query_mdns_service("_printer", "_tcp"); + query_mdns_service("_ipp", "_tcp"); + query_mdns_service("_afpovertcp", "_tcp"); + query_mdns_service("_smb", "_tcp"); + query_mdns_service("_ftp", "_tcp"); + query_mdns_service("_nfs", "_tcp"); + } + old_level = new_level; } static void mdns_example_task(void *pvParameters) { - mdns_server_t * mdns = NULL; + /* Wait for the callback to set the CONNECTED_BIT in the event group. */ + xEventGroupWaitBits(wifi_event_group, IP4_CONNECTED_BIT | IP6_CONNECTED_BIT, + false, true, portMAX_DELAY); while(1) { - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); - - if (!mdns) { - esp_err_t err = mdns_init(TCPIP_ADAPTER_IF_STA, &mdns); - if (err) { - ESP_LOGE(TAG, "Failed starting MDNS: %u", err); - continue; - } - - ESP_ERROR_CHECK( mdns_set_hostname(mdns, EXAMPLE_MDNS_HOSTNAME) ); - ESP_ERROR_CHECK( mdns_set_instance(mdns, EXAMPLE_MDNS_INSTANCE) ); - - const char * arduTxtData[4] = { - "board=esp32", - "tcp_check=no", - "ssh_upload=no", - "auth_upload=no" - }; - - ESP_ERROR_CHECK( mdns_service_add(mdns, "_arduino", "_tcp", 3232) ); - ESP_ERROR_CHECK( mdns_service_txt_set(mdns, "_arduino", "_tcp", 4, arduTxtData) ); - ESP_ERROR_CHECK( mdns_service_add(mdns, "_http", "_tcp", 80) ); - ESP_ERROR_CHECK( mdns_service_instance_set(mdns, "_http", "_tcp", "ESP32 WebServer") ); - ESP_ERROR_CHECK( mdns_service_add(mdns, "_smb", "_tcp", 445) ); - } else { - query_mdns_service(mdns, "esp32", NULL); - query_mdns_service(mdns, "_arduino", "_tcp"); - query_mdns_service(mdns, "_http", "_tcp"); - query_mdns_service(mdns, "_printer", "_tcp"); - query_mdns_service(mdns, "_ipp", "_tcp"); - query_mdns_service(mdns, "_afpovertcp", "_tcp"); - query_mdns_service(mdns, "_smb", "_tcp"); - query_mdns_service(mdns, "_ftp", "_tcp"); - query_mdns_service(mdns, "_nfs", "_tcp"); - } - - ESP_LOGI(TAG, "Restarting in 10 seconds!"); - vTaskDelay(10000 / portTICK_PERIOD_MS); - ESP_LOGI(TAG, "Starting again!"); + check_button(); + vTaskDelay(50 / portTICK_PERIOD_MS); } } void app_main() { ESP_ERROR_CHECK( nvs_flash_init() ); + initialise_mdns(); initialise_wifi(); + initialise_button(); xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL); } From ef924f1aa5c9a4230f55e67fe41a7f649d8fd12b Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 17 Jan 2018 19:06:42 +0200 Subject: [PATCH 015/289] mdns: Fix issue with some mDNS parsers Some mDNS parser have issue with zero terminated TXT lists. This fix targets to overcome this issue. Found and tested with jmdns. * Original commit: espressif/esp-idf@51dde19a765533af67fc7be21f116641773a9be4 --- components/mdns/mdns.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 061c63148..bc8a94e3f 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -803,7 +803,7 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns record_length += part_length; uint16_t data_len_location = *index - 2; - uint16_t data_len = 1; + uint16_t data_len = 0; char * tmp; mdns_txt_linked_item_t * txt = service->txt; @@ -820,9 +820,11 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns } txt = txt->next; } - - packet[*index] = 0; - *index = *index + 1; + if (!data_len) { + data_len = 1; + packet[*index] = 0; + *index = *index + 1; + } _mdns_set_u16(packet, data_len_location, data_len); record_length += data_len; return record_length; From bce7d5231c54d3a94cd927d17776e5160a9164c1 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 22 Jan 2018 13:17:59 +0100 Subject: [PATCH 016/289] mdns: Fix case where service is NULL and that will cause exception * Original commit: espressif/esp-idf@4fa130ae4fb5de99ddddc5a7bed7e26ae645591c --- components/mdns/mdns.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index bc8a94e3f..13368c3ed 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1304,6 +1304,10 @@ static mdns_tx_packet_t * _mdns_get_next_pcb_packet(tcpip_adapter_if_t tcpip_if, */ static void _mdns_remove_scheduled_answer(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t * service) { + mdns_srv_item_t s = {NULL, NULL}; + if (!service) { + service = &s; + } mdns_tx_packet_t * q = _mdns_server->tx_queue_head; while (q) { if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol && q->distributed) { @@ -1336,6 +1340,10 @@ static void _mdns_dealloc_answer(mdns_out_answer_t ** destnation, uint16_t type, if (!d) { return; } + mdns_srv_item_t s = {NULL, NULL}; + if (!service) { + service = &s; + } if (d->type == type && d->service == service->service) { *destnation = d->next; free(d); From 26f00e8ddbcc2299633ec83b8f5008facfcd3cc6 Mon Sep 17 00:00:00 2001 From: krzychb Date: Sat, 3 Feb 2018 22:12:13 +0100 Subject: [PATCH 017/289] Moved files into separate folders per 'en' and 'zh_CN' language version and linked 'zh_CN' files back to 'en' files if translation is not yet available * Original commit: espressif/esp-idf@097adc3a33ceae214dcb26b3357261aa6f783895 --- docs/en/api-reference/protocols/mdns.rst | 188 ++++++++++++++++++++ docs/zh_CN/api-reference/protocols/mdns.rst | 1 + 2 files changed, 189 insertions(+) create mode 100644 docs/en/api-reference/protocols/mdns.rst create mode 100644 docs/zh_CN/api-reference/protocols/mdns.rst diff --git a/docs/en/api-reference/protocols/mdns.rst b/docs/en/api-reference/protocols/mdns.rst new file mode 100644 index 000000000..d01e24149 --- /dev/null +++ b/docs/en/api-reference/protocols/mdns.rst @@ -0,0 +1,188 @@ +mDNS Service +============ + +Overview +-------- + +mDNS is a multicast UDP service that is used to provide local network service and host discovery. + +mDNS is installed by default on most operating systems or is available as separate package. On ``Mac OS`` it is installed by default and is called ``Bonjour``. Apple releases an installer for ``Windows`` that can be found `on Apple's support page `_. On ``Linux``, mDNS is provided by `avahi `_ and is usually installed by default. + +mDNS Properties +^^^^^^^^^^^^^^^ + + * ``hostname``: the hostname that the device will respond to. If not set, the ``hostname`` will be read from the interface. Example: ``my-esp32`` will resolve to ``my-esp32.local`` + * ``default_instance``: friendly name for your device, like ``Jhon's ESP32 Thing``. If not set, ``hostname`` will be used. + +Example method to start mDNS for the STA interface and set ``hostname`` and ``default_instance``: + +.. highlight:: c + +:: + + void start_mdns_service() + { + //initialize mDNS service + esp_err_t err = mdns_init(); + if (err) { + printf("MDNS Init failed: %d\n", err); + return; + } + + //set hostname + mdns_hostname_set("my-esp32"); + //set default instance + mdns_instance_name_set("Jhon's ESP32 Thing"); + } + +mDNS Services +^^^^^^^^^^^^^ + +mDNS can advertise information about network services that your device offers. Each service is defined by a few properties. + + * ``instance_name``: friendly name for your service, like ``Jhon's ESP32 Web Server``. If not defined, ``default_instance`` will be used. + * ``service_type``: (required) service type, prepended with underscore. Some common types can be found `here `_. + * ``proto``: (required) protocol that the service runs on, prepended with underscore. Example: ``_tcp`` or ``_udp`` + * ``port``: (required) network port that the service runs on + * ``txt``: ``{var, val}`` array of strings, used to define properties for your service + +Example method to add a few services and different properties:: + + void add_mdns_services() + { + //add our services + mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0); + mdns_service_add(NULL, "_arduino", "_tcp", 3232, NULL, 0); + mdns_service_add(NULL, "_myservice", "_udp", 1234, NULL, 0); + + //NOTE: services must be added before their properties can be set + //use custom instance for the web server + mdns_service_instance_name_set("_http", "_tcp", "Jhon's ESP32 Web Server"); + + mdns_txt_item_t serviceTxtData[3] = { + {"board","esp32"}, + {"u","user"}, + {"p","password"} + }; + //set txt data for service (will free and replace current data) + mdns_service_txt_set("_http", "_tcp", serviceTxtData, 3); + + //change service port + mdns_service_port_set("_myservice", "_udp", 4321); + } + +mDNS Query +^^^^^^^^^^ + +mDNS provides methods for browsing for services and resolving host's IP/IPv6 addresses. + +Results for services are returned as a linked list of ``mdns_result_t`` objects. + +Example method to resolve host IPs:: + + void resolve_mdns_host(const char * host_name) + { + printf("Query A: %s.local", host_name); + + struct ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(host_name, 2000, &addr); + if(err){ + if(err == ESP_ERR_NOT_FOUND){ + printf("Host was not found!"); + return; + } + printf("Query Failed"); + return; + } + + printf(IPSTR, IP2STR(&addr)); + } + +Example method to resolve local services:: + + static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; + static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; + + void mdns_print_results(mdns_result_t * results){ + mdns_result_t * r = results; + mdns_ip_addr_t * a = NULL; + int i = 1, t; + while(r){ + printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]); + if(r->instance_name){ + printf(" PTR : %s\n", r->instance_name); + } + if(r->hostname){ + printf(" SRV : %s.local:%u\n", r->hostname, r->port); + } + if(r->txt_count){ + printf(" TXT : [%u] ", r->txt_count); + for(t=0; ttxt_count; t++){ + printf("%s=%s; ", r->txt[t].key, r->txt[t].value); + } + printf("\n"); + } + a = r->addr; + while(a){ + if(a->addr.type == MDNS_IP_PROTOCOL_V6){ + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + r = r->next; + } + + } + + void find_mdns_service(const char * service_name, const char * proto) + { + ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); + + mdns_result_t * results = NULL; + esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); + if(err){ + ESP_LOGE(TAG, "Query Failed"); + return; + } + if(!results){ + ESP_LOGW(TAG, "No results found!"); + return; + } + + mdns_print_results(results); + mdns_query_results_free(results); + } + +Example of using the methods above:: + + void my_app_some_method(){ + //search for esp32-mdns.local + resolve_mdns_host("esp32-mdns"); + + //search for HTTP servers + find_mdns_service("_http", "_tcp"); + //or file servers + find_mdns_service("_smb", "_tcp"); //windows sharing + find_mdns_service("_afpovertcp", "_tcp"); //apple sharing + find_mdns_service("_nfs", "_tcp"); //NFS server + find_mdns_service("_ftp", "_tcp"); //FTP server + //or networked printer + find_mdns_service("_printer", "_tcp"); + find_mdns_service("_ipp", "_tcp"); + } + +Application Example +------------------- + +mDNS server/scanner example: :example:`protocols/mdns`. + +API Reference +------------- + +.. include:: /_build/inc/mdns.inc + + diff --git a/docs/zh_CN/api-reference/protocols/mdns.rst b/docs/zh_CN/api-reference/protocols/mdns.rst new file mode 100644 index 000000000..3f82c5d80 --- /dev/null +++ b/docs/zh_CN/api-reference/protocols/mdns.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/protocols/mdns.rst \ No newline at end of file From 9ebd9852ca5c8d7aba7b293b032118cd81318baa Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Thu, 22 Feb 2018 14:48:53 +0100 Subject: [PATCH 018/289] Examples: Demonstrate the usage of esp_err_to_name * Original commit: espressif/esp-idf@27a63c492f289b2007731b9e6c922b61ff66ac4c --- examples/protocols/mdns/main/mdns_example_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index e6495b0eb..44984c268 100755 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -162,7 +162,7 @@ static void query_mdns_service(const char * service_name, const char * proto) mdns_result_t * results = NULL; esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); if(err){ - ESP_LOGE(TAG, "Query Failed"); + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); return; } if(!results){ @@ -184,10 +184,10 @@ static void query_mdns_host(const char * host_name) esp_err_t err = mdns_query_a(host_name, 2000, &addr); if(err){ if(err == ESP_ERR_NOT_FOUND){ - ESP_LOGW(TAG, "Host was not found!"); + ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err)); return; } - ESP_LOGE(TAG, "Query Failed"); + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); return; } From 7784d002fc3c7da508b94850f0df9f74615a8218 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 2 Apr 2018 22:24:28 +0300 Subject: [PATCH 019/289] Fix exception when service is removed while there are pending packets that depend on it * Original commit: espressif/esp-idf@421c6f154b10d9253b78875ab28ee6bdcaaaf3c0 --- components/mdns/mdns.c | 279 +++++++++++++++++++++++++++++++---------- 1 file changed, 214 insertions(+), 65 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 13368c3ed..da00d7e5d 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -50,6 +50,10 @@ static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static inline bool _str_null_or_empty(const char * str){ + return (str == NULL || *str == 0); +} + /* * @brief Appends/increments a number to name/instance in case of collision * */ @@ -411,6 +415,26 @@ static size_t _udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_ return len; } +/** + * @brief Get the service name of a service + */ +static const char * _mdns_get_service_instance_name(mdns_service_t * service) +{ + if (service && !_str_null_or_empty(service->instance)) { + return service->instance; + } + + if (_mdns_server && !_str_null_or_empty(_mdns_server->instance)) { + return _mdns_server->instance; + } + + if (_mdns_server && !_str_null_or_empty(_mdns_server->hostname)) { + return _mdns_server->hostname; + } + + return NULL; +} + /** * @brief reads MDNS FQDN into mdns_name_t structure * FQDN is in format: [hostname.|[instance.]_service._proto.]local. @@ -783,13 +807,15 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns uint16_t record_length = 0; uint8_t part_length; - str[0] = (service->instance)?service->instance - :(_mdns_server->instance)?_mdns_server->instance - :_mdns_server->hostname; + str[0] = _mdns_get_service_instance_name(service); str[1] = service->service; str[2] = service->proto; str[3] = MDNS_DEFAULT_DOMAIN; + if (!str[0]) { + return 0; + } + part_length = _mdns_append_fqdn(packet, index, str, 4); if (!part_length) { return 0; @@ -846,13 +872,15 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns uint16_t record_length = 0; uint8_t part_length; - str[0] = (service->instance)?service->instance - :(_mdns_server->instance)?_mdns_server->instance - :_mdns_server->hostname; + str[0] = _mdns_get_service_instance_name(service); str[1] = service->service; str[2] = service->proto; str[3] = MDNS_DEFAULT_DOMAIN; + if (!str[0]) { + return 0; + } + part_length = _mdns_append_fqdn(packet, index, str, 4); if (!part_length) { return 0; @@ -877,6 +905,11 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns str[0] = _mdns_server->hostname; str[1] = MDNS_DEFAULT_DOMAIN; + + if (_str_null_or_empty(str[0])) { + return 0; + } + part_length = _mdns_append_fqdn(packet, index, str, 2); if (!part_length) { return 0; @@ -906,6 +939,11 @@ static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, uint32 str[0] = _mdns_server->hostname; str[1] = MDNS_DEFAULT_DOMAIN; + if (_str_null_or_empty(str[0])) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, str, 2); if (!part_length) { return 0; @@ -951,6 +989,11 @@ static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, uin str[0] = _mdns_server->hostname; str[1] = MDNS_DEFAULT_DOMAIN; + if (_str_null_or_empty(str[0])) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, str, 2); if (!part_length) { return 0; @@ -1067,9 +1110,7 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ if (answer->service) { return _mdns_append_ptr_record(packet, index, - (answer->service->instance)?answer->service->instance - :(_mdns_server->instance)?_mdns_server->instance - :_mdns_server->hostname, + _mdns_get_service_instance_name(answer->service), answer->service->service, answer->service->proto, answer->flush, answer->bye) > 0; } else { @@ -1536,25 +1577,23 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(tcpip_adapter_if_t tcpip_if, q->next = NULL; q->unicast = first; q->type = MDNS_TYPE_ANY; - q->host = (services[i]->service->instance)?services[i]->service->instance - :(_mdns_server->instance)?_mdns_server->instance - :_mdns_server->hostname; + q->host = _mdns_get_service_instance_name(services[i]->service); q->service = services[i]->service->service; q->proto = services[i]->service->proto; q->domain = MDNS_DEFAULT_DOMAIN; - if (_mdns_question_exists(q, packet->questions)) { + if (!q->host || _mdns_question_exists(q, packet->questions)) { free(q); } else { queueToEnd(mdns_out_question_t, packet->questions, q); } - if (!_mdns_alloc_answer(&packet->servers, MDNS_TYPE_SRV, services[i]->service, false, false)) { + if (!q->host || !_mdns_alloc_answer(&packet->servers, MDNS_TYPE_SRV, services[i]->service, false, false)) { _mdns_free_tx_packet(packet); return NULL; } } - if (include_ip) { + if (include_ip && !_str_null_or_empty(_mdns_server->hostname)) { mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); if (!q) { _mdns_free_tx_packet(packet); @@ -1691,7 +1730,7 @@ static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); - if (!_mdns_server->hostname || !_mdns_server->hostname[0]) { + if (_str_null_or_empty(_mdns_server->hostname)) { pcb->state = PCB_RUNNING; return; } @@ -1766,7 +1805,7 @@ static void _mdns_restart_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip static void _mdns_send_bye(mdns_srv_item_t ** services, size_t len, bool include_ip) { uint8_t i, j; - if (!_mdns_server->hostname || !_mdns_server->hostname[0]) { + if (_str_null_or_empty(_mdns_server->hostname)) { return; } @@ -1810,7 +1849,7 @@ static void _mdns_announce_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t i } } else if (_pcb->state == PCB_RUNNING) { - if (!_mdns_server->hostname || !_mdns_server->hostname[0]) { + if (_str_null_or_empty(_mdns_server->hostname)) { return; } @@ -2049,6 +2088,114 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * return s; } +/** + * @brief Remove and free service answer from answer list (destination) + */ +static void _mdns_dealloc_scheduled_service_answers(mdns_out_answer_t ** destination, mdns_service_t * service) +{ + mdns_out_answer_t * d = *destination; + if (!d) { + return; + } + while (d && d->service == service) { + *destination = d->next; + free(d); + d = *destination; + } + while (d && d->next) { + mdns_out_answer_t * a = d->next; + if (a->service == service) { + d->next = a->next; + free(a); + } else { + d = d->next; + } + } +} + +/** + * @brief Find, remove and free answers and scheduled packets for service + */ +static void _mdns_remove_scheduled_service_packets(mdns_service_t * service) +{ + mdns_tx_packet_t * p = NULL; + mdns_tx_packet_t * q = _mdns_server->tx_queue_head; + while (q) { + bool had_answers = (q->answers != NULL); + + _mdns_dealloc_scheduled_service_answers(&(q->answers), service); + _mdns_dealloc_scheduled_service_answers(&(q->additional), service); + _mdns_dealloc_scheduled_service_answers(&(q->servers), service); + + + mdns_pcb_t * _pcb = &_mdns_server->interfaces[q->tcpip_if].pcbs[q->ip_protocol]; + if(_pcb->pcb) { + if (PCB_STATE_IS_PROBING(_pcb)) { + uint8_t i; + //check if we are probing this service + for (i=0; i<_pcb->probe_services_len; i++) { + mdns_srv_item_t * s = _pcb->probe_services[i]; + if (s->service == service){ + break; + } + } + if (i < _pcb->probe_services_len) { + if (_pcb->probe_services_len > 1) { + uint8_t n; + for (n=(i+1); n<_pcb->probe_services_len; n++) { + _pcb->probe_services[n-1] = _pcb->probe_services[n]; + } + _pcb->probe_services_len--; + } else { + _pcb->probe_services_len = 0; + free(_pcb->probe_services); + _pcb->probe_services = NULL; + if (!_pcb->probe_ip) { + _pcb->probe_running = false; + _pcb->state = PCB_RUNNING; + } + } + + if (q->questions) { + mdns_out_question_t * qsn = NULL; + mdns_out_question_t * qs = q->questions; + if (qs->type == MDNS_TYPE_ANY + && qs->service && strcmp(qs->service, service->service) == 0 + && qs->proto && strcmp(qs->proto, service->proto) == 0) + { + q->questions = q->questions->next; + free(qs); + } else while (qs->next) { + qsn = qs->next; + if (qsn->type == MDNS_TYPE_ANY + && qsn->service && strcmp(qsn->service, service->service) == 0 + && qsn->proto && strcmp(qsn->proto, service->proto) == 0) + { + qs->next = qsn->next; + free(qsn); + break; + } + qs = qs->next; + } + } + } + } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { + //if answers were cleared, set to running + if (had_answers && q->answers == NULL) { + _pcb->state = PCB_RUNNING; + } + } + } + + p = q; + q = q->next; + if(!p->questions && !p->answers && !p->additional && !p->servers){ + queueDetach(mdns_tx_packet_t, _mdns_server->tx_queue_head, p); + _mdns_free_tx_packet(p); + } + } +} + /** * @brief free service memory * @@ -2059,6 +2206,7 @@ static void _mdns_free_service(mdns_service_t * service) if (!service) { return; } + _mdns_remove_scheduled_service_packets(service); free((char *)service->instance); free((char *)service->service); free((char *)service->proto); @@ -2083,6 +2231,10 @@ static void _mdns_free_service(mdns_service_t * service) */ static int _mdns_check_srv_collision(mdns_service_t * service, uint16_t priority, uint16_t weight, uint16_t port, const char * host, const char * domain) { + if (_str_null_or_empty(_mdns_server->hostname)) { + return 0; + } + size_t our_host_len = strlen(_mdns_server->hostname); size_t our_len = 14 + our_host_len; @@ -2290,20 +2442,23 @@ static bool _mdns_name_is_discovery(mdns_name_t * name, uint16_t type) static bool _mdns_name_is_ours(mdns_name_t * name) { //domain have to be "local" - if (!name->domain || !name->domain[0] || strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN)) { + if (_str_null_or_empty(name->domain) || strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN)) { return false; } //if service and proto are empty, host must match out hostname - if ((!name->service || !name->service[0]) && (!name->proto || !name->proto[0])) { - if (name->host && name->host[0] && strcasecmp(name->host, _mdns_server->hostname) == 0) { + if (_str_null_or_empty(name->service) && _str_null_or_empty(name->proto)) { + if (!_str_null_or_empty(name->host) + && !_str_null_or_empty(_mdns_server->hostname) + && strcasecmp(name->host, _mdns_server->hostname) == 0) + { return true; } return false; } //if service or proto is empty, name is invalid - if ((!name->service || !name->service[0]) || (!name->proto || !name->proto[0])) { + if (_str_null_or_empty(name->service) || _str_null_or_empty(name->proto)) { return false; } @@ -2314,20 +2469,14 @@ static bool _mdns_name_is_ours(mdns_name_t * name) } //if host is empty and we have service, we have success - if (!name->host || !name->host[0]) { + if (_str_null_or_empty(name->host)) { return true; } //OK we have host in the name. find what is the instance of the service - const char * instance = service->service->instance; + const char * instance = _mdns_get_service_instance_name(service->service); if (instance == NULL) { - if (_mdns_server->instance && _mdns_server->instance[0]) { - instance = _mdns_server->instance; - } else if (_mdns_server->hostname && _mdns_server->hostname[0]) { - instance = _mdns_server->hostname; - } else { - return false; - } + return false; } //compare the instance against the name @@ -2420,14 +2569,8 @@ static bool _mdns_question_matches(mdns_parsed_question_t * question, uint16_t t return true; } } else if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { - const char * name = service->service->instance; - if (!name) { - name = _mdns_server->instance; - } - if (!name) { - name = _mdns_server->hostname; - } - if (!strcasecmp(name, question->host) + const char * name = _mdns_get_service_instance_name(service->service); + if (name && !strcasecmp(name, question->host) && !strcasecmp(service->service->service, question->service) && !strcasecmp(service->service->proto, question->proto) && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { @@ -2648,6 +2791,12 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) return; } + //if we have not set the hostname, we can not answer questions + if (header.questions && _str_null_or_empty(_mdns_server->hostname)) { + free(parsed_packet); + return; + } + parsed_packet->tcpip_if = packet->tcpip_if; parsed_packet->ip_protocol = packet->ip_protocol; parsed_packet->multicast = packet->multicast; @@ -2859,14 +3008,14 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) do_not_reply = true; if (_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; - if (service->service->instance) { + if (!_str_null_or_empty(service->service->instance)) { char * new_instance = _mdns_mangle_name((char *)service->service->instance); if (new_instance) { free((char *)service->service->instance); service->service->instance = new_instance; } _mdns_probe_all_pcbs(&service, 1, false, false); - } else if (_mdns_server->instance) { + } else if (!_str_null_or_empty(_mdns_server->instance)) { char * new_instance = _mdns_mangle_name((char *)_mdns_server->instance); if (new_instance) { free((char *)_mdns_server->instance); @@ -3182,7 +3331,7 @@ static mdns_search_once_t * _mdns_search_init(const char * name, const char * se return NULL; } - if (name) { + if (!_str_null_or_empty(name)) { search->instance = strndup(name, MDNS_NAME_BUF_LEN-1); if (!search->instance) { _mdns_search_free(search); @@ -3190,7 +3339,7 @@ static mdns_search_once_t * _mdns_search_init(const char * name, const char * se } } - if (service) { + if (!_str_null_or_empty(service)) { search->service = strndup(service, MDNS_NAME_BUF_LEN-1); if (!search->service) { _mdns_search_free(search); @@ -3198,7 +3347,7 @@ static mdns_search_once_t * _mdns_search_init(const char * name, const char * se } } - if (proto) { + if (!_str_null_or_empty(proto)) { search->proto = strndup(proto, MDNS_NAME_BUF_LEN-1); if (!search->proto) { _mdns_search_free(search); @@ -3343,7 +3492,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * } else if (search->type == MDNS_TYPE_PTR) { r = search->result; while (r) { - if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && r->hostname && !strcasecmp(hostname, r->hostname)) { + if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { _mdns_result_add_ip(r, ip); break; } @@ -3359,7 +3508,7 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, { mdns_result_t * r = search->result; while (r) { - if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && r->instance_name && !strcasecmp(instance, r->instance_name)) { + if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { return r; } r = r->next; @@ -3394,7 +3543,7 @@ static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char { mdns_result_t * r = search->result; while (r) { - if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && r->hostname && !strcasecmp(hostname, r->hostname)) { + if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { return; } r = r->next; @@ -3488,7 +3637,7 @@ static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * s, mdns_ } r = s->result; while (r) { - if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && r->hostname && !strcasecmp(name->host, r->hostname)) { + if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { return s; } r = r->next; @@ -3755,7 +3904,7 @@ static void _mdns_execute_action(mdns_action_t * action) break; case ACTION_SERVICE_INSTANCE_SET: - if (action->data.srv_port.service->service->instance) { + if (action->data.srv_instance.service->service->instance) { _mdns_send_bye(&action->data.srv_instance.service, 1, false); free((char*)action->data.srv_instance.service->service->instance); } @@ -4221,7 +4370,7 @@ esp_err_t mdns_hostname_set(const char * hostname) if (!_mdns_server) { return ESP_ERR_INVALID_ARG; } - if (strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } char * new_hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); @@ -4249,7 +4398,7 @@ esp_err_t mdns_instance_name_set(const char * instance) if (!_mdns_server) { return ESP_ERR_INVALID_ARG; } - if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { + if (_str_null_or_empty(instance) || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } char * new_instance = strndup(instance, MDNS_NAME_BUF_LEN - 1); @@ -4278,7 +4427,7 @@ esp_err_t mdns_instance_name_set(const char * instance) esp_err_t mdns_service_add(const char * instance, const char * service, const char * proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!_mdns_server || !service || !proto || !port) { + if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { return ESP_ERR_INVALID_ARG; } mdns_srv_item_t * item = _mdns_get_service_item(service, proto); @@ -4328,7 +4477,7 @@ esp_err_t mdns_service_add(const char * instance, const char * service, const ch esp_err_t mdns_service_port_set(const char * service, const char * proto, uint16_t port) { - if (!_mdns_server || !_mdns_server->services || !service || !proto || !port) { + if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { return ESP_ERR_INVALID_ARG; } mdns_srv_item_t * s = _mdns_get_service_item(service, proto); @@ -4352,7 +4501,7 @@ esp_err_t mdns_service_port_set(const char * service, const char * proto, uint16 esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_txt_item_t txt[], uint8_t num_items) { - if (!_mdns_server || !_mdns_server->services || !service || !proto || (num_items && txt == NULL)) { + if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || (num_items && txt == NULL)) { return ESP_ERR_INVALID_ARG; } mdns_srv_item_t * s = _mdns_get_service_item(service, proto); @@ -4390,7 +4539,7 @@ esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_tx esp_err_t mdns_service_txt_item_set(const char * service, const char * proto, const char * key, const char * value) { - if (!_mdns_server || !_mdns_server->services || !service || !proto) { + if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(key) || !value) { return ESP_ERR_INVALID_ARG; } mdns_srv_item_t * s = _mdns_get_service_item(service, proto); @@ -4426,7 +4575,7 @@ esp_err_t mdns_service_txt_item_set(const char * service, const char * proto, co esp_err_t mdns_service_txt_item_remove(const char * service, const char * proto, const char * key) { - if (!_mdns_server || !_mdns_server->services || !service || !proto) { + if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(key)) { return ESP_ERR_INVALID_ARG; } mdns_srv_item_t * s = _mdns_get_service_item(service, proto); @@ -4455,10 +4604,10 @@ esp_err_t mdns_service_txt_item_remove(const char * service, const char * proto, esp_err_t mdns_service_instance_name_set(const char * service, const char * proto, const char * instance) { - if (!_mdns_server || !_mdns_server->services || !service || !proto) { + if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } - if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { + if (_str_null_or_empty(instance) || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } mdns_srv_item_t * s = _mdns_get_service_item(service, proto); @@ -4488,7 +4637,7 @@ esp_err_t mdns_service_instance_name_set(const char * service, const char * prot esp_err_t mdns_service_remove(const char * service, const char * proto) { - if (!_mdns_server || !_mdns_server->services || !service || !proto) { + if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } mdns_srv_item_t * s = _mdns_get_service_item(service, proto); @@ -4573,7 +4722,7 @@ esp_err_t mdns_query(const char * name, const char * service, const char * proto return ESP_ERR_INVALID_STATE; } - if (!timeout) { + if (!timeout || _str_null_or_empty(service) != _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } @@ -4596,7 +4745,7 @@ esp_err_t mdns_query(const char * name, const char * service, const char * proto esp_err_t mdns_query_ptr(const char * service, const char * proto, uint32_t timeout, size_t max_results, mdns_result_t ** results) { - if (!service || !proto) { + if (_str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } @@ -4605,7 +4754,7 @@ esp_err_t mdns_query_ptr(const char * service, const char * proto, uint32_t time esp_err_t mdns_query_srv(const char * instance, const char * service, const char * proto, uint32_t timeout, mdns_result_t ** result) { - if (!instance || !service || !proto) { + if (_str_null_or_empty(instance) || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } @@ -4614,7 +4763,7 @@ esp_err_t mdns_query_srv(const char * instance, const char * service, const char esp_err_t mdns_query_txt(const char * instance, const char * service, const char * proto, uint32_t timeout, mdns_result_t ** result) { - if (!instance || !service || !proto) { + if (_str_null_or_empty(instance) || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } @@ -4626,7 +4775,7 @@ esp_err_t mdns_query_a(const char * name, uint32_t timeout, ip4_addr_t * addr) mdns_result_t * result = NULL; esp_err_t err; - if (!name) { + if (_str_null_or_empty(name)) { return ESP_ERR_INVALID_ARG; } @@ -4659,7 +4808,7 @@ esp_err_t mdns_query_aaaa(const char * name, uint32_t timeout, ip6_addr_t * addr mdns_result_t * result = NULL; esp_err_t err; - if (!name) { + if (_str_null_or_empty(name)) { return ESP_ERR_INVALID_ARG; } From 6d99957f2d0f49652b8b1c2ac5a2e9606c11fdce Mon Sep 17 00:00:00 2001 From: Hrishikesh Dhayagude Date: Thu, 5 Apr 2018 14:32:34 +0530 Subject: [PATCH 020/289] Fix Kconfig.projbuild in some examples, where myssid is erroneously kept as the default value for password. Signed-off-by: Hrishikesh Dhayagude * Original commit: espressif/esp-idf@59d19d12af66e534db54dff0b8e879ddac80bfa8 --- examples/protocols/mdns/main/Kconfig.projbuild | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index 3122e0309..a55b0bf4c 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -8,7 +8,7 @@ config WIFI_SSID config WIFI_PASSWORD string "WiFi Password" - default "myssid" + default "mypassword" help WiFi password (WPA or WPA2) for the example to use. @@ -26,4 +26,4 @@ config MDNS_INSTANCE help mDNS Instance Name for example to use -endmenu \ No newline at end of file +endmenu From 259d3fc609c82b698f65a6a6d1fb5c358f9cbe18 Mon Sep 17 00:00:00 2001 From: jack Date: Wed, 25 Apr 2018 20:52:38 +0800 Subject: [PATCH 021/289] fix the bug that in mdns test code redefine esp_err_t to uint32_t, which should be int32_t * Original commit: espressif/esp-idf@81e4cad61593cde879a5c44a08060d9d336e5a3f --- components/mdns/test_afl_fuzz_host/esp32_compat.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/esp32_compat.h b/components/mdns/test_afl_fuzz_host/esp32_compat.h index d6a913a3c..fd21b2365 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_compat.h +++ b/components/mdns/test_afl_fuzz_host/esp32_compat.h @@ -67,8 +67,7 @@ ((uint32_t)((c) & 0xff) << 16) | \ ((uint32_t)((b) & 0xff) << 8) | \ (uint32_t)((a) & 0xff) - -typedef uint32_t esp_err_t; +typedef int32_t esp_err_t; typedef void * xSemaphoreHandle; typedef void * xQueueHandle; From 84bd1d7e88911a06328b8fab3f4bd916aeff1e47 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 12 Jan 2018 13:49:13 +1100 Subject: [PATCH 022/289] build system: Initial cmake support, work in progress * Original commit: espressif/esp-idf@c671a0c3ebf90f18576d6db55b51b62730c58301 --- components/mdns/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 components/mdns/CMakeLists.txt diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt new file mode 100644 index 000000000..0ba2e49dc --- /dev/null +++ b/components/mdns/CMakeLists.txt @@ -0,0 +1,2 @@ +register_component() + From f1ccc4052e2b540fe5215707cd53a8f83609f090 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 19 Jan 2018 16:22:08 +1100 Subject: [PATCH 023/289] cmake: Remove defaults for COMPONENT_SRCDIRS, COMPONENT_SRCS, COMPONENT_ADD_INCLUDEDIRS * Philosophical: "explicit is better than implicit". * Practical: Allows useful errors if invalid directories given in components as the defaults aren't always used. Also trims the -I path from a number of components that have no actual include directory. * Simplifies knowing which components will be header-only and which won't * Original commit: espressif/esp-idf@4f1a856dbfd752336cd71730105e02ad8c045541 --- components/mdns/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 0ba2e49dc..149dcb0bc 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -1,2 +1,5 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_PRIV_INCLUDEDIRS "private_include") register_component() From b9726db48eada3482eabbbbb26db194494fbae94 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 27 Feb 2018 17:44:31 +1100 Subject: [PATCH 024/289] cmake: Add CMakeLists.txt files for all examples Generating using convert_to_cmake.py, with some minor cleanup * Original commit: espressif/esp-idf@800bffb8b007dfafd09c667e8fb019fb38b7a1d1 --- examples/protocols/mdns/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 examples/protocols/mdns/CMakeLists.txt diff --git a/examples/protocols/mdns/CMakeLists.txt b/examples/protocols/mdns/CMakeLists.txt new file mode 100644 index 000000000..57c5e9a2e --- /dev/null +++ b/examples/protocols/mdns/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(MAIN_SRCS main/mdns_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mdns-test) From c7701d41f839a08a8193926cae9b08f205def667 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 22 Mar 2018 17:27:10 +1100 Subject: [PATCH 025/289] cmake: Add component dependency support Components should set the COMPONENT_REQUIRES & COMPONENT_PRIVATE_REQUIRES variables to define their requirements. * Original commit: espressif/esp-idf@1cb5712463a8963cd3e8331da90fb5e03f13575f --- components/mdns/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 149dcb0bc..4ab664110 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -1,5 +1,7 @@ set(COMPONENT_SRCDIRS ".") set(COMPONENT_ADD_INCLUDEDIRS "include") set(COMPONENT_PRIV_INCLUDEDIRS "private_include") +set(COMPONENT_REQUIRES lwip mbedtls console tcpip_adapter) + register_component() From 450c9de67b6afd48a1801be23c2bf06f74365148 Mon Sep 17 00:00:00 2001 From: Wayne Keenan Date: Mon, 30 Apr 2018 08:03:35 +0100 Subject: [PATCH 026/289] Fix potential NULL pointer dereference crash. * Original commit: espressif/esp-idf@be707f1c6b0a196489c98508f203abe6a0ca21e2 --- examples/protocols/mdns/main/mdns_example_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 44984c268..fb805545a 100755 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -137,7 +137,7 @@ static void mdns_print_results(mdns_result_t * results){ if(r->txt_count){ printf(" TXT : [%u] ", r->txt_count); for(t=0; ttxt_count; t++){ - printf("%s=%s; ", r->txt[t].key, r->txt[t].value); + printf("%s=%s; ", r->txt[t].key, r->txt[t].value?r->txt[t].value:"NULL"); } printf("\n"); } From 9f1be3668eba6db786330876911f3eef61177e1a Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 4 May 2018 16:42:54 +0200 Subject: [PATCH 027/289] MDNS-Fuzzer: AFL fuzzer tests for mdsn packet parser * Original commit: espressif/esp-idf@e983230be933fb83cebdd1945ba6539a7dc99b28 --- components/mdns/include/mdns.h | 4 - components/mdns/mdns.c | 318 +----------------- components/mdns/mdns_networking.c | 284 ++++++++++++++++ .../mdns/private_include/mdns_networking.h | 52 +++ components/mdns/test_afl_fuzz_host/Makefile | 22 +- .../mdns/test_afl_fuzz_host/esp32_compat.h | 153 +++++++-- .../mdns/test_afl_fuzz_host/esp32_mock.c | 84 +++++ .../mdns/test_afl_fuzz_host/esp32_mock.h | 45 +++ components/mdns/test_afl_fuzz_host/mdns_di.h | 53 +++ components/mdns/test_afl_fuzz_host/test.c | 209 +++++++++--- 10 files changed, 833 insertions(+), 391 deletions(-) create mode 100644 components/mdns/mdns_networking.c create mode 100644 components/mdns/private_include/mdns_networking.h create mode 100644 components/mdns/test_afl_fuzz_host/esp32_mock.c create mode 100644 components/mdns/test_afl_fuzz_host/esp32_mock.h create mode 100644 components/mdns/test_afl_fuzz_host/mdns_di.h diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index db0e3b522..a5ebb809f 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -18,12 +18,8 @@ extern "C" { #endif -#ifndef MDNS_TEST_MODE #include #include "esp_event.h" -#else -#include "esp32_compat.h" -#endif #define MDNS_TYPE_A 0x0001 #define MDNS_TYPE_PTR 0x000C diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index da00d7e5d..73c5f99c9 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -11,25 +11,11 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #include "mdns.h" - -#include -#include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" -#include "lwip/ip_addr.h" -#include "lwip/pbuf.h" -#include "lwip/igmp.h" -#include "lwip/udp.h" -#include "lwip/mld6.h" -#include "lwip/priv/tcpip_priv.h" -#include "esp_wifi.h" -#include "esp_system.h" -#include "esp_timer.h" -#include "esp_event_loop.h" - #include "mdns_private.h" +#include "mdns_networking.h" +#include #ifdef MDNS_ENABLE_DEBUG void mdns_debug_packet(const uint8_t * data, size_t len); @@ -38,7 +24,7 @@ void mdns_debug_packet(const uint8_t * data, size_t len); static const char * MDNS_DEFAULT_DOMAIN = "local"; static const char * MDNS_SUB_STR = "_sub"; -static mdns_server_t * _mdns_server = NULL; +mdns_server_t * _mdns_server = NULL; static volatile TaskHandle_t _mdns_service_task_handle = NULL; static SemaphoreHandle_t _mdns_service_semaphore = NULL; @@ -110,14 +96,7 @@ static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char return NULL; } -/* - * MDNS Server Networking - * */ - -/** - * @brief Queue RX packet action - */ -static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet) +esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet) { mdns_action_t * action = NULL; @@ -135,286 +114,6 @@ static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet) return ESP_OK; } -/** - * @brief the receive callback of the raw udp api. Packets are received here - * - */ -static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport) -{ - uint8_t i; - while (pb != NULL) { - struct pbuf * this_pb = pb; - pb = pb->next; - this_pb->next = NULL; - - mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t)); - if (!packet) { - //missed packet - no memory - pbuf_free(this_pb); - continue; - } - - packet->tcpip_if = TCPIP_ADAPTER_IF_MAX; - packet->pb = this_pb; - packet->src_port = rport; - memcpy(&packet->src, raddr, sizeof(ip_addr_t)); - packet->dest.type = packet->src.type; - - if (packet->src.type == IPADDR_TYPE_V4) { - packet->ip_protocol = MDNS_IP_PROTOCOL_V4; - struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN); - packet->dest.u_addr.ip4.addr = iphdr->dest.addr; - } else { - packet->ip_protocol = MDNS_IP_PROTOCOL_V6; - struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN); - memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16); - } - packet->multicast = ip_addr_ismulticast(&(packet->dest)); - - //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces) - struct netif * netif = NULL; - void * nif = NULL; - struct udp_pcb * pcb = NULL; - for (i=0; iinterfaces[i].pcbs[packet->ip_protocol].pcb; - tcpip_adapter_get_netif (i, &nif); - netif = (struct netif *)nif; - if (pcb && netif && netif == ip_current_input_netif ()) { - if (packet->src.type == IPADDR_TYPE_V4) { - if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) { - //packet source is not in the same subnet - pcb = NULL; - break; - } - } - packet->tcpip_if = i; - break; - } - pcb = NULL; - } - - if (!pcb || !_mdns_server || !_mdns_server->action_queue - || _mdns_send_rx_action(packet) != ESP_OK) { - pbuf_free(this_pb); - free(packet); - } - } -} - -/** - * @brief Stop PCB Main code - */ -static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - if (!_mdns_server) { - return; - } - mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; - if (_pcb->pcb) { - _pcb->state = PCB_OFF; - udp_recv(_pcb->pcb, NULL, NULL); - udp_disconnect(_pcb->pcb); - udp_remove(_pcb->pcb); - free(_pcb->probe_services); - _pcb->pcb = NULL; - _pcb->probe_ip = false; - _pcb->probe_services = NULL; - _pcb->probe_services_len = 0; - _pcb->probe_running = false; - _pcb->failed_probes = 0; - } -} - -/** - * @brief Start PCB V4 - */ -static esp_err_t _udp_pcb_v4_init(tcpip_adapter_if_t tcpip_if) -{ - tcpip_adapter_ip_info_t if_ip_info; - - if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) { - return ESP_ERR_INVALID_STATE; - } - - if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info) || if_ip_info.ip.addr == 0) { - return ESP_ERR_INVALID_ARG; - } - - ip_addr_t interface_addr = IPADDR4_INIT(if_ip_info.ip.addr); - - ip_addr_t multicast_addr; - IP_ADDR4(&multicast_addr, 224, 0, 0, 251); - - if (igmp_joingroup((const struct ip4_addr *)&interface_addr.u_addr.ip4, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) { - return ESP_ERR_INVALID_STATE; - } - - struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V4); - if (!pcb) { - return ESP_ERR_NO_MEM; - } - - if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { - udp_remove(pcb); - return ESP_ERR_INVALID_STATE; - } - - pcb->mcast_ttl = 1; - pcb->remote_port = MDNS_SERVICE_PORT; - ip_addr_copy(pcb->multicast_ip, interface_addr); - ip_addr_copy(pcb->remote_ip, multicast_addr); - - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb = pcb; - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].failed_probes = 0; - udp_recv(pcb, &_udp_recv, _mdns_server); - - return ESP_OK; -} - -/** - * @brief Start PCB V6 - */ -static esp_err_t _udp_pcb_v6_init(tcpip_adapter_if_t tcpip_if) -{ - ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); - ip_addr_t interface_addr; - interface_addr.type = IPADDR_TYPE_V6; - - if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) { - return ESP_ERR_INVALID_STATE; - } - - if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &interface_addr.u_addr.ip6)) { - return ESP_ERR_INVALID_ARG; - } - - if (mld6_joingroup(&(interface_addr.u_addr.ip6), &(multicast_addr.u_addr.ip6))) { - return ESP_ERR_INVALID_STATE; - } - - struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V6); - if (!pcb) { - return ESP_ERR_NO_MEM; - } - - if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { - udp_remove(pcb); - return ESP_ERR_INVALID_STATE; - } - - pcb->remote_port = MDNS_SERVICE_PORT; - ip_addr_copy(pcb->remote_ip, multicast_addr); - - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb = pcb; - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].failed_probes = 0; - udp_recv(pcb, &_udp_recv, _mdns_server); - - return ESP_OK; -} - -/** - * @brief Start PCB Main code - */ -static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - if (ip_protocol == MDNS_IP_PROTOCOL_V4) { - return _udp_pcb_v4_init(tcpip_if); - } else if (ip_protocol == MDNS_IP_PROTOCOL_V6) { - return _udp_pcb_v6_init(tcpip_if); - } - return ESP_ERR_INVALID_ARG; -} - -typedef struct { - struct tcpip_api_call call; - tcpip_adapter_if_t tcpip_if; - mdns_ip_protocol_t ip_protocol; - esp_err_t err; -} mdns_api_call_t; - -/** - * @brief Start PCB from LwIP thread - */ -static err_t _mdns_pcb_init_api(struct tcpip_api_call *api_call_msg) -{ - mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; - msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol); - return msg->err; -} - -/** - * @brief Start PCB - */ -static esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_api_call_t msg = { - .tcpip_if = tcpip_if, - .ip_protocol = ip_protocol - }; - tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call*)&msg); - return msg.err; -} - -/** - * @brief Stop PCB from LwIP thread - */ -static err_t _mdns_pcb_deinit_api(struct tcpip_api_call *api_call_msg) -{ - mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; - _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol); - msg->err = ESP_OK; - return ESP_OK; -} - -/** - * @brief Stop PCB - */ -static esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_api_call_t msg = { - .tcpip_if = tcpip_if, - .ip_protocol = ip_protocol - }; - tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call*)&msg); - return msg.err; -} - - -/** - * @brief send packet over UDP - * - * @param server The server - * @param data byte array containing the packet data - * @param len length of the packet data - * - * @return length of sent packet or 0 on error - */ -static size_t _udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len) -{ -#ifndef MDNS_TEST_MODE - struct netif * netif = NULL; - void * nif = NULL; - esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif); - netif = (struct netif *)nif; - if (err) { - return 0; - } - - struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pbt == NULL) { - return 0; - } - memcpy((uint8_t *)pbt->payload, data, len); - - err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif); - pbuf_free(pbt); - if (err) { - return 0; - } -#endif - return len; -} - /** * @brief Get the service name of a service */ @@ -1235,7 +934,7 @@ static void _mdns_dispatch_tx_packet(mdns_tx_packet_t * p) mdns_debug_packet(packet, index); #endif - _udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); + _mdns_udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); } /** @@ -4192,7 +3891,6 @@ static esp_err_t _mdns_stop_timer(){ */ static esp_err_t _mdns_service_task_start() { -#ifndef MDNS_TEST_MODE if (!_mdns_service_semaphore) { _mdns_service_semaphore = xSemaphoreCreateMutex(); if (!_mdns_service_semaphore) { @@ -4212,8 +3910,6 @@ static esp_err_t _mdns_service_task_start() } } MDNS_SERVICE_UNLOCK(); -#endif - return ESP_OK; } @@ -4225,7 +3921,6 @@ static esp_err_t _mdns_service_task_start() */ static esp_err_t _mdns_service_task_stop() { -#ifndef MDNS_TEST_MODE MDNS_SERVICE_LOCK(); _mdns_stop_timer(); if (_mdns_service_task_handle) { @@ -4241,7 +3936,6 @@ static esp_err_t _mdns_service_task_stop() } } MDNS_SERVICE_UNLOCK(); -#endif return ESP_OK; } diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c new file mode 100644 index 000000000..e4ab816de --- /dev/null +++ b/components/mdns/mdns_networking.c @@ -0,0 +1,284 @@ + +/* + * MDNS Server Networking + * + */ +#include +#include "mdns_networking.h" + + +extern mdns_server_t * _mdns_server; + +/* + * MDNS Server Networking + * + */ + +/** + * @brief the receive callback of the raw udp api. Packets are received here + * + */ +static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport) +{ + + uint8_t i; + while (pb != NULL) { + struct pbuf * this_pb = pb; + pb = pb->next; + this_pb->next = NULL; + + mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t)); + if (!packet) { + //missed packet - no memory + pbuf_free(this_pb); + continue; + } + + packet->tcpip_if = TCPIP_ADAPTER_IF_MAX; + packet->pb = this_pb; + packet->src_port = rport; + memcpy(&packet->src, raddr, sizeof(ip_addr_t)); + packet->dest.type = packet->src.type; + + if (packet->src.type == IPADDR_TYPE_V4) { + packet->ip_protocol = MDNS_IP_PROTOCOL_V4; + struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN); + packet->dest.u_addr.ip4.addr = iphdr->dest.addr; + } else { + packet->ip_protocol = MDNS_IP_PROTOCOL_V6; + struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN); + memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16); + } + packet->multicast = ip_addr_ismulticast(&(packet->dest)); + + //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces) + struct netif * netif = NULL; + void * nif = NULL; + struct udp_pcb * pcb = NULL; + for (i=0; iinterfaces[i].pcbs[packet->ip_protocol].pcb; + tcpip_adapter_get_netif (i, &nif); + netif = (struct netif *)nif; + if (pcb && netif && netif == ip_current_input_netif ()) { + if (packet->src.type == IPADDR_TYPE_V4) { + if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) { + //packet source is not in the same subnet + pcb = NULL; + break; + } + } + packet->tcpip_if = i; + break; + } + pcb = NULL; + } + + if (!pcb || !_mdns_server || !_mdns_server->action_queue + || _mdns_send_rx_action(packet) != ESP_OK) { + pbuf_free(this_pb); + free(packet); + } + } + +} + +/** + * @brief Stop PCB Main code + */ +static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (!_mdns_server) { + return; + } + mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; + if (_pcb->pcb) { + _pcb->state = PCB_OFF; + udp_recv(_pcb->pcb, NULL, NULL); + udp_disconnect(_pcb->pcb); + udp_remove(_pcb->pcb); + free(_pcb->probe_services); + _pcb->pcb = NULL; + _pcb->probe_ip = false; + _pcb->probe_services = NULL; + _pcb->probe_services_len = 0; + _pcb->probe_running = false; + _pcb->failed_probes = 0; + } +} + +/** + * @brief Start PCB V4 + */ +static esp_err_t _udp_pcb_v4_init(tcpip_adapter_if_t tcpip_if) +{ + tcpip_adapter_ip_info_t if_ip_info; + + if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) { + return ESP_ERR_INVALID_STATE; + } + + if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info) || if_ip_info.ip.addr == 0) { + return ESP_ERR_INVALID_ARG; + } + + ip_addr_t interface_addr = IPADDR4_INIT(if_ip_info.ip.addr); + + ip_addr_t multicast_addr; + IP_ADDR4(&multicast_addr, 224, 0, 0, 251); + + if (igmp_joingroup((const struct ip4_addr *)&interface_addr.u_addr.ip4, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) { + return ESP_ERR_INVALID_STATE; + } + + struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V4); + if (!pcb) { + return ESP_ERR_NO_MEM; + } + + if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { + udp_remove(pcb); + return ESP_ERR_INVALID_STATE; + } + + pcb->mcast_ttl = 1; + pcb->remote_port = MDNS_SERVICE_PORT; + ip_addr_copy(pcb->multicast_ip, interface_addr); + ip_addr_copy(pcb->remote_ip, multicast_addr); + + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb = pcb; + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].failed_probes = 0; + udp_recv(pcb, &_udp_recv, _mdns_server); + + return ESP_OK; +} + +/** + * @brief Start PCB V6 + */ +static esp_err_t _udp_pcb_v6_init(tcpip_adapter_if_t tcpip_if) +{ + ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); + ip_addr_t interface_addr; + interface_addr.type = IPADDR_TYPE_V6; + + if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) { + return ESP_ERR_INVALID_STATE; + } + + if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &interface_addr.u_addr.ip6)) { + return ESP_ERR_INVALID_ARG; + } + + if (mld6_joingroup(&(interface_addr.u_addr.ip6), &(multicast_addr.u_addr.ip6))) { + return ESP_ERR_INVALID_STATE; + } + + struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V6); + if (!pcb) { + return ESP_ERR_NO_MEM; + } + + if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { + udp_remove(pcb); + return ESP_ERR_INVALID_STATE; + } + + pcb->remote_port = MDNS_SERVICE_PORT; + ip_addr_copy(pcb->remote_ip, multicast_addr); + + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb = pcb; + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].failed_probes = 0; + udp_recv(pcb, &_udp_recv, _mdns_server); + + return ESP_OK; +} + +/** + * @brief Start PCB Main code + */ +static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (ip_protocol == MDNS_IP_PROTOCOL_V4) { + return _udp_pcb_v4_init(tcpip_if); + } else if (ip_protocol == MDNS_IP_PROTOCOL_V6) { + return _udp_pcb_v6_init(tcpip_if); + } + return ESP_ERR_INVALID_ARG; +} + +typedef struct { + struct tcpip_api_call call; + tcpip_adapter_if_t tcpip_if; + mdns_ip_protocol_t ip_protocol; + esp_err_t err; +} mdns_api_call_t; + +/** + * @brief Start PCB from LwIP thread + */ +static err_t _mdns_pcb_init_api(struct tcpip_api_call *api_call_msg) +{ + mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; + msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol); + return msg->err; +} + +/** + * @brief Stop PCB from LwIP thread + */ +static err_t _mdns_pcb_deinit_api(struct tcpip_api_call *api_call_msg) +{ + mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; + _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol); + msg->err = ESP_OK; + return ESP_OK; +} + +/* + * Non-static functions below are + * - _mdns prefixed + * - commented in mdns_networking.h header + */ +esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_api_call_t msg = { + .tcpip_if = tcpip_if, + .ip_protocol = ip_protocol + }; + tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call*)&msg); + return msg.err; +} + +esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_api_call_t msg = { + .tcpip_if = tcpip_if, + .ip_protocol = ip_protocol + }; + tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call*)&msg); + return msg.err; +} + +size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len) +{ + struct netif * netif = NULL; + void * nif = NULL; + esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif); + netif = (struct netif *)nif; + if (err) { + return 0; + } + + struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pbt == NULL) { + return 0; + } + memcpy((uint8_t *)pbt->payload, data, len); + + err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif); + pbuf_free(pbt); + if (err) { + return 0; + } + return len; +} diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h new file mode 100644 index 000000000..5b56f8066 --- /dev/null +++ b/components/mdns/private_include/mdns_networking.h @@ -0,0 +1,52 @@ +#ifndef ESP_MDNS_NETWORKING_H_ +#define ESP_MDNS_NETWORKING_H_ + +/* + * MDNS Server Networking -- private include + * + */ +#include "mdns.h" +#include "mdns_private.h" +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "lwip/ip_addr.h" +#include "lwip/pbuf.h" +#include "lwip/igmp.h" +#include "lwip/udp.h" +#include "lwip/mld6.h" +#include "lwip/priv/tcpip_priv.h" +#include "esp_wifi.h" +#include "esp_system.h" +#include "esp_timer.h" +#include "esp_event_loop.h" + + +/** + * @brief Queue RX packet action + */ +esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet); + +/** + * @brief Start PCB + */ +esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Stop PCB + */ +esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief send packet over UDP + * + * @param server The server + * @param data byte array containing the packet data + * @param len length of the packet data + * + * @return length of sent packet or 0 on error + */ +size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len); + +#endif /* ESP_MDNS_NETWORKING_H_ */ diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 65a318ef2..61bedc520 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -1,17 +1,25 @@ TEST_NAME=test FUZZ=afl-fuzz -CC=afl-clang-fast +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 +MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h +ifeq ($(INSTR),off) + CC=gcc + CFLAGS+=-DINSTR_IS_OFF + TEST_NAME=test_sim +else + CC=afl-clang-fast +endif CPP=$(CC) LD=$(CC) -OBJECTS=mdns.o test.o -CFLAGS=-DMDNS_TEST_MODE -I. -I../include +OBJECTS=mdns.o esp32_mock.o test.o OS := $(shell uname) ifeq ($(OS),Darwin) LDLIBS= else - LDLIBS=-lbsd - CFLAGS+=-DUSE_BSD_STRING + LDLIBS=-lbsd + CFLAGS+=-DUSE_BSD_STRING endif all: $(TEST_NAME) @@ -22,11 +30,11 @@ all: $(TEST_NAME) mdns.o: ../mdns.c @echo "[CC] $<" - @$(CC) $(CFLAGS) -c $< -o $@ + @$(CC) $(CFLAGS) $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@ $(TEST_NAME): $(OBJECTS) @echo "[LD] $@" - @$(LD) $(LDLIBS) $(OBJECTS) -o $@ + @$(LD) $(OBJECTS) -o $@ $(LDLIBS) fuzz: $(TEST_NAME) @$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) diff --git a/components/mdns/test_afl_fuzz_host/esp32_compat.h b/components/mdns/test_afl_fuzz_host/esp32_compat.h index fd21b2365..402807c4f 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_compat.h +++ b/components/mdns/test_afl_fuzz_host/esp32_compat.h @@ -17,6 +17,12 @@ #ifdef MDNS_TEST_MODE +// Not to include +#define ESP_MDNS_NETWORKING_H_ +#define _TCPIP_ADAPTER_H_ +#define __ESP_EVENT_H__ + + #ifdef USE_BSD_STRING #include #endif @@ -28,6 +34,7 @@ #include #include + #define ERR_OK 0 #define ESP_OK 0 #define ESP_FAIL -1 @@ -44,21 +51,26 @@ #define pdTRUE true #define pdFALSE false +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) #define portMAX_DELAY 0xFFFFFFFF #define portTICK_PERIOD_MS 1 #define xSemaphoreTake(s,d) +#define xTaskDelete(a) +#define vTaskDelete(a) free(a) #define xSemaphoreGive(s) +#define _mdns_pcb_init(a,b) true +#define _mdns_pcb_deinit(a,b) true #define xSemaphoreCreateMutex() malloc(1) #define vSemaphoreDelete(s) free(s) -#define xQueueCreate(n,s) malloc((n)*(s)) -#define vQueueDelete(q) free(q) -#define xQueueReceive(q, d, t) (ESP_OK) -#define vTaskDelay(m) usleep((m)*1000) +#define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1) +#define vTaskDelay(m) usleep((m)*0) #define pbuf_free(p) free(p) - -#define tcpip_adapter_get_ip_info(i,d) +#define esp_random() (rand()%UINT32_MAX) +#define tcpip_adapter_get_ip_info(i,d) true +#define tcpip_adapter_dhcpc_get_status(a, b) TCPIP_ADAPTER_DHCP_STARTED #define tcpip_adapter_get_ip6_linklocal(i,d) (ESP_OK) #define tcpip_adapter_get_hostname(i, n) *(n) = "esp32-0123456789AB" @@ -67,17 +79,31 @@ ((uint32_t)((c) & 0xff) << 16) | \ ((uint32_t)((b) & 0xff) << 8) | \ (uint32_t)((a) & 0xff) +#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) +#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) + +#define IPADDR_TYPE_V4 0U +#define IPADDR_TYPE_V6 6U +#define IPADDR_TYPE_ANY 46U +#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) +#define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0) +#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0) + +#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 } + typedef int32_t esp_err_t; typedef void * xSemaphoreHandle; +typedef void * SemaphoreHandle_t; typedef void * xQueueHandle; +typedef void * QueueHandle_t; +typedef void * TaskHandle_t; +typedef void * esp_timer_handle_t; +typedef uint32_t TickType_t; +typedef uint32_t portTickType; -typedef enum { - TCPIP_ADAPTER_IF_STA = 0, /**< ESP32 station interface */ - TCPIP_ADAPTER_IF_AP, /**< ESP32 soft-AP interface */ - TCPIP_ADAPTER_IF_ETH, /**< ESP32 ethernet interface */ - TCPIP_ADAPTER_IF_MAX -} tcpip_adapter_if_t; typedef enum { WIFI_MODE_NULL = 0, /**< null mode */ @@ -87,6 +113,42 @@ typedef enum { WIFI_MODE_MAX } wifi_mode_t; +/* status of DHCP client or DHCP server */ +typedef enum { + TCPIP_ADAPTER_DHCP_INIT = 0, /**< DHCP client/server in initial state */ + TCPIP_ADAPTER_DHCP_STARTED, /**< DHCP client/server already been started */ + TCPIP_ADAPTER_DHCP_STOPPED, /**< DHCP client/server already been stopped */ + 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; }; @@ -101,27 +163,76 @@ struct ip6_addr { }; typedef struct ip6_addr ip6_addr_t; +typedef struct _ip_addr { + union { + ip6_addr_t ip6; + ip4_addr_t ip4; + } u_addr; + uint8_t type; +} ip_addr_t; + typedef struct { ip4_addr_t ip; ip4_addr_t netmask; 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 */ + TCPIP_ADAPTER_IF_ETH, /**< ESP32 ethernet interface */ + TCPIP_ADAPTER_IF_MAX +} tcpip_adapter_if_t; + +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; + inline esp_err_t esp_wifi_get_mode(wifi_mode_t * mode) { *mode = WIFI_MODE_APSTA; return ESP_OK; } -inline uint32_t xTaskGetTickCount() -{ - struct timeval tv; - struct timezone tz; - if (gettimeofday(&tv, &tz) == 0) { - return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - } - return 0; -} +struct pbuf { + struct pbuf *next; + void *payload; + uint16_t tot_len; + uint16_t len; + uint8_t /*pbuf_type*/ type; + uint8_t flags; + uint16_t ref; +}; + +#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) +#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) +#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) +#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ + (dest).addr[1] = (src).addr[1]; \ + (dest).addr[2] = (src).addr[2]; \ + (dest).addr[3] = (src).addr[3];}while(0) + +#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) + +#include "esp32_mock.h" + +uint32_t xTaskGetTickCount(); + #endif //MDNS_TEST_MODE diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.c b/components/mdns/test_afl_fuzz_host/esp32_mock.c new file mode 100644 index 000000000..aa9ca7f72 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include "esp32_compat.h" + +void* g_queue; +int g_queue_send_shall_fail = 0; +int g_size = 0; + +esp_err_t esp_timer_delete(esp_timer_handle_t timer) +{ + return ESP_OK; +} + +esp_err_t esp_timer_stop(esp_timer_handle_t timer) +{ + return ESP_OK; +} + +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) +{ + return ESP_OK; +} + +esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, + esp_timer_handle_t* out_handle) +{ + return ESP_OK; +} + +uint32_t xTaskGetTickCount() +{ + struct timeval tv; + struct timezone tz; + if (gettimeofday(&tv, &tz) == 0) { + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + } + return 0; +} + +/// Queue mock + QueueHandle_t xQueueCreate( uint32_t uxQueueLength, uint32_t uxItemSize ) + { + g_size = uxItemSize; + g_queue = malloc((uxQueueLength)*(uxItemSize)); + return g_queue; + } + + +void vQueueDelete( QueueHandle_t xQueue ) +{ + free(xQueue); +} + +uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait) +{ + if (g_queue_send_shall_fail) + { + return pdFALSE; + } + else + { + memcpy(xQueue, pvItemToQueue, g_size); + return pdPASS; + } +} + + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait) +{ + return pdFALSE; +} + +void GetLastItem(void *pvBuffer) +{ + memcpy(pvBuffer, g_queue, g_size); +} + +void ForceTaskDelete() +{ + g_queue_send_shall_fail = 1; +} diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h new file mode 100644 index 000000000..7246e2968 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.h @@ -0,0 +1,45 @@ +#ifndef ESP32_MOCK_H_ +#define ESP32_MOCK_H_ + +typedef void (*esp_timer_cb_t)(void* arg); + +typedef enum +{ + ESP_TIMER_TASK, //!< Callback is called from timer task +} esp_timer_dispatch_t; + +typedef struct +{ + esp_timer_cb_t callback; //!< Function to call when timer expires + void* arg; //!< Argument to pass to the callback + esp_timer_dispatch_t dispatch_method; //!< Call the callback from task or from ISR + const char* name; //!< Timer name, used in esp_timer_dump function +} esp_timer_create_args_t; + +esp_err_t esp_timer_delete(esp_timer_handle_t timer); + +esp_err_t esp_timer_stop(esp_timer_handle_t timer); + +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period); + +esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, + esp_timer_handle_t* out_handle); + + +// Queue mock + QueueHandle_t xQueueCreate( uint32_t uxQueueLength, + uint32_t uxItemSize ); + +void vQueueDelete( QueueHandle_t xQueue ); + +uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait); + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); + +void GetLastItem(void *pvBuffer); + +void ForceTaskDelete(); + +#define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len + +#endif /* ESP32_MOCK_H_ */ \ No newline at end of file diff --git a/components/mdns/test_afl_fuzz_host/mdns_di.h b/components/mdns/test_afl_fuzz_host/mdns_di.h new file mode 100644 index 000000000..05aeb8bd5 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/mdns_di.h @@ -0,0 +1,53 @@ +/* + * MDNS Dependecy injection -- preincluded to inject interface test functions into static variables + * + */ + +#include "mdns.h" +#include "mdns_private.h" + +void (*mdns_test_static_execute_action)(mdns_action_t *) = NULL; +mdns_srv_item_t * (*mdns_test_static_mdns_get_service_item)(const char * service, const char * proto) = NULL; +mdns_search_once_t * (*mdns_test_static_search_init)(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) = NULL; +esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t * search) = NULL; +void (*mdns_test_static_search_free)(mdns_search_once_t * search) = NULL; + +static void _mdns_execute_action(mdns_action_t * action); +static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto); +static mdns_search_once_t * _mdns_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results); +static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t * search); +static void _mdns_search_free(mdns_search_once_t * search); + +void mdns_test_init_di() +{ + mdns_test_static_execute_action = _mdns_execute_action; + mdns_test_static_mdns_get_service_item = _mdns_get_service_item; + mdns_test_static_search_init = _mdns_search_init; + mdns_test_static_send_search_action = _mdns_send_search_action; + mdns_test_static_search_free = _mdns_search_free; +} + +void mdns_test_execute_action(void * action) +{ + mdns_test_static_execute_action((mdns_action_t *)action); +} + +void mdns_test_search_free(mdns_search_once_t * search) +{ + return mdns_test_static_search_free(search); +} + +esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t * search) +{ + return mdns_test_static_send_search_action(type, search); +} + +mdns_search_once_t * mdns_test_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) +{ + return mdns_test_static_search_init(name, service, proto, type, timeout, max_results); +} + +mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto) +{ + return mdns_test_static_mdns_get_service_item(service, proto); +} \ No newline at end of file diff --git a/components/mdns/test_afl_fuzz_host/test.c b/components/mdns/test_afl_fuzz_host/test.c index be06ac0bf..8ea72d95c 100644 --- a/components/mdns/test_afl_fuzz_host/test.c +++ b/components/mdns/test_afl_fuzz_host/test.c @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifdef MDNS_TEST_MODE - #include #include #include @@ -21,93 +19,210 @@ #include #include "mdns.h" +#include "mdns_private.h" -void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len); +// +// Global stuctures containing packet payload, search +mdns_rx_packet_t g_packet; +struct pbuf mypbuf; +mdns_search_once_t * search = NULL; +// +// Dependency injected test functions +void mdns_test_execute_action(void * action); +mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto); +mdns_search_once_t * mdns_test_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results); +esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t * search); +void mdns_test_search_free(mdns_search_once_t * search); +void mdns_test_init_di(); + +// +// mdns function wrappers for mdns setup in test mode +static int mdns_test_hostname_set(const char * mdns_hostname) +{ + int ret = mdns_hostname_set(mdns_hostname); + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + +static int mdns_test_service_instance_name_set(const char * service, const char * proto, const char * instance) +{ + int ret = mdns_service_instance_name_set(service, proto, instance); + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + +static int mdns_test_service_txt_set(const char * service, const char * proto, uint8_t num_items, mdns_txt_item_t txt[]) +{ + int ret = mdns_service_txt_set(service, proto, txt, num_items); + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + +static int mdns_test_service_add(const char * service_name, const char * proto, uint32_t port) +{ + if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { + // This is expected failure as the service thread is not running + } + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + + if (mdns_test_mdns_get_service_item(service_name, proto)==NULL) { + return ESP_FAIL; + } + return ESP_OK; +} + +static mdns_result_t* mdns_test_query(const char * service_name, const char * proto) +{ + search = mdns_test_search_init(NULL, service_name, proto, MDNS_TYPE_PTR, 3000, 20); + if (!search) { + abort(); + } + + if (mdns_test_send_search_action(ACTION_SEARCH_ADD, search)) { + mdns_test_search_free(search); + abort(); + } + + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return NULL; +} + +static void mdns_test_query_free() +{ + mdns_test_search_free(search); +} + +// +// function "under test" where afl-mangled packets passed +// +void mdns_parse_packet(mdns_rx_packet_t * packet); + +// +// Test starts here +// int main(int argc, char** argv) { + int i; const char * mdns_hostname = "minifritz"; const char * mdns_instance = "Hristo's Time Capsule"; - const char * arduTxtData[4] = { - "board=esp32", - "tcp_check=no", - "ssh_upload=no", - "auth_upload=no" + mdns_txt_item_t arduTxtData[4] = { + {"board","esp32"}, + {"tcp_check","no"}, + {"ssh_upload","no"}, + {"auth_upload","no"} }; + const uint8_t mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x32}; - mdns_server_t * mdns = NULL; uint8_t buf[1460]; char winstance[21+strlen(mdns_hostname)]; sprintf(winstance, "%s [%02x:%02x:%02x:%02x:%02x:%02x]", mdns_hostname, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - if (mdns_init(TCPIP_ADAPTER_IF_ETH, &mdns)) { + // Init depencency injected methods + mdns_test_init_di(); + + if (mdns_init()) { abort(); } - if (mdns_set_hostname(mdns, mdns_hostname)) { + if (mdns_test_hostname_set(mdns_hostname)) { abort(); } - if (mdns_set_instance(mdns, mdns_instance)) { + if (mdns_test_service_add("_workstation", "_tcp", 9)) { + abort(); + } + if (mdns_test_service_instance_name_set("_workstation", "_tcp", winstance)) { abort(); } - if (mdns_service_add(mdns, "_workstation", "_tcp", 9)) { + if (mdns_test_service_add("_arduino", "_tcp", 3232)) { abort(); } - if (mdns_service_instance_set(mdns, "_workstation", "_tcp", winstance)) { + if (mdns_test_service_txt_set("_arduino", "_tcp", 4, arduTxtData)) { abort(); } - if (mdns_service_add(mdns, "_arduino", "_tcp", 3232)) { + if (mdns_test_service_add("_http", "_tcp", 80)) { abort(); } - if (mdns_service_txt_set(mdns, "_arduino", "_tcp", 4, arduTxtData)) { - abort(); - } - - if (mdns_service_add(mdns, "_http", "_tcp", 80)) { - abort(); - } - - if (mdns_service_instance_set(mdns, "_http", "_tcp", "ESP WebServer")) { + if (mdns_test_service_instance_name_set("_http", "_tcp", "ESP WebServer")) { abort(); } if ( - mdns_service_add(mdns, "_afpovertcp", "_tcp", 548) - || mdns_service_add(mdns, "_rfb", "_tcp", 885) - || mdns_service_add(mdns, "_smb", "_tcp", 885) - || mdns_service_add(mdns, "_adisk", "_tcp", 885) - || mdns_service_add(mdns, "_airport", "_tcp", 885) - || mdns_service_add(mdns, "_printer", "_tcp", 885) - || mdns_service_add(mdns, "_airplay", "_tcp", 885) - || mdns_service_add(mdns, "_raop", "_tcp", 885) - || mdns_service_add(mdns, "_uscan", "_tcp", 885) - || mdns_service_add(mdns, "_uscans", "_tcp", 885) - || mdns_service_add(mdns, "_ippusb", "_tcp", 885) - || mdns_service_add(mdns, "_scanner", "_tcp", 885) - || mdns_service_add(mdns, "_ipp", "_tcp", 885) - || mdns_service_add(mdns, "_ipps", "_tcp", 885) - || mdns_service_add(mdns, "_pdl-datastream", "_tcp", 885) - || mdns_service_add(mdns, "_ptp", "_tcp", 885) - || mdns_service_add(mdns, "_sleep-proxy", "_udp", 885)) + mdns_test_service_add("_afpovertcp", "_tcp", 548) + || mdns_test_service_add("_rfb", "_tcp", 885) + || mdns_test_service_add("_smb", "_tcp", 885) + || mdns_test_service_add("_adisk", "_tcp", 885) + || mdns_test_service_add("_airport", "_tcp", 885) + || mdns_test_service_add("_printer", "_tcp", 885) + || mdns_test_service_add("_airplay", "_tcp", 885) + || mdns_test_service_add("_raop", "_tcp", 885) + || mdns_test_service_add("_uscan", "_tcp", 885) + || mdns_test_service_add("_uscans", "_tcp", 885) + || mdns_test_service_add("_ippusb", "_tcp", 885) + || mdns_test_service_add("_scanner", "_tcp", 885) + || mdns_test_service_add("_ipp", "_tcp", 885) + || mdns_test_service_add("_ipps", "_tcp", 885) + || mdns_test_service_add("_pdl-datastream", "_tcp", 885) + || mdns_test_service_add("_ptp", "_tcp", 885) + || mdns_test_service_add("_sleep-proxy", "_udp", 885)) { - abort(); + abort(); + } + + mdns_result_t * results = NULL; + FILE *file; + size_t nread; + +#ifdef INSTR_IS_OFF + size_t len = 1460; + memset(buf, 0, 1460); + + if (argc != 2) + { + printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n"); + return 1; + } + else + { + // + // Note: parameter1 is a file (mangled packet) which caused the crash + file = fopen(argv[1], "r"); + if (file) { + len = fread(buf, 1, 1460, file); + } + fclose(file); } + for (i=0; i<1; i++) { +#else while (__AFL_LOOP(1000)) { memset(buf, 0, 1460); size_t len = read(0, buf, 1460); - mdns_query(mdns, "_afpovertcp", "_tcp", 0); - mdns_parse_packet(mdns, buf, len); - mdns_query_end(mdns); +#endif + mypbuf.payload = buf; + mypbuf.len = len; + g_packet.pb = &mypbuf; + mdns_test_query("_afpovertcp", "_tcp"); + mdns_parse_packet(&g_packet); } + ForceTaskDelete(); + mdns_free(); return 0; } - -#endif From ad29d34bb67ada6dfe898c0ea47b407d737402f7 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 22 May 2018 11:10:27 +0200 Subject: [PATCH 028/289] Fixed nullptr dereference in MDNS.c * Original commit: espressif/esp-idf@fffbf7b75065b5852e064e04b0c5102dd0fc2244 --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 73c5f99c9..8ead7c44d 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2269,7 +2269,7 @@ static bool _mdns_question_matches(mdns_parsed_question_t * question, uint16_t t } } else if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { const char * name = _mdns_get_service_instance_name(service->service); - if (name && !strcasecmp(name, question->host) + if (name && question->host && !strcasecmp(name, question->host) && !strcasecmp(service->service->service, question->service) && !strcasecmp(service->service->proto, question->proto) && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { From 98069f9ca248b9996ac444a7d3cd6530d85a0964 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 29 May 2018 02:08:38 +0800 Subject: [PATCH 029/289] remove executable permission from source files * Original commit: espressif/esp-idf@cb649e452f3c64a7db1f4a61e162a16b70248204 --- components/mdns/test_afl_fuzz_host/in/test-14.bin | Bin components/mdns/test_afl_fuzz_host/in/test-15.bin | Bin components/mdns/test_afl_fuzz_host/in/test-16.bin | Bin components/mdns/test_afl_fuzz_host/in/test-28.bin | Bin components/mdns/test_afl_fuzz_host/in/test-29.bin | Bin components/mdns/test_afl_fuzz_host/in/test-31.bin | Bin components/mdns/test_afl_fuzz_host/in/test-53.bin | Bin components/mdns/test_afl_fuzz_host/in/test-56.bin | Bin components/mdns/test_afl_fuzz_host/in/test-63.bin | Bin components/mdns/test_afl_fuzz_host/in/test-83.bin | Bin components/mdns/test_afl_fuzz_host/in/test-88.bin | Bin components/mdns/test_afl_fuzz_host/in/test-89.bin | Bin components/mdns/test_afl_fuzz_host/in/test-95.bin | Bin components/mdns/test_afl_fuzz_host/in/test-96.bin | Bin examples/protocols/mdns/main/mdns_example_main.c | 0 15 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-14.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-15.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-16.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-28.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-29.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-31.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-53.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-56.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-63.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-83.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-88.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-89.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-95.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-96.bin mode change 100755 => 100644 examples/protocols/mdns/main/mdns_example_main.c diff --git a/components/mdns/test_afl_fuzz_host/in/test-14.bin b/components/mdns/test_afl_fuzz_host/in/test-14.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-15.bin b/components/mdns/test_afl_fuzz_host/in/test-15.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-16.bin b/components/mdns/test_afl_fuzz_host/in/test-16.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-28.bin b/components/mdns/test_afl_fuzz_host/in/test-28.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-29.bin b/components/mdns/test_afl_fuzz_host/in/test-29.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-31.bin b/components/mdns/test_afl_fuzz_host/in/test-31.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-53.bin b/components/mdns/test_afl_fuzz_host/in/test-53.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-56.bin b/components/mdns/test_afl_fuzz_host/in/test-56.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-63.bin b/components/mdns/test_afl_fuzz_host/in/test-63.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-83.bin b/components/mdns/test_afl_fuzz_host/in/test-83.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-88.bin b/components/mdns/test_afl_fuzz_host/in/test-88.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-89.bin b/components/mdns/test_afl_fuzz_host/in/test-89.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-95.bin b/components/mdns/test_afl_fuzz_host/in/test-95.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-96.bin b/components/mdns/test_afl_fuzz_host/in/test-96.bin old mode 100755 new mode 100644 diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c old mode 100755 new mode 100644 From b26c8665f8264a57b744ab15aa06b4f7547e1449 Mon Sep 17 00:00:00 2001 From: Liu Han Date: Sun, 3 Jun 2018 17:29:49 +0800 Subject: [PATCH 030/289] fix(mdns): fix the exception when remove one of multiple service * Original commit: espressif/esp-idf@696d733eb04ee98f764dffdc82bcef51a724c9c6 --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 8ead7c44d..6b74f7de8 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3703,7 +3703,7 @@ static void _mdns_execute_action(mdns_action_t * action) a = a->next; } if (a->next == action->data.srv_del.service) { - mdns_srv_item_t * b = a; + mdns_srv_item_t * b = a->next; a->next = a->next->next; _mdns_send_bye(&b, 1, false); _mdns_free_service(b->service); From 0191d6fcd76d60d44e77b7ac348b28601f1970a6 Mon Sep 17 00:00:00 2001 From: Liu Han Date: Fri, 15 Jun 2018 15:55:48 +0800 Subject: [PATCH 031/289] fix(mdns): add the maximum number of services * Original commit: espressif/esp-idf@ba458c69cfb2f18478d73690c289b09641c62004 --- components/mdns/Kconfig | 13 ++++++++++++ components/mdns/mdns.c | 20 +++++++++++++++++++ .../mdns/private_include/mdns_private.h | 3 +++ 3 files changed, 36 insertions(+) create mode 100644 components/mdns/Kconfig diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig new file mode 100644 index 000000000..321b0f652 --- /dev/null +++ b/components/mdns/Kconfig @@ -0,0 +1,13 @@ +menu "mDNS" + +config MDNS_MAX_SERVICES + int "Max number of services" + range 1 64 + default 10 + 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. + +endmenu diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 6b74f7de8..9fb64777e 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -96,6 +96,21 @@ static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char return NULL; } +static bool _mdns_can_add_more_services(void) +{ + mdns_srv_item_t * s = _mdns_server->services; + uint16_t service_num = 0; + while (s) { + service_num ++; + s = s->next; + if (service_num >= MDNS_MAX_SERVICES) { + return false; + } + } + + return true; +} + esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet) { mdns_action_t * action = NULL; @@ -4124,6 +4139,11 @@ esp_err_t mdns_service_add(const char * instance, const char * service, const ch if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { return ESP_ERR_INVALID_ARG; } + + if (!_mdns_can_add_more_services()) { + return ESP_ERR_NO_MEM; + } + mdns_srv_item_t * item = _mdns_get_service_item(service, proto); if (item) { return ESP_ERR_INVALID_ARG; diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index a3d9fa279..d6edfb082 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -20,6 +20,9 @@ #define _mdns_dbg_printf(...) printf(__VA_ARGS__) #endif +/** The maximum number of services */ +#define MDNS_MAX_SERVICES CONFIG_MDNS_MAX_SERVICES + #define MDNS_ANSWER_PTR_TTL 4500 #define MDNS_ANSWER_TXT_TTL 4500 #define MDNS_ANSWER_SRV_TTL 120 From 19acac76ebf9d175c0c5cf3cf273d5a629c4828b Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 5 Jul 2018 09:01:03 +1000 Subject: [PATCH 032/289] Replace all DOS line endings with Unix Command run was: git ls-tree -r HEAD --name-only | xargs dos2unix * Original commit: espressif/esp-idf@a67d5d89e0e90390fa7ff02816a6a79008d75d40 --- .../mdns/test_afl_fuzz_host/esp32_mock.c | 168 +++++++++--------- .../mdns/test_afl_fuzz_host/esp32_mock.h | 88 ++++----- 2 files changed, 128 insertions(+), 128 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.c b/components/mdns/test_afl_fuzz_host/esp32_mock.c index aa9ca7f72..8cc986dfd 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.c +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.c @@ -1,84 +1,84 @@ -#include -#include -#include -#include -#include -#include "esp32_compat.h" - -void* g_queue; -int g_queue_send_shall_fail = 0; -int g_size = 0; - -esp_err_t esp_timer_delete(esp_timer_handle_t timer) -{ - return ESP_OK; -} - -esp_err_t esp_timer_stop(esp_timer_handle_t timer) -{ - return ESP_OK; -} - -esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) -{ - return ESP_OK; -} - -esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, - esp_timer_handle_t* out_handle) -{ - return ESP_OK; -} - -uint32_t xTaskGetTickCount() -{ - struct timeval tv; - struct timezone tz; - if (gettimeofday(&tv, &tz) == 0) { - return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - } - return 0; -} - -/// Queue mock - QueueHandle_t xQueueCreate( uint32_t uxQueueLength, uint32_t uxItemSize ) - { - g_size = uxItemSize; - g_queue = malloc((uxQueueLength)*(uxItemSize)); - return g_queue; - } - - -void vQueueDelete( QueueHandle_t xQueue ) -{ - free(xQueue); -} - -uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait) -{ - if (g_queue_send_shall_fail) - { - return pdFALSE; - } - else - { - memcpy(xQueue, pvItemToQueue, g_size); - return pdPASS; - } -} - - -uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait) -{ - return pdFALSE; -} - -void GetLastItem(void *pvBuffer) -{ - memcpy(pvBuffer, g_queue, g_size); -} - -void ForceTaskDelete() -{ - g_queue_send_shall_fail = 1; -} +#include +#include +#include +#include +#include +#include "esp32_compat.h" + +void* g_queue; +int g_queue_send_shall_fail = 0; +int g_size = 0; + +esp_err_t esp_timer_delete(esp_timer_handle_t timer) +{ + return ESP_OK; +} + +esp_err_t esp_timer_stop(esp_timer_handle_t timer) +{ + return ESP_OK; +} + +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) +{ + return ESP_OK; +} + +esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, + esp_timer_handle_t* out_handle) +{ + return ESP_OK; +} + +uint32_t xTaskGetTickCount() +{ + struct timeval tv; + struct timezone tz; + if (gettimeofday(&tv, &tz) == 0) { + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + } + return 0; +} + +/// Queue mock + QueueHandle_t xQueueCreate( uint32_t uxQueueLength, uint32_t uxItemSize ) + { + g_size = uxItemSize; + g_queue = malloc((uxQueueLength)*(uxItemSize)); + return g_queue; + } + + +void vQueueDelete( QueueHandle_t xQueue ) +{ + free(xQueue); +} + +uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait) +{ + if (g_queue_send_shall_fail) + { + return pdFALSE; + } + else + { + memcpy(xQueue, pvItemToQueue, g_size); + return pdPASS; + } +} + + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait) +{ + return pdFALSE; +} + +void GetLastItem(void *pvBuffer) +{ + memcpy(pvBuffer, g_queue, g_size); +} + +void ForceTaskDelete() +{ + g_queue_send_shall_fail = 1; +} diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h index 7246e2968..5ff5ad633 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.h @@ -1,45 +1,45 @@ -#ifndef ESP32_MOCK_H_ -#define ESP32_MOCK_H_ - -typedef void (*esp_timer_cb_t)(void* arg); - -typedef enum -{ - ESP_TIMER_TASK, //!< Callback is called from timer task -} esp_timer_dispatch_t; - -typedef struct -{ - esp_timer_cb_t callback; //!< Function to call when timer expires - void* arg; //!< Argument to pass to the callback - esp_timer_dispatch_t dispatch_method; //!< Call the callback from task or from ISR - const char* name; //!< Timer name, used in esp_timer_dump function -} esp_timer_create_args_t; - -esp_err_t esp_timer_delete(esp_timer_handle_t timer); - -esp_err_t esp_timer_stop(esp_timer_handle_t timer); - -esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period); - -esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, - esp_timer_handle_t* out_handle); - - -// Queue mock - QueueHandle_t xQueueCreate( uint32_t uxQueueLength, - uint32_t uxItemSize ); - -void vQueueDelete( QueueHandle_t xQueue ); - -uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait); - -uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); - -void GetLastItem(void *pvBuffer); - -void ForceTaskDelete(); - -#define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len - +#ifndef ESP32_MOCK_H_ +#define ESP32_MOCK_H_ + +typedef void (*esp_timer_cb_t)(void* arg); + +typedef enum +{ + ESP_TIMER_TASK, //!< Callback is called from timer task +} esp_timer_dispatch_t; + +typedef struct +{ + esp_timer_cb_t callback; //!< Function to call when timer expires + void* arg; //!< Argument to pass to the callback + esp_timer_dispatch_t dispatch_method; //!< Call the callback from task or from ISR + const char* name; //!< Timer name, used in esp_timer_dump function +} esp_timer_create_args_t; + +esp_err_t esp_timer_delete(esp_timer_handle_t timer); + +esp_err_t esp_timer_stop(esp_timer_handle_t timer); + +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period); + +esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, + esp_timer_handle_t* out_handle); + + +// Queue mock + QueueHandle_t xQueueCreate( uint32_t uxQueueLength, + uint32_t uxItemSize ); + +void vQueueDelete( QueueHandle_t xQueue ); + +uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait); + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); + +void GetLastItem(void *pvBuffer); + +void ForceTaskDelete(); + +#define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len + #endif /* ESP32_MOCK_H_ */ \ No newline at end of file From 39de491597f58861e06ab50aff2de1fafa4d79b8 Mon Sep 17 00:00:00 2001 From: Piyush Shah Date: Thu, 12 Jul 2018 19:15:02 +0530 Subject: [PATCH 033/289] mdns: Minor fix for mdns_service_remove() Send the Goodbye packet while removing an mDNS service as an "Authoritative" packet so that the listeners remove the service from their records immediately. * Original commit: espressif/esp-idf@5c7eb7e27be7508130459d896cf7d13ffefda87f --- components/mdns/mdns.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 9fb64777e..6ffebf663 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1419,6 +1419,7 @@ static void _mdns_pcb_send_bye(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t i if (!packet) { return; } + packet->flags = MDNS_FLAGS_AUTHORITATIVE; size_t i; for (i=0; ianswers, MDNS_TYPE_PTR, services[i]->service, true, true)) { From dd714947d630a22f6c753893f5534104dd98bc6c Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 11 Jun 2018 08:32:40 +0200 Subject: [PATCH 034/289] added CI job for AFL fuzzer tests * Original commit: espressif/esp-idf@0c147648f7642d058b63fbe2ddd5de31c2326304 --- components/mdns/test_afl_fuzz_host/esp32_compat.h | 1 + 1 file changed, 1 insertion(+) diff --git a/components/mdns/test_afl_fuzz_host/esp32_compat.h b/components/mdns/test_afl_fuzz_host/esp32_compat.h index 402807c4f..7a662607c 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_compat.h +++ b/components/mdns/test_afl_fuzz_host/esp32_compat.h @@ -34,6 +34,7 @@ #include #include +#define CONFIG_MDNS_MAX_SERVICES 25 #define ERR_OK 0 #define ESP_OK 0 From b4ab30b5de169f84e9b5826ab20ded4b199430e2 Mon Sep 17 00:00:00 2001 From: Liu Han Date: Tue, 31 Jul 2018 10:00:02 +0800 Subject: [PATCH 035/289] mdns: Fix a portion of the queries are issued with the wildcard query type * Original commit: espressif/esp-idf@f3f0445f4db7c9ad97ae10a9728767337aa7bb62 --- components/mdns/mdns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 6ffebf663..09efde983 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1195,7 +1195,7 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed } if (service) { if (q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_ANY) { - if (q->type == MDNS_TYPE_PTR) { + if (q->type == MDNS_TYPE_PTR || !parsed_packet->probe) { shared = true; } if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service->service, false, false) @@ -2570,7 +2570,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) continue; } - if (type == MDNS_TYPE_ANY) { + if (type == MDNS_TYPE_ANY && !_str_null_or_empty(name->host)) { parsed_packet->probe = true; } From fed787f54f2a2ae1905d9371a6744a86cb56d54b Mon Sep 17 00:00:00 2001 From: Zhang Yan Jiao Date: Thu, 6 Sep 2018 19:43:08 +0800 Subject: [PATCH 036/289] Feature/sync lwip as submodule * Original commit: espressif/esp-idf@3578fe39e01ba0c2d54824ac70c3276502661c6b --- components/mdns/mdns_networking.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index e4ab816de..1779bd527 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -207,7 +207,7 @@ static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t i } typedef struct { - struct tcpip_api_call call; + struct tcpip_api_call_data call; tcpip_adapter_if_t tcpip_if; mdns_ip_protocol_t ip_protocol; esp_err_t err; @@ -216,7 +216,7 @@ typedef struct { /** * @brief Start PCB from LwIP thread */ -static err_t _mdns_pcb_init_api(struct tcpip_api_call *api_call_msg) +static err_t _mdns_pcb_init_api(struct tcpip_api_call_data *api_call_msg) { mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol); @@ -226,7 +226,7 @@ static err_t _mdns_pcb_init_api(struct tcpip_api_call *api_call_msg) /** * @brief Stop PCB from LwIP thread */ -static err_t _mdns_pcb_deinit_api(struct tcpip_api_call *api_call_msg) +static err_t _mdns_pcb_deinit_api(struct tcpip_api_call_data *api_call_msg) { mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol); @@ -245,7 +245,7 @@ esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_prot .tcpip_if = tcpip_if, .ip_protocol = ip_protocol }; - tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call_data*)&msg); return msg.err; } @@ -255,7 +255,7 @@ esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_pr .tcpip_if = tcpip_if, .ip_protocol = ip_protocol }; - tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call_data*)&msg); return msg.err; } From 67173f6770e714753037e4b393c64851284495a8 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Tue, 11 Sep 2018 09:44:12 +0800 Subject: [PATCH 037/289] cmake: make main a component again * Original commit: espressif/esp-idf@d9939cedd9b44d63dc148354c3a0a139b9c7113d --- components/mdns/CMakeLists.txt | 4 +++- examples/protocols/mdns/CMakeLists.txt | 4 +--- examples/protocols/mdns/main/CMakeLists.txt | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 examples/protocols/mdns/main/CMakeLists.txt diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 4ab664110..0933e3005 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -1,4 +1,6 @@ -set(COMPONENT_SRCDIRS ".") +set(COMPONENT_SRCS "mdns.c" + "mdns_console.c" + "mdns_networking.c") set(COMPONENT_ADD_INCLUDEDIRS "include") set(COMPONENT_PRIV_INCLUDEDIRS "private_include") set(COMPONENT_REQUIRES lwip mbedtls console tcpip_adapter) diff --git a/examples/protocols/mdns/CMakeLists.txt b/examples/protocols/mdns/CMakeLists.txt index 57c5e9a2e..88b7c1e3f 100644 --- a/examples/protocols/mdns/CMakeLists.txt +++ b/examples/protocols/mdns/CMakeLists.txt @@ -1,8 +1,6 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists +# The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(MAIN_SRCS main/mdns_example_main.c) - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mdns-test) diff --git a/examples/protocols/mdns/main/CMakeLists.txt b/examples/protocols/mdns/main/CMakeLists.txt new file mode 100644 index 000000000..814837ea9 --- /dev/null +++ b/examples/protocols/mdns/main/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCS "mdns_example_main.c") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() From 0c17121ad7886f5fcef53a3948e46caea737b7c7 Mon Sep 17 00:00:00 2001 From: Piyush Shah Date: Tue, 11 Sep 2018 16:20:00 +0530 Subject: [PATCH 038/289] bugfix: mdns_service_txt_set() wasn't allocating memory for TXT records Allocation was happening later, causing possible use of stack variables of caller function, which could be invalid. Signed-off-by: Piyush Shah * Original commit: espressif/esp-idf@e5e2702ca3f63a29da57eb138f75a20c74fb2a94 --- components/mdns/mdns.c | 35 ++++++++++--------- .../mdns/private_include/mdns_private.h | 3 +- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 09efde983..238da14a5 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1756,6 +1756,17 @@ static mdns_txt_linked_item_t * _mdns_allocate_txt(size_t num_items, mdns_txt_it } return new_txt; } +static void _mdns_free_linked_txt(mdns_txt_linked_item_t *txt) +{ + mdns_txt_linked_item_t *t; + while (txt) { + t = txt; + txt = txt->next; + free((char *)t->value); + free((char *)t->key); + free(t); + } +} /** * @brief creates/allocates new service @@ -3636,14 +3647,8 @@ static void _mdns_execute_action(mdns_action_t * action) service = action->data.srv_txt_replace.service->service; txt = service->txt; service->txt = NULL; - while (txt) { - t = txt; - txt = txt->next; - free((char *)t->value); - free((char *)t->key); - free(t); - } - service->txt = _mdns_allocate_txt(action->data.srv_txt_replace.num_items, action->data.srv_txt_replace.txt); + _mdns_free_linked_txt(txt); + service->txt = action->data.srv_txt_replace.txt; _mdns_announce_all_pcbs(&action->data.srv_txt_replace.service, 1, false); break; @@ -4224,27 +4229,25 @@ esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_tx return ESP_ERR_NOT_FOUND; } - mdns_txt_item_t * txt_copy = NULL; + mdns_txt_linked_item_t * new_txt = NULL; if (num_items){ - txt_copy = (mdns_txt_item_t *)malloc(num_items * sizeof(mdns_txt_item_t)); - if (!txt_copy) { + new_txt = _mdns_allocate_txt(num_items, txt); + if (!new_txt) { return ESP_ERR_NO_MEM; } - memcpy(txt_copy, txt, num_items * sizeof(mdns_txt_item_t)); } mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { - free(txt_copy); + _mdns_free_linked_txt(new_txt); return ESP_ERR_NO_MEM; } action->type = ACTION_SERVICE_TXT_REPLACE; action->data.srv_txt_replace.service = s; - action->data.srv_txt_replace.num_items = num_items; - action->data.srv_txt_replace.txt = txt_copy; + action->data.srv_txt_replace.txt = new_txt; if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { - free(txt_copy); + _mdns_free_linked_txt(new_txt); free(action); return ESP_ERR_NO_MEM; } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index d6edfb082..568c81b09 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -364,8 +364,7 @@ typedef struct { } srv_port; struct { mdns_srv_item_t * service; - uint8_t num_items; - mdns_txt_item_t * txt; + mdns_txt_linked_item_t * txt; } srv_txt_replace; struct { mdns_srv_item_t * service; From 81c219d4ee89fdd09ebf9ad233c329bc1f7ec112 Mon Sep 17 00:00:00 2001 From: Liu Han Date: Fri, 14 Sep 2018 15:36:52 +0800 Subject: [PATCH 039/289] feat(mdns): fix bug when clean action memory * Original commit: espressif/esp-idf@3d4deb972620cae8e8ce4d0050153cc6f39db372 --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 238da14a5..38d678268 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3565,7 +3565,7 @@ static void _mdns_free_action(mdns_action_t * action) free(action->data.srv_instance.instance); break; case ACTION_SERVICE_TXT_REPLACE: - free(action->data.srv_txt_replace.txt); + _mdns_free_linked_txt(action->data.srv_txt_replace.txt); break; case ACTION_SERVICE_TXT_SET: free(action->data.srv_txt_set.key); From ea2300753e7176869a19ee3bbac57ddc54f53a25 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 13 Sep 2018 12:01:11 +0200 Subject: [PATCH 040/289] Update network code for mDNS to work with newest LwIP - Uses one PCB that listens to all interfaces - Manages multicast groups for each interface * Original commit: espressif/esp-idf@3ec0e7e2d2ddea70e9f8fb5025664d0fe24c301a --- components/mdns/mdns_networking.c | 215 +++++++++++++++++------------- 1 file changed, 119 insertions(+), 96 deletions(-) diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index 1779bd527..4e64e36cf 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -14,6 +14,89 @@ extern mdns_server_t * _mdns_server; * */ +static struct udp_pcb * _pcb_main = NULL; + +static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport); + +/** + * @brief Low level UDP PCB Initialize + */ +static esp_err_t _udp_pcb_main_init() +{ + if(_pcb_main) { + return ESP_OK; + } + _pcb_main = udp_new(); + if (!_pcb_main) { + return ESP_ERR_NO_MEM; + } + if (udp_bind(_pcb_main, IP_ANY_TYPE, MDNS_SERVICE_PORT) != 0) { + udp_remove(_pcb_main); + _pcb_main = NULL; + return ESP_ERR_INVALID_STATE; + } + _pcb_main->mcast_ttl = 1; + _pcb_main->remote_port = MDNS_SERVICE_PORT; + ip_addr_copy(_pcb_main->remote_ip, ip_addr_any_type); + udp_recv(_pcb_main, &_udp_recv, _mdns_server); + return ESP_OK; +} + +/** + * @brief Low level UDP PCB Free + */ +static void _udp_pcb_main_deinit() +{ + if(_pcb_main){ + udp_recv(_pcb_main, NULL, NULL); + udp_disconnect(_pcb_main); + udp_remove(_pcb_main); + _pcb_main = NULL; + } +} + +/** + * @brief Low level UDP Multicast membership control + */ +static esp_err_t _udp_join_group(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, bool join) +{ + struct netif * netif = NULL; + void * nif = NULL; + esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif); + if (err) { + return ESP_ERR_INVALID_ARG; + } + netif = (struct netif *)nif; + + if (ip_protocol == MDNS_IP_PROTOCOL_V4) { + ip_addr_t multicast_addr; + IP_ADDR4(&multicast_addr, 224, 0, 0, 251); + + if(join){ + if (igmp_joingroup_netif(netif, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) { + return ESP_ERR_INVALID_STATE; + } + } else { + if (igmp_leavegroup_netif(netif, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) { + return ESP_ERR_INVALID_STATE; + } + } + } else { + ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); + + if(join){ + if (mld6_joingroup_netif(netif, &(multicast_addr.u_addr.ip6))) { + return ESP_ERR_INVALID_STATE; + } + } else { + if (mld6_leavegroup_netif(netif, &(multicast_addr.u_addr.ip6))) { + return ESP_ERR_INVALID_STATE; + } + } + } + return ESP_OK; +} + /** * @brief the receive callback of the raw udp api. Packets are received here * @@ -82,6 +165,21 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip } +/** + * @brief Check if any of the interfaces is up + */ +static bool _udp_pcb_is_in_use(){ + int i, p; + for (i=0; iinterfaces[i].pcbs[p].pcb){ + return true; + } + } + } + return false; +} + /** * @brief Stop PCB Main code */ @@ -92,118 +190,43 @@ static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_p } mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; if (_pcb->pcb) { - _pcb->state = PCB_OFF; - udp_recv(_pcb->pcb, NULL, NULL); - udp_disconnect(_pcb->pcb); - udp_remove(_pcb->pcb); free(_pcb->probe_services); + _pcb->state = PCB_OFF; _pcb->pcb = NULL; _pcb->probe_ip = false; _pcb->probe_services = NULL; _pcb->probe_services_len = 0; _pcb->probe_running = false; _pcb->failed_probes = 0; + _udp_join_group(tcpip_if, ip_protocol, false); + if(!_udp_pcb_is_in_use()) { + _udp_pcb_main_deinit(); + } } } -/** - * @brief Start PCB V4 - */ -static esp_err_t _udp_pcb_v4_init(tcpip_adapter_if_t tcpip_if) -{ - tcpip_adapter_ip_info_t if_ip_info; - - if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) { - return ESP_ERR_INVALID_STATE; - } - - if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info) || if_ip_info.ip.addr == 0) { - return ESP_ERR_INVALID_ARG; - } - - ip_addr_t interface_addr = IPADDR4_INIT(if_ip_info.ip.addr); - - ip_addr_t multicast_addr; - IP_ADDR4(&multicast_addr, 224, 0, 0, 251); - - if (igmp_joingroup((const struct ip4_addr *)&interface_addr.u_addr.ip4, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) { - return ESP_ERR_INVALID_STATE; - } - - struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V4); - if (!pcb) { - return ESP_ERR_NO_MEM; - } - - if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { - udp_remove(pcb); - return ESP_ERR_INVALID_STATE; - } - - pcb->mcast_ttl = 1; - pcb->remote_port = MDNS_SERVICE_PORT; - ip_addr_copy(pcb->multicast_ip, interface_addr); - ip_addr_copy(pcb->remote_ip, multicast_addr); - - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb = pcb; - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].failed_probes = 0; - udp_recv(pcb, &_udp_recv, _mdns_server); - - return ESP_OK; -} - -/** - * @brief Start PCB V6 - */ -static esp_err_t _udp_pcb_v6_init(tcpip_adapter_if_t tcpip_if) -{ - ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); - ip_addr_t interface_addr; - interface_addr.type = IPADDR_TYPE_V6; - - if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) { - return ESP_ERR_INVALID_STATE; - } - - if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &interface_addr.u_addr.ip6)) { - return ESP_ERR_INVALID_ARG; - } - - if (mld6_joingroup(&(interface_addr.u_addr.ip6), &(multicast_addr.u_addr.ip6))) { - return ESP_ERR_INVALID_STATE; - } - - struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V6); - if (!pcb) { - return ESP_ERR_NO_MEM; - } - - if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { - udp_remove(pcb); - return ESP_ERR_INVALID_STATE; - } - - pcb->remote_port = MDNS_SERVICE_PORT; - ip_addr_copy(pcb->remote_ip, multicast_addr); - - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb = pcb; - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].failed_probes = 0; - udp_recv(pcb, &_udp_recv, _mdns_server); - - return ESP_OK; -} - /** * @brief Start PCB Main code */ static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { - if (ip_protocol == MDNS_IP_PROTOCOL_V4) { - return _udp_pcb_v4_init(tcpip_if); - } else if (ip_protocol == MDNS_IP_PROTOCOL_V6) { - return _udp_pcb_v6_init(tcpip_if); + if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) { + return ESP_ERR_INVALID_STATE; } - return ESP_ERR_INVALID_ARG; + + esp_err_t err = _udp_join_group(tcpip_if, ip_protocol, true); + if(err){ + return err; + } + + err = _udp_pcb_main_init(); + if(err){ + return err; + } + + _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb = _pcb_main; + _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].failed_probes = 0; + return ESP_OK; } typedef struct { From 9b3b41c3f1b60ccc2ebb5d82ccfe5c8b0315f9e1 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 22 Oct 2018 16:45:42 +0200 Subject: [PATCH 041/289] mdns: fixed crashes on network changes 1) two events AP_STOP, AP_START shortly after each other may cause IGMP config on already stopped netif 2) not properly locked sending packets to queue from timer task closes #2580 * Original commit: espressif/esp-idf@097282a8e3f85958747430d9931ce0a545d37700 --- components/mdns/mdns.c | 3 ++- components/mdns/mdns_networking.c | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 38d678268..443b39846 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3794,13 +3794,14 @@ static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_o */ static void _mdns_scheduler_run() { + MDNS_SERVICE_LOCK(); mdns_tx_packet_t * p = _mdns_server->tx_queue_head; mdns_action_t * action = NULL; if (!p) { + MDNS_SERVICE_UNLOCK(); return; } - MDNS_SERVICE_LOCK(); if ((int32_t)(p->send_at - (xTaskGetTickCount() * portTICK_PERIOD_MS)) < 0) { action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (action) { diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index 4e64e36cf..9aac3ec89 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -62,6 +62,12 @@ static esp_err_t _udp_join_group(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t { struct netif * netif = NULL; void * nif = NULL; + + if (!tcpip_adapter_is_netif_up(tcpip_if)) { + // Network interface went down before event propagated, skipping IGMP config + return ESP_ERR_INVALID_STATE; + } + esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif); if (err) { return ESP_ERR_INVALID_ARG; From 8cd0e8a5018739e6eaf8f851fd3b78b6217303ef Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 12 Oct 2018 08:13:55 +0200 Subject: [PATCH 042/289] mdns: sending search packets also in probing and announcing state mdns queries did not work properly when send imeadiately after set_hostname, which cuased reinit of pcb and therefore restarted probing, so search packets were blocked until probing finished closes #2507, closes #2593 * Original commit: espressif/esp-idf@d16762a036e35ce86ece86bb44e6e99f9cc7c431 --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 443b39846..f5d337a32 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3465,7 +3465,7 @@ static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search static void _mdns_search_send_pcb(mdns_search_once_t * search, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_tx_packet_t * packet = NULL; - if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb && _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state == PCB_RUNNING) { + if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb && _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state > PCB_INIT) { packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol); if (!packet) { return; From ade4aeffa555d5c45b2717e2955850885ecc2229 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 12 Oct 2018 16:45:52 +0200 Subject: [PATCH 043/289] mdns: added example test for ci runners * Original commit: espressif/esp-idf@6309643c1ddb291c61d48f6fb84249a8e0d4f0a0 --- examples/protocols/mdns/README.md | 88 ++++++++++++- .../protocols/mdns/main/Kconfig.projbuild | 35 ++++-- .../protocols/mdns/main/mdns_example_main.c | 23 +++- examples/protocols/mdns/mdns_example_test.py | 117 ++++++++++++++++++ 4 files changed, 241 insertions(+), 22 deletions(-) create mode 100644 examples/protocols/mdns/mdns_example_test.py diff --git a/examples/protocols/mdns/README.md b/examples/protocols/mdns/README.md index 8cc56d835..b4745a111 100644 --- a/examples/protocols/mdns/README.md +++ b/examples/protocols/mdns/README.md @@ -10,12 +10,88 @@ Shows how to use mDNS to advertise lookup services and hosts - GPIO0 (BOOT Button) is initialized as pulled-up input that can be monitored for button press - Example task is started to check if the button is pressed so it can execute the mDNS queries defined -## Running the example +### Configure the project -- Run `make menuconfig` to configure the access point's SSID and Password and the default device mDNS host name and instance name -- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal -- Wait for WiFi to connec to your access point -- You can now ping the device at `[hostname].local` and browse for `_http._tcp` on the same network to find the advertised service -- Pressing the BOOT button will start quring the local network for the predefined in `check_button` hosts and services +``` +make menuconfig +``` + +* Set `Default serial port` under `Serial flasher config`. +* Set `WiFi SSID` and `WiFi Password` for the board to connect to AP. +* Set `mDNS Hostname` as host name prefix for the device and its instance name in `mDNS Instance Name` +* Disable `Resolve test services` to prevent the example from querying defined names/services on startup (cause warnings in example logs, as illustrated below) + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +make -j4 flash monitor +``` +- Wait for WiFi to connect to your access point +- You can now ping the device at `[board-hostname].local`, where `[board-hostname]` is a string created from preconfigured hostname (`esp32-mdns` by default) and last 3 bytes from device MAC address. Please check the serial output log for the specific board-hostname (`esp32-mdns_80FFFF` in the log below) +- You can also browse for `_http._tcp` on the same network to find the advertised service +- Pressing the BOOT button will start querying the local network for the predefined in `check_button` hosts and services + + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output +``` +I (0) cpu_start: Starting scheduler on APP CPU. +I (276) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (276) mdns-test: mdns hostname set to: [esp32-mdns_80FFFF] +I (286) wifi: wifi driver task: 3ffc2fa4, prio:23, stack:3584, core=0 +I (286) wifi: wifi firmware version: a3be639 +I (286) wifi: config NVS flash: enabled +I (296) wifi: config nano formating: disabled +I (296) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (306) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (336) wifi: Init dynamic tx buffer num: 32 +I (336) wifi: Init data frame dynamic rx buffer num: 32 +I (336) wifi: Init management frame dynamic rx buffer num: 32 +I (346) wifi: Init static rx buffer size: 1600 +I (346) wifi: Init static rx buffer num: 10 +I (346) wifi: Init dynamic rx buffer num: 32 +I (356) mdns-test: Setting WiFi configuration SSID myssid... +I (426) phy: phy_version: 4000, b6198fa, Sep 3 2018, 15:11:06, 0, 0 +I (426) wifi: mode : sta (30:ae:a4:80:FF:FF) +I (426) gpio: GPIO[0]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 +I (1756) wifi: n:11 0, o:1 0, ap:255 255, sta:11 0, prof:1 +I (2736) wifi: state: init -> auth (b0) +I (2756) wifi: state: auth -> assoc (0) +I (2766) wifi: state: assoc -> run (10) +I (2786) wifi: connected with myssid, channel 11 +I (2786) wifi: pm start, type: 1 + +I (4786) event: sta ip: 192.168.0.139, mask: 255.255.255.0, gw: 192.168.0.2 +I (4786) mdns-test: Query A: tinytester.local +W (6876) mdns-test: ESP_ERR_NOT_FOUND: Host was not found! +I (6876) mdns-test: Query PTR: _tiny._tcp.local +W (9976) mdns-test: No results found! +I (21126) mdns-test: Query A: esp32.local +W (23176) mdns-test: ESP_ERR_NOT_FOUND: Host was not found! +I (23176) mdns-test: Query PTR: _arduino._tcp.local +W (26276) mdns-test: No results found! +I (26276) mdns-test: Query PTR: _http._tcp.local +1: Interface: STA, Type: V6 + PTR : HP Color LaserJet MFP M277dw (7C2E10) + SRV : NPI7C2E10.local:80 + A : 254.128.0.0 +2: Interface: STA, Type: V4 + PTR : switch4e4919 + SRV : switch4e4919.local:80 + TXT : [1] path=/config/authentication_page.htm; + A : 192.168.0.118 +I (29396) mdns-test: Query PTR: _printer._tcp.local +1: Interface: STA, Type: V6 + PTR : HP Color LaserJet MFP M277dw (7C2E10) + SRV : NPI7C2E10.local:515 + A : 254.128.0.0 +2: Interface: STA, Type: V4 + PTR : HP Color LaserJet MFP M277dw (7C2E10) +``` See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index a55b0bf4c..9cbca2f6b 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -2,28 +2,37 @@ menu "Example Configuration" config WIFI_SSID string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. + default "myssid" + help + SSID (network name) for the example to connect to. config WIFI_PASSWORD string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. + Can be left blank if the network has no security set. config MDNS_HOSTNAME string "mDNS Hostname" - default "esp32-mdns" - help - mDNS Hostname for example to use + default "esp32-mdns" + help + mDNS Hostname for example to use config MDNS_INSTANCE string "mDNS Instance Name" - default "ESP32 with mDNS" - help - mDNS Instance Name for example to use + default "ESP32 with mDNS" + help + mDNS Instance Name for example to use + +config RESOLVE_TEST_SERVICES + bool "Resolve test services" + default y + help + Enable resolving test services on startup. + These services are advertized and evaluated in automated tests. + When executed locally, these will not be resolved and warnings appear in the log. + Please set to false to disable initial querying to avoid warnings. endmenu diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index fb805545a..ad9b6f275 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -29,11 +29,12 @@ #define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID #define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD -#define EXAMPLE_MDNS_HOSTNAME CONFIG_MDNS_HOSTNAME #define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE + /* FreeRTOS event group to signal when we are connected & ready to make a request */ static EventGroupHandle_t wifi_event_group; +static const char c_config_hostname[] = CONFIG_MDNS_HOSTNAME; /* The event group allows multiple bits for each event, but we only care about one event - are we connected @@ -97,10 +98,20 @@ static void initialise_wifi(void) static void initialise_mdns(void) { + _Static_assert(sizeof(c_config_hostname) < CONFIG_MAIN_TASK_STACK_SIZE/2, "Configured mDNS name consumes more than half of the stack. Please select a shorter host name or extend the main stack size please."); + const size_t config_hostname_len = sizeof(c_config_hostname) - 1; // without term char + char hostname[config_hostname_len + 1 + 3*2 + 1]; // adding underscore + 3 digits + term char + uint8_t mac[6]; + + // adding 3 LSBs from mac addr to setup a board specific name + esp_read_mac(mac, ESP_MAC_WIFI_STA); + snprintf(hostname, sizeof(hostname), "%s_%02x%02X%02X", c_config_hostname, mac[3], mac[4], mac[5]); + //initialize mDNS ESP_ERROR_CHECK( mdns_init() ); //set mDNS hostname (required if you want to advertise services) - ESP_ERROR_CHECK( mdns_hostname_set(EXAMPLE_MDNS_HOSTNAME) ); + ESP_ERROR_CHECK( mdns_hostname_set(hostname) ); + ESP_LOGI(TAG, "mdns hostname set to: [%s]", hostname); //set default mDNS instance name ESP_ERROR_CHECK( mdns_instance_name_set(EXAMPLE_MDNS_INSTANCE) ); @@ -191,7 +202,7 @@ static void query_mdns_host(const char * host_name) return; } - ESP_LOGI(TAG, IPSTR, IP2STR(&addr)); + ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr)); } static void initialise_button(void) @@ -228,6 +239,12 @@ static void mdns_example_task(void *pvParameters) /* Wait for the callback to set the CONNECTED_BIT in the event group. */ xEventGroupWaitBits(wifi_event_group, IP4_CONNECTED_BIT | IP6_CONNECTED_BIT, false, true, portMAX_DELAY); + +#if CONFIG_RESOLVE_TEST_SERVICES == 1 + /* Send initial queries that are started by CI tester */ + query_mdns_host("tinytester"); +#endif + while(1) { check_button(); vTaskDelay(50 / portTICK_PERIOD_MS); diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py new file mode 100644 index 000000000..1cd1877d6 --- /dev/null +++ b/examples/protocols/mdns/mdns_example_test.py @@ -0,0 +1,117 @@ +import re +import os +import sys +import socket +import time +import imp +import struct +import dpkt, dpkt.dns +from threading import Thread + + + +# this is a test case write with tiny-test-fw. +# to run test cases outside tiny-test-fw, +# we need to set environment variable `TEST_FW_PATH`, +# then get and insert `TEST_FW_PATH` to sys path before import FW module + +test_fw_path = os.getenv("TEST_FW_PATH") +if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + +import TinyFW +import IDF + +g_run_server = True +g_done = False + +def mdns_server(esp_host): + global g_run_server + global g_done + UDP_IP="0.0.0.0" + UDP_PORT=5353 + MCAST_GRP = '224.0.0.251' + sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + sock.bind( (UDP_IP,UDP_PORT) ) + mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') + # sock.sendto(dns.pack(),(MCAST_GRP,UDP_PORT)) + sock.settimeout(30) + resp_dns = dpkt.dns.DNS(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + resp_dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA + resp_dns.rcode = dpkt.dns.DNS_RCODE_NOERR + arr = dpkt.dns.DNS.RR() + arr.cls = dpkt.dns.DNS_IN + arr.type = dpkt.dns.DNS_A + arr.name = u'tinytester.local' + arr.ip =socket.inet_aton('127.0.0.1') + resp_dns. an.append(arr) + sock.sendto(resp_dns.pack(),(MCAST_GRP,UDP_PORT)) + while g_run_server: + try: + m=sock.recvfrom( 1024 ); + dns = dpkt.dns.DNS(m[0]) + if len(dns.qd)>0 and dns.qd[0].type == dpkt.dns.DNS_A: + if dns.qd[0].name == u'tinytester.local': + print (dns.__repr__(),dns.qd[0].name) + sock.sendto(resp_dns.pack(),(MCAST_GRP,UDP_PORT)) + if len(dns.an)>0 and dns.an[0].type == dpkt.dns.DNS_A: + if dns.an[0].name == esp_host + u'.local': + print("Received answer esp32-mdns query") + g_done = True + print (dns.an[0].name) + dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') + dns.qd[0].name= esp_host + u'.local' + sock.sendto(dns.pack(),(MCAST_GRP,UDP_PORT)) + print("Sending esp32-mdns query") + time.sleep(0.5) + except socket.timeout: + break + +@IDF.idf_example_test(env_tag="Example_WIFI") +def test_examples_protocol_mdns(env, extra_data): + global g_run_server + global g_done + """ + steps: | + 1. join AP + init mdns example + 2. get the dut host name (and IP address) + 3. check the mdns name is accessible + 4. check DUT output if mdns advertized host is resolved + """ + dut1 = env.get_dut("mdns-test", "examples/protocols/mdns") + # check and log bin size + binary_file = os.path.join(dut1.app.binary_path, "mdns-test.bin") + bin_size = os.path.getsize(binary_file) + IDF.log_performance("mdns-test_bin_size", "{}KB".format(bin_size//1024)) + IDF.check_performance("mdns-test_bin_size", bin_size//1024) + # 1. start mdns application + dut1.start_app() + # 2. get the dut host name (and IP address) + specific_host = dut1.expect(re.compile(r"mdns hostname set to: \[([^\]]+)\]"), timeout=30) + specific_host = str(specific_host[0]) + dut_ip = "" + try: + dut_ip = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) + except DUT.ExpectTimeout: + raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') + # 3. check the mdns name is accessible + thread1 = Thread(target = mdns_server, args = (specific_host,)) + thread1.start() + start = time.time() + while (time.time() - start) <= 60: + if g_done: + print("Test passed") + break + g_run_server = False + thread1.join() + if g_done == False: + raise ValueError('Test has failed: did not receive mdns answer within timeout') + # 4. check DUT output if mdns advertized host is resolved + dut1.expect(re.compile(r"mdns-test: Query A: tinytester.local resolved to: 127.0.0.1"), timeout=30) + +if __name__ == '__main__': + test_examples_protocol_mdns() From dce0b26ef8a276220d1a0308b544c1831edb6940 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Tue, 4 Dec 2018 08:32:48 +0100 Subject: [PATCH 044/289] examples: Fix Python coding style * Original commit: espressif/esp-idf@57c54f96f1e58df6383fae5b8635fc15da816838 --- examples/protocols/mdns/mdns_example_test.py | 56 +++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index 1cd1877d6..111935291 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -3,38 +3,41 @@ import os import sys import socket import time -import imp import struct -import dpkt, dpkt.dns +import dpkt +import dpkt.dns from threading import Thread - # this is a test case write with tiny-test-fw. # to run test cases outside tiny-test-fw, # we need to set environment variable `TEST_FW_PATH`, # then get and insert `TEST_FW_PATH` to sys path before import FW module -test_fw_path = os.getenv("TEST_FW_PATH") -if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) +try: + import IDF +except ImportError: + test_fw_path = os.getenv("TEST_FW_PATH") + if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + import IDF -import TinyFW -import IDF +import DUT g_run_server = True g_done = False + def mdns_server(esp_host): global g_run_server global g_done - UDP_IP="0.0.0.0" - UDP_PORT=5353 + UDP_IP = "0.0.0.0" + UDP_PORT = 5353 MCAST_GRP = '224.0.0.251' - sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) - sock.bind( (UDP_IP,UDP_PORT) ) + sock.bind((UDP_IP,UDP_PORT)) mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') @@ -47,30 +50,31 @@ def mdns_server(esp_host): arr.cls = dpkt.dns.DNS_IN arr.type = dpkt.dns.DNS_A arr.name = u'tinytester.local' - arr.ip =socket.inet_aton('127.0.0.1') + arr.ip = socket.inet_aton('127.0.0.1') resp_dns. an.append(arr) sock.sendto(resp_dns.pack(),(MCAST_GRP,UDP_PORT)) while g_run_server: try: - m=sock.recvfrom( 1024 ); + m = sock.recvfrom(1024) dns = dpkt.dns.DNS(m[0]) - if len(dns.qd)>0 and dns.qd[0].type == dpkt.dns.DNS_A: + if len(dns.qd) > 0 and dns.qd[0].type == dpkt.dns.DNS_A: if dns.qd[0].name == u'tinytester.local': - print (dns.__repr__(),dns.qd[0].name) + print(dns.__repr__(),dns.qd[0].name) sock.sendto(resp_dns.pack(),(MCAST_GRP,UDP_PORT)) - if len(dns.an)>0 and dns.an[0].type == dpkt.dns.DNS_A: - if dns.an[0].name == esp_host + u'.local': + if len(dns.an) > 0 and dns.an[0].type == dpkt.dns.DNS_A: + if dns.an[0].name == esp_host + u'.local': print("Received answer esp32-mdns query") g_done = True - print (dns.an[0].name) + print(dns.an[0].name) dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') - dns.qd[0].name= esp_host + u'.local' + dns.qd[0].name = esp_host + u'.local' sock.sendto(dns.pack(),(MCAST_GRP,UDP_PORT)) print("Sending esp32-mdns query") time.sleep(0.5) except socket.timeout: break + @IDF.idf_example_test(env_tag="Example_WIFI") def test_examples_protocol_mdns(env, extra_data): global g_run_server @@ -86,20 +90,19 @@ def test_examples_protocol_mdns(env, extra_data): # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "mdns-test.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("mdns-test_bin_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("mdns-test_bin_size", bin_size//1024) + IDF.log_performance("mdns-test_bin_size", "{}KB".format(bin_size // 1024)) + IDF.check_performance("mdns-test_bin_size", bin_size // 1024) # 1. start mdns application dut1.start_app() # 2. get the dut host name (and IP address) specific_host = dut1.expect(re.compile(r"mdns hostname set to: \[([^\]]+)\]"), timeout=30) specific_host = str(specific_host[0]) - dut_ip = "" try: - dut_ip = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) + dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) except DUT.ExpectTimeout: raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') # 3. check the mdns name is accessible - thread1 = Thread(target = mdns_server, args = (specific_host,)) + thread1 = Thread(target=mdns_server, args=(specific_host,)) thread1.start() start = time.time() while (time.time() - start) <= 60: @@ -108,10 +111,11 @@ def test_examples_protocol_mdns(env, extra_data): break g_run_server = False thread1.join() - if g_done == False: + if g_done is False: raise ValueError('Test has failed: did not receive mdns answer within timeout') # 4. check DUT output if mdns advertized host is resolved dut1.expect(re.compile(r"mdns-test: Query A: tinytester.local resolved to: 127.0.0.1"), timeout=30) + if __name__ == '__main__': test_examples_protocol_mdns() From 2763bcdb8de2e1d6199a8cfbec7a68d9c2b4f9ab Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 30 Nov 2018 17:00:05 +0100 Subject: [PATCH 045/289] mdns: skip sending search when finished, not properly locked timer task * Original commit: espressif/esp-idf@31163f02d5c414d8b492dce6f729b43a0061581b --- components/mdns/mdns.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index f5d337a32..ff8df426e 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3480,6 +3480,22 @@ static void _mdns_search_send_pcb(mdns_search_once_t * search, tcpip_adapter_if_ */ static void _mdns_search_send(mdns_search_once_t * search) { + mdns_search_once_t* queue = _mdns_server->search_once; + bool found = false; + // looking for this search in active searches + while (queue) { + if (queue == search) { + found = true; + break; + } + queue = queue->next; + } + + if (!found) { + // no longer active -> skip sending this search + return; + } + uint8_t i, j; for (i=0; isearch_once; uint32_t now = xTaskGetTickCount() * portTICK_PERIOD_MS; if (!s) { + MDNS_SERVICE_UNLOCK(); return; } - MDNS_SERVICE_LOCK(); while (s) { if (s->state != SEARCH_OFF) { if (now > (s->started_at + s->timeout)) { From b4e57424f9832512970f2c785ff30209c9027f2c Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 6 Dec 2018 16:46:31 +0100 Subject: [PATCH 046/289] mdns: resolve memory leak when txt record received multiple times * Original commit: espressif/esp-idf@a6b2b73f03bbb75a39685ddba6cf877fd1e5e6d7 --- components/mdns/mdns.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index ff8df426e..4ad1da3ee 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2769,10 +2769,6 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) if (search_result) { mdns_txt_item_t * txt = NULL; size_t txt_count = 0; - _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_count); - if (!txt_count) { - continue; - } mdns_result_t * result = NULL; if (search_result->type == MDNS_TYPE_PTR) { @@ -2792,8 +2788,11 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } } if (!result->txt) { - result->txt = txt; - result->txt_count = txt_count; + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_count); + if (txt_count) { + result->txt = txt; + result->txt_count = txt_count; + } } } else { _mdns_search_result_add_txt(search_result, txt, txt_count, packet->tcpip_if, packet->ip_protocol); @@ -3305,7 +3304,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it while (r) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol) { if (r->txt) { - return; + goto free_txt; } r->txt = txt; r->txt_count = txt_count; @@ -3316,12 +3315,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it if (!search->max_results || search->num_results < search->max_results) { r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); if (!r) { - for (i=0; iresult = r; search->num_results++; } + return; + +free_txt: + for (i=0; i Date: Fri, 7 Dec 2018 20:43:13 +0100 Subject: [PATCH 047/289] mdns: check all mallocs for failure and add default hook to log error with free heap solves crash about _mdns_result_txt_create when stress test * Original commit: espressif/esp-idf@c8cb4cd3c8eb56d5901ade03302ad1231d7f3de5 --- components/mdns/mdns.c | 60 +++++++++++++++++++ components/mdns/mdns_networking.c | 3 + .../mdns/private_include/mdns_private.h | 3 + 3 files changed, 66 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 4ad1da3ee..3617edbb5 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -15,6 +15,7 @@ #include "mdns.h" #include "mdns_private.h" #include "mdns_networking.h" +#include "esp_log.h" #include #ifdef MDNS_ENABLE_DEBUG @@ -26,6 +27,8 @@ static const char * MDNS_SUB_STR = "_sub"; mdns_server_t * _mdns_server = NULL; +static const char *TAG = "MDNS"; + static volatile TaskHandle_t _mdns_service_task_handle = NULL; static SemaphoreHandle_t _mdns_service_semaphore = NULL; @@ -63,11 +66,16 @@ static char * _mdns_mangle_name(char* in) { //need to add -2 to string ret = malloc(strlen(in) + 3); if (ret == NULL) { + HOOK_MALLOC_FAILED; return NULL; } sprintf(ret, "%s-2", in); } else { ret = malloc(strlen(in) + 2); //one extra byte in case 9-10 or 99-100 etc + if (ret == NULL) { + HOOK_MALLOC_FAILED; + return NULL; + } strcpy(ret, in); int baseLen = p - in; //length of 'bla' in 'bla-123' //overwrite suffix with new suffix @@ -117,6 +125,7 @@ esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet) action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } @@ -557,6 +566,9 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns return 0; } data_len += l; + } else { + HOOK_MALLOC_FAILED; + // continue } txt = txt->next; } @@ -1130,6 +1142,7 @@ static bool _mdns_alloc_answer(mdns_out_answer_t ** destnation, uint16_t type, m mdns_out_answer_t * a = (mdns_out_answer_t *)malloc(sizeof(mdns_out_answer_t)); if (!a) { + HOOK_MALLOC_FAILED; return false; } a->type = type; @@ -1148,6 +1161,7 @@ static mdns_tx_packet_t * _mdns_alloc_packet_default(tcpip_adapter_if_t tcpip_if { mdns_tx_packet_t * packet = (mdns_tx_packet_t*)malloc(sizeof(mdns_tx_packet_t)); if (!packet) { + HOOK_MALLOC_FAILED; return NULL; } memset((uint8_t*)packet, 0, sizeof(mdns_tx_packet_t)); @@ -1285,6 +1299,7 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(tcpip_adapter_if_t tcpip_if, for (i=0; ihostname)) { mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); if (!q) { + HOOK_MALLOC_FAILED; _mdns_free_tx_packet(packet); return NULL; } @@ -1457,6 +1473,7 @@ static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t if (services_final_len) { _services = (mdns_srv_item_t **)malloc(sizeof(mdns_srv_item_t *) * services_final_len); if (!_services) { + HOOK_MALLOC_FAILED; return; } @@ -1737,6 +1754,7 @@ static mdns_txt_linked_item_t * _mdns_allocate_txt(size_t num_items, mdns_txt_it for (i=0; ikey = strdup(txt[i].key); @@ -1783,6 +1801,7 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * { mdns_service_t * s = (mdns_service_t *)malloc(sizeof(mdns_service_t)); if (!s) { + HOOK_MALLOC_FAILED; return NULL; } @@ -2046,6 +2065,9 @@ static int _mdns_check_txt_collision(mdns_service_t * service, const uint8_t * d sprintf(tmp, "%s=%s", txt->key, txt->value); _mdns_append_string(ours, &index, tmp); free(tmp); + } else { + HOOK_MALLOC_FAILED; + // continue } txt = txt->next; } @@ -2402,6 +2424,10 @@ static void _mdns_result_txt_create(const uint8_t * data, size_t len, mdns_txt_i } mdns_txt_item_t * txt = (mdns_txt_item_t *)malloc(sizeof(mdns_txt_item_t) * num_items); + if (!txt) { + HOOK_MALLOC_FAILED; + return; + } memset(txt, 0, sizeof(mdns_txt_item_t) * num_items); size_t txt_num = 0; @@ -2422,6 +2448,7 @@ static void _mdns_result_txt_create(const uint8_t * data, size_t len, mdns_txt_i } char * key = (char *)malloc(name_len + 1); if (!key) { + HOOK_MALLOC_FAILED; goto handle_error;//error } @@ -2435,6 +2462,10 @@ static void _mdns_result_txt_create(const uint8_t * data, size_t len, mdns_txt_i int value_len = partLen - name_len - 1; if (value_len > 0) { char * value = (char *)malloc(value_len + 1); + if (!value) { + HOOK_MALLOC_FAILED; + goto handle_error;//error + } memcpy(value, data + i, value_len); value[value_len] = 0; i += value_len; @@ -2498,6 +2529,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) mdns_parsed_packet_t * parsed_packet = (mdns_parsed_packet_t *)malloc(sizeof(mdns_parsed_packet_t)); if (!parsed_packet) { + HOOK_MALLOC_FAILED; return; } memset(parsed_packet, 0, sizeof(mdns_parsed_packet_t)); @@ -2560,6 +2592,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) while (a) { mdns_parsed_question_t * question = (mdns_parsed_question_t *)malloc(sizeof(mdns_parsed_question_t)); if (!question) { + HOOK_MALLOC_FAILED; goto clear_rx_packet; } question->next = parsed_packet->questions; @@ -2587,6 +2620,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) mdns_parsed_question_t * question = (mdns_parsed_question_t *)malloc(sizeof(mdns_parsed_question_t)); if (!question) { + HOOK_MALLOC_FAILED; goto clear_rx_packet; } question->next = parsed_packet->questions; @@ -3046,6 +3080,7 @@ static mdns_search_once_t * _mdns_search_init(const char * name, const char * se { mdns_search_once_t * search = (mdns_search_once_t *)malloc(sizeof(mdns_search_once_t)); if (!search) { + HOOK_MALLOC_FAILED; return NULL; } memset(search, 0, sizeof(mdns_search_once_t)); @@ -3137,6 +3172,7 @@ static mdns_ip_addr_t * _mdns_result_addr_create_ip(ip_addr_t * ip) { mdns_ip_addr_t * a = (mdns_ip_addr_t *)malloc(sizeof(mdns_ip_addr_t)); if (!a) { + HOOK_MALLOC_FAILED; return NULL; } memset(a, 0 , sizeof(mdns_ip_addr_t)); @@ -3196,6 +3232,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * if (!search->max_results || search->num_results < search->max_results) { r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); if (!r) { + HOOK_MALLOC_FAILED; return; } @@ -3241,6 +3278,7 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, if (!search->max_results || search->num_results < search->max_results) { r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); if (!r) { + HOOK_MALLOC_FAILED; return NULL; } @@ -3276,6 +3314,7 @@ static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char if (!search->max_results || search->num_results < search->max_results) { r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); if (!r) { + HOOK_MALLOC_FAILED; return; } @@ -3315,6 +3354,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it if (!search->max_results || search->num_results < search->max_results) { r = (mdns_result_t *)malloc(sizeof(mdns_result_t)); if (!r) { + HOOK_MALLOC_FAILED; goto free_txt; } @@ -3420,6 +3460,7 @@ static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); if (!q) { + HOOK_MALLOC_FAILED; _mdns_free_tx_packet(packet); return NULL; } @@ -3442,6 +3483,7 @@ static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search } mdns_out_answer_t * a = (mdns_out_answer_t *)malloc(sizeof(mdns_out_answer_t)); if (!a) { + HOOK_MALLOC_FAILED; _mdns_free_tx_packet(packet); return NULL; } @@ -3687,6 +3729,7 @@ static void _mdns_execute_action(mdns_action_t * action) if (!txt) { txt = (mdns_txt_linked_item_t *)malloc(sizeof(mdns_txt_linked_item_t)); if (!txt) { + HOOK_MALLOC_FAILED; _mdns_free_action(action); return; } @@ -3795,6 +3838,7 @@ static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_o action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } @@ -3830,6 +3874,9 @@ static void _mdns_scheduler_run() free(action); _mdns_server->tx_queue_head = p; } + } else { + HOOK_MALLOC_FAILED; + // continue } } MDNS_SERVICE_UNLOCK(); @@ -3992,6 +4039,7 @@ esp_err_t mdns_handle_system_event(void *ctx, system_event_t *event) mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_OK; } action->type = ACTION_SYSTEM_EVENT; @@ -4013,6 +4061,7 @@ esp_err_t mdns_init() _mdns_server = (mdns_server_t *)malloc(sizeof(mdns_server_t)); if (!_mdns_server) { + HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } memset((uint8_t*)_mdns_server, 0, sizeof(mdns_server_t)); @@ -4115,6 +4164,7 @@ esp_err_t mdns_hostname_set(const char * hostname) mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; free(new_hostname); return ESP_ERR_NO_MEM; } @@ -4143,6 +4193,7 @@ esp_err_t mdns_instance_name_set(const char * instance) mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; free(new_instance); return ESP_ERR_NO_MEM; } @@ -4182,6 +4233,7 @@ esp_err_t mdns_service_add(const char * instance, const char * service, const ch item = (mdns_srv_item_t *)malloc(sizeof(mdns_srv_item_t)); if (!item) { + HOOK_MALLOC_FAILED; _mdns_free_service(s); return ESP_ERR_NO_MEM; } @@ -4191,6 +4243,7 @@ esp_err_t mdns_service_add(const char * instance, const char * service, const ch mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; _mdns_free_service(s); free(item); return ESP_ERR_NO_MEM; @@ -4227,6 +4280,7 @@ esp_err_t mdns_service_port_set(const char * service, const char * proto, uint16 mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } action->type = ACTION_SERVICE_PORT_SET; @@ -4259,6 +4313,7 @@ esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_tx mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; _mdns_free_linked_txt(new_txt); return ESP_ERR_NO_MEM; } @@ -4286,6 +4341,7 @@ esp_err_t mdns_service_txt_item_set(const char * service, const char * proto, co } mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } @@ -4322,6 +4378,7 @@ esp_err_t mdns_service_txt_item_remove(const char * service, const char * proto, } mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } @@ -4359,6 +4416,7 @@ esp_err_t mdns_service_instance_name_set(const char * service, const char * prot mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; free(new_instance); return ESP_ERR_NO_MEM; } @@ -4385,6 +4443,7 @@ esp_err_t mdns_service_remove(const char * service, const char * proto) mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } action->type = ACTION_SERVICE_DEL; @@ -4407,6 +4466,7 @@ esp_err_t mdns_service_remove_all() mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { + HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; } action->type = ACTION_SERVICES_CLEAR; diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index 9aac3ec89..c474561ab 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -5,6 +5,7 @@ */ #include #include "mdns_networking.h" +#include "esp_log.h" extern mdns_server_t * _mdns_server; @@ -13,6 +14,7 @@ extern mdns_server_t * _mdns_server; * MDNS Server Networking * */ +static const char *TAG = "MDNS_Networking"; static struct udp_pcb * _pcb_main = NULL; @@ -118,6 +120,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t)); if (!packet) { + HOOK_MALLOC_FAILED; //missed packet - no memory pbuf_free(this_pb); continue; diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 568c81b09..934b9427e 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -118,6 +118,9 @@ #define MDNS_SEARCH_LOCK() xSemaphoreTake(_mdns_server->search.lock, portMAX_DELAY) #define MDNS_SEARCH_UNLOCK() xSemaphoreGive(_mdns_server->search.lock) +#ifndef HOOK_MALLOC_FAILED +#define HOOK_MALLOC_FAILED ESP_LOGE(TAG, "Cannot allocate memory (line: %d, free heap: %d bytes)", __LINE__, esp_get_free_heap_size()); +#endif typedef enum { PCB_OFF, PCB_DUP, PCB_INIT, From b30a7fec270bec1126a63b7a16c632aea18d324b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 10 Dec 2018 16:42:10 +0100 Subject: [PATCH 048/289] mdns: fixed static memory leak * Original commit: espressif/esp-idf@6bb68a5a7567a94c3605136d44960ff060c74663 --- components/mdns/mdns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 3617edbb5..742c47aee 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4011,6 +4011,7 @@ static esp_err_t _mdns_service_task_stop() { MDNS_SERVICE_LOCK(); _mdns_stop_timer(); + MDNS_SERVICE_UNLOCK(); if (_mdns_service_task_handle) { mdns_action_t action; mdns_action_t * a = &action; @@ -4023,7 +4024,6 @@ static esp_err_t _mdns_service_task_stop() vTaskDelay(10 / portTICK_PERIOD_MS); } } - MDNS_SERVICE_UNLOCK(); return ESP_OK; } @@ -4115,8 +4115,8 @@ void mdns_free() if (!_mdns_server) { return; } - _mdns_service_task_stop(); mdns_service_remove_all(_mdns_server); + _mdns_service_task_stop(); for (i=0; i Date: Fri, 14 Dec 2018 11:23:19 +0100 Subject: [PATCH 049/289] mdns: fix networking running udp_sendif from lwip thread * Original commit: espressif/esp-idf@f7d4a4be6a9e0b0ac5edb9400d3b123dbbed2ffc --- components/mdns/mdns_networking.c | 44 ++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index c474561ab..981b9d825 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -242,6 +242,9 @@ typedef struct { struct tcpip_api_call_data call; tcpip_adapter_if_t tcpip_if; mdns_ip_protocol_t ip_protocol; + struct pbuf *pbt; + const ip_addr_t *ip; + uint16_t port; esp_err_t err; } mdns_api_call_t; @@ -277,7 +280,7 @@ esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_prot .tcpip_if = tcpip_if, .ip_protocol = ip_protocol }; - tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call_data*)&msg); + tcpip_api_call(_mdns_pcb_init_api, &msg.call); return msg.err; } @@ -287,29 +290,44 @@ esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_pr .tcpip_if = tcpip_if, .ip_protocol = ip_protocol }; - tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call_data*)&msg); + tcpip_api_call(_mdns_pcb_deinit_api, &msg.call); return msg.err; } +static err_t _mdns_udp_pcb_write_api(struct tcpip_api_call_data *api_call_msg) +{ + void * nif = NULL; + mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; + mdns_pcb_t * _pcb = &_mdns_server->interfaces[msg->tcpip_if].pcbs[msg->ip_protocol]; + esp_err_t err = tcpip_adapter_get_netif(msg->tcpip_if, &nif); + if (err) { + msg->err = err; + return err; + } + err = udp_sendto_if (_pcb->pcb, msg->pbt, msg->ip, msg->port, (struct netif *)nif); + pbuf_free(msg->pbt); + msg->err = err; + return err; +} + size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len) { - struct netif * netif = NULL; - void * nif = NULL; - esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif); - netif = (struct netif *)nif; - if (err) { - return 0; - } - struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); if (pbt == NULL) { return 0; } memcpy((uint8_t *)pbt->payload, data, len); - err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif); - pbuf_free(pbt); - if (err) { + mdns_api_call_t msg = { + .tcpip_if = tcpip_if, + .ip_protocol = ip_protocol, + .pbt = pbt, + .ip = ip, + .port = port + }; + tcpip_api_call(_mdns_udp_pcb_write_api, &msg.call); + + if (msg.err) { return 0; } return len; From 98e3171db677f7eabcdc97bb76e82bbcecfe8210 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Fri, 25 Jan 2019 17:10:53 +0100 Subject: [PATCH 050/289] Correct Kconfigs according to the coding style * Original commit: espressif/esp-idf@37126d3451eabb44eeeb48b8e2ee554dc233e2a8 --- components/mdns/Kconfig | 20 +++---- .../protocols/mdns/main/Kconfig.projbuild | 58 +++++++++---------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig index 321b0f652..5c97d65f4 100644 --- a/components/mdns/Kconfig +++ b/components/mdns/Kconfig @@ -1,13 +1,13 @@ menu "mDNS" -config MDNS_MAX_SERVICES - int "Max number of services" - range 1 64 - default 10 - 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 + 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. + endmenu diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index 9cbca2f6b..377873fcb 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -1,38 +1,38 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. + config WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. + config WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. + Can be left blank if the network has no security set. -config MDNS_HOSTNAME - string "mDNS Hostname" - default "esp32-mdns" - help - mDNS Hostname for example to use + config MDNS_HOSTNAME + string "mDNS Hostname" + default "esp32-mdns" + help + mDNS Hostname for example to use -config MDNS_INSTANCE - string "mDNS Instance Name" - default "ESP32 with mDNS" - help - mDNS Instance Name for example to use + config MDNS_INSTANCE + string "mDNS Instance Name" + default "ESP32 with mDNS" + help + mDNS Instance Name for example to use -config RESOLVE_TEST_SERVICES - bool "Resolve test services" - default y - help - Enable resolving test services on startup. - These services are advertized and evaluated in automated tests. - When executed locally, these will not be resolved and warnings appear in the log. - Please set to false to disable initial querying to avoid warnings. + config RESOLVE_TEST_SERVICES + bool "Resolve test services" + default y + help + Enable resolving test services on startup. + These services are advertized and evaluated in automated tests. + When executed locally, these will not be resolved and warnings appear in the log. + Please set to false to disable initial querying to avoid warnings. endmenu From 2ac83d0f27c5d11f69f93fda570b1470b25395ec Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 25 Jan 2019 17:19:13 +0100 Subject: [PATCH 051/289] mdns: fixed crash on free undefined ptr after skipped strdup Shortcircuit evaluation may cause skip of _mdns_strdup_check of any further question field, which after clear_rx_packet freed undefined memory. Fixes https://ezredmine.espressif.cn:8765/issues/28465 * Original commit: espressif/esp-idf@e0a8044a16907e642001b883469618a999dbe6db --- components/mdns/mdns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 742c47aee..c77c9443f 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2590,7 +2590,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) parsed_packet->discovery = true; mdns_srv_item_t * a = _mdns_server->services; while (a) { - mdns_parsed_question_t * question = (mdns_parsed_question_t *)malloc(sizeof(mdns_parsed_question_t)); + mdns_parsed_question_t * question = (mdns_parsed_question_t *)calloc(1, sizeof(mdns_parsed_question_t)); if (!question) { HOOK_MALLOC_FAILED; goto clear_rx_packet; @@ -2618,7 +2618,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) parsed_packet->probe = true; } - mdns_parsed_question_t * question = (mdns_parsed_question_t *)malloc(sizeof(mdns_parsed_question_t)); + mdns_parsed_question_t * question = (mdns_parsed_question_t *)calloc(1, sizeof(mdns_parsed_question_t)); if (!question) { HOOK_MALLOC_FAILED; goto clear_rx_packet; From 8d08e5ed9570ce776634e0a75bdbe72bca8238de Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 25 Jan 2019 20:24:30 +0100 Subject: [PATCH 052/289] mdns tests: execute test services only when running example in ci Test services may cause confussion (and did cause some GitHub/forum issues). This update runs test services only when example executed in ci. Also host name is a simple config entry if executed outside of ci. * Original commit: espressif/esp-idf@74cc7a065f48598e896063f7156f5e05481e859b --- examples/protocols/mdns/README.md | 9 ++---- .../protocols/mdns/main/Kconfig.projbuild | 9 +++++- .../protocols/mdns/main/mdns_example_main.c | 31 +++++++++++++------ examples/protocols/mdns/mdns_example_test.py | 22 +++++++------ examples/protocols/mdns/sdkconfig.ci | 2 ++ 5 files changed, 47 insertions(+), 26 deletions(-) create mode 100644 examples/protocols/mdns/sdkconfig.ci diff --git a/examples/protocols/mdns/README.md b/examples/protocols/mdns/README.md index b4745a111..d787099af 100644 --- a/examples/protocols/mdns/README.md +++ b/examples/protocols/mdns/README.md @@ -29,9 +29,10 @@ Build the project and flash it to the board, then run monitor tool to view seria make -j4 flash monitor ``` - Wait for WiFi to connect to your access point -- You can now ping the device at `[board-hostname].local`, where `[board-hostname]` is a string created from preconfigured hostname (`esp32-mdns` by default) and last 3 bytes from device MAC address. Please check the serial output log for the specific board-hostname (`esp32-mdns_80FFFF` in the log below) +- You can now ping the device at `[board-hostname].local`, where `[board-hostname]` is preconfigured hostname, `esp32-mdns` by default. - You can also browse for `_http._tcp` on the same network to find the advertised service - Pressing the BOOT button will start querying the local network for the predefined in `check_button` hosts and services +- Note that for purpose of CI tests, configuration options of `RESOLVE_TEST_SERVICES` and `MDNS_ADD_MAC_TO_HOSTNAME` are available, but disabled by default. If enabled, then the hostname suffix of last 3 bytes from device MAC address is added, e.g. `esp32-mdns-80FFFF`, and a query for test service is issued. (To exit the serial monitor, type ``Ctrl-]``.) @@ -42,7 +43,7 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ``` I (0) cpu_start: Starting scheduler on APP CPU. I (276) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE -I (276) mdns-test: mdns hostname set to: [esp32-mdns_80FFFF] +I (276) mdns-test: mdns hostname set to: [esp32-mdns] I (286) wifi: wifi driver task: 3ffc2fa4, prio:23, stack:3584, core=0 I (286) wifi: wifi firmware version: a3be639 I (286) wifi: config NVS flash: enabled @@ -67,10 +68,6 @@ I (2786) wifi: connected with myssid, channel 11 I (2786) wifi: pm start, type: 1 I (4786) event: sta ip: 192.168.0.139, mask: 255.255.255.0, gw: 192.168.0.2 -I (4786) mdns-test: Query A: tinytester.local -W (6876) mdns-test: ESP_ERR_NOT_FOUND: Host was not found! -I (6876) mdns-test: Query PTR: _tiny._tcp.local -W (9976) mdns-test: No results found! I (21126) mdns-test: Query A: esp32.local W (23176) mdns-test: ESP_ERR_NOT_FOUND: Host was not found! I (23176) mdns-test: Query PTR: _arduino._tcp.local diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index 377873fcb..731696060 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -28,11 +28,18 @@ menu "Example Configuration" config RESOLVE_TEST_SERVICES bool "Resolve test services" - default y + default n help Enable resolving test services on startup. These services are advertized and evaluated in automated tests. When executed locally, these will not be resolved and warnings appear in the log. Please set to false to disable initial querying to avoid warnings. + config MDNS_ADD_MAC_TO_HOSTNAME + bool "Add mac suffix to hostname" + default n + help + If enabled, a portion of MAC address is added to the hostname, this is used + for evaluation of tests in CI + endmenu diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index ad9b6f275..ed32f5ac3 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -34,7 +34,6 @@ /* FreeRTOS event group to signal when we are connected & ready to make a request */ static EventGroupHandle_t wifi_event_group; -static const char c_config_hostname[] = CONFIG_MDNS_HOSTNAME; /* The event group allows multiple bits for each event, but we only care about one event - are we connected @@ -44,6 +43,7 @@ const int IP6_CONNECTED_BIT = BIT1; static const char *TAG = "mdns-test"; static bool auto_reconnect = true; +static char* generate_hostname(); static esp_err_t event_handler(void *ctx, system_event_t *event) { @@ -98,15 +98,7 @@ static void initialise_wifi(void) static void initialise_mdns(void) { - _Static_assert(sizeof(c_config_hostname) < CONFIG_MAIN_TASK_STACK_SIZE/2, "Configured mDNS name consumes more than half of the stack. Please select a shorter host name or extend the main stack size please."); - const size_t config_hostname_len = sizeof(c_config_hostname) - 1; // without term char - char hostname[config_hostname_len + 1 + 3*2 + 1]; // adding underscore + 3 digits + term char - uint8_t mac[6]; - - // adding 3 LSBs from mac addr to setup a board specific name - esp_read_mac(mac, ESP_MAC_WIFI_STA); - snprintf(hostname, sizeof(hostname), "%s_%02x%02X%02X", c_config_hostname, mac[3], mac[4], mac[5]); - + char* hostname = generate_hostname(); //initialize mDNS ESP_ERROR_CHECK( mdns_init() ); //set mDNS hostname (required if you want to advertise services) @@ -128,6 +120,7 @@ static void initialise_mdns(void) ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") ); //change TXT item value ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "u", "admin") ); + free(hostname); } static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; @@ -259,3 +252,21 @@ void app_main() initialise_button(); xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL); } + +/** Generate host name based on sdkconfig, optionally adding a portion of MAC address to it. + * @return host name string allocated from the heap + */ +static char* generate_hostname() +{ +#ifndef CONFIG_MDNS_ADD_MAC_TO_HOSTNAME + return strdup(CONFIG_MDNS_HOSTNAME); +#else + uint8_t mac[6]; + char *hostname; + esp_read_mac(mac, ESP_MAC_WIFI_STA); + if (-1 == asprintf(&hostname, "%s-%02X%02X%02X", CONFIG_MDNS_HOSTNAME, mac[3], mac[4], mac[5])) { + abort(); + } + return hostname; +#endif +} diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index 111935291..cb527989a 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -29,7 +29,6 @@ g_done = False def mdns_server(esp_host): - global g_run_server global g_done UDP_IP = "0.0.0.0" UDP_PORT = 5353 @@ -41,7 +40,6 @@ def mdns_server(esp_host): mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') - # sock.sendto(dns.pack(),(MCAST_GRP,UDP_PORT)) sock.settimeout(30) resp_dns = dpkt.dns.DNS(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') resp_dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA @@ -71,14 +69,16 @@ def mdns_server(esp_host): sock.sendto(dns.pack(),(MCAST_GRP,UDP_PORT)) print("Sending esp32-mdns query") time.sleep(0.5) + sock.sendto(resp_dns.pack(),(MCAST_GRP,UDP_PORT)) except socket.timeout: break + except dpkt.UnpackError: + continue @IDF.idf_example_test(env_tag="Example_WIFI") def test_examples_protocol_mdns(env, extra_data): global g_run_server - global g_done """ steps: | 1. join AP + init mdns example @@ -97,24 +97,28 @@ def test_examples_protocol_mdns(env, extra_data): # 2. get the dut host name (and IP address) specific_host = dut1.expect(re.compile(r"mdns hostname set to: \[([^\]]+)\]"), timeout=30) specific_host = str(specific_host[0]) + thread1 = Thread(target=mdns_server, args=(specific_host,)) + thread1.start() try: dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) except DUT.ExpectTimeout: + g_run_server = False + thread1.join() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') # 3. check the mdns name is accessible - thread1 = Thread(target=mdns_server, args=(specific_host,)) - thread1.start() start = time.time() while (time.time() - start) <= 60: if g_done: - print("Test passed") break - g_run_server = False - thread1.join() + time.sleep(0.5) if g_done is False: raise ValueError('Test has failed: did not receive mdns answer within timeout') # 4. check DUT output if mdns advertized host is resolved - dut1.expect(re.compile(r"mdns-test: Query A: tinytester.local resolved to: 127.0.0.1"), timeout=30) + try: + dut1.expect(re.compile(r"mdns-test: Query A: tinytester.local resolved to: 127.0.0.1"), timeout=30) + finally: + g_run_server = False + thread1.join() if __name__ == '__main__': diff --git a/examples/protocols/mdns/sdkconfig.ci b/examples/protocols/mdns/sdkconfig.ci new file mode 100644 index 000000000..8d9206d0e --- /dev/null +++ b/examples/protocols/mdns/sdkconfig.ci @@ -0,0 +1,2 @@ +CONFIG_RESOLVE_TEST_SERVICES=y +CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y From 358d26c8a1415908aeef641263a75b6f95b61906 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 25 Jan 2019 16:17:07 +0100 Subject: [PATCH 053/289] mdns: fix crash after init if no memory for task mdns init first starts timer task, then starts service task. if service task failed to be created, timer task needs to be stopped too. fixed https://ezredmine.espressif.cn:8765/issues/28466 * Original commit: espressif/esp-idf@a47768dc4e4750fd7e1c29b15d6e2dd3c76e6591 --- components/mdns/mdns.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index c77c9443f..1626ffaeb 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3993,7 +3993,10 @@ static esp_err_t _mdns_service_task_start() if (!_mdns_service_task_handle) { xTaskCreatePinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, 1, (TaskHandle_t * const)(&_mdns_service_task_handle), 0); if (!_mdns_service_task_handle) { + _mdns_stop_timer(); MDNS_SERVICE_UNLOCK(); + vSemaphoreDelete(_mdns_service_semaphore); + _mdns_service_semaphore = NULL; return ESP_FAIL; } } @@ -4012,6 +4015,8 @@ static esp_err_t _mdns_service_task_stop() MDNS_SERVICE_LOCK(); _mdns_stop_timer(); MDNS_SERVICE_UNLOCK(); + vSemaphoreDelete(_mdns_service_semaphore); + _mdns_service_semaphore = NULL; if (_mdns_service_task_handle) { mdns_action_t action; mdns_action_t * a = &action; From 6582b41cd131012a0a5554f6c76ef8331a1b31c9 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 14 Feb 2019 16:39:11 +0100 Subject: [PATCH 054/289] mdns: fix memory leak when query for service receives multiple ptr entries for one instance fixes redmine issue 27300 * Original commit: espressif/esp-idf@9a4da97fb4b3c241998cb969a08c3a917ffb4cd1 --- components/mdns/mdns.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 1626ffaeb..1bce6db43 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2741,8 +2741,10 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) if (search_result) { if (search_result->type == MDNS_TYPE_PTR) { - result->port = port; - result->hostname = strdup(name->host); + if (!result->hostname) { // assign host/port for this entry only if not previously set + result->port = port; + result->hostname = strdup(name->host); + } } else { _mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol); } From c546ab8dea20420c0759f70e8cc9496835ff0b1f Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 15 Feb 2019 13:23:21 +0100 Subject: [PATCH 055/289] mdns: fix possible crash when mdns_free called while action queue not empty * Original commit: espressif/esp-idf@206b47c03aca0acdf40d1d9c250e18aeddfe1bd7 --- components/mdns/mdns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 1bce6db43..cf16ae656 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4017,8 +4017,6 @@ static esp_err_t _mdns_service_task_stop() MDNS_SERVICE_LOCK(); _mdns_stop_timer(); MDNS_SERVICE_UNLOCK(); - vSemaphoreDelete(_mdns_service_semaphore); - _mdns_service_semaphore = NULL; if (_mdns_service_task_handle) { mdns_action_t action; mdns_action_t * a = &action; @@ -4031,6 +4029,8 @@ static esp_err_t _mdns_service_task_stop() vTaskDelay(10 / portTICK_PERIOD_MS); } } + vSemaphoreDelete(_mdns_service_semaphore); + _mdns_service_semaphore = NULL; return ESP_OK; } From 90e4babc6170e5825375fe4cfc01d492aa3fa1de Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 15 Feb 2019 13:46:51 +0100 Subject: [PATCH 056/289] mdns: fix malfuctional query_txt when running a query for a single txt, result entries were not created and attached to result structure. this issue was introduced when fixing memory leak in txt structure, which worked correctly for PTR queries, but caused trouble for TXT query. * Original commit: espressif/esp-idf@1a027734af06abf08fcb1c34ee65bdf50d12be4d --- components/mdns/mdns.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index cf16ae656..84d578b3c 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2831,7 +2831,10 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } } } else { - _mdns_search_result_add_txt(search_result, txt, txt_count, packet->tcpip_if, packet->ip_protocol); + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_count); + if (txt_count) { + _mdns_search_result_add_txt(search_result, txt, txt_count, packet->tcpip_if, packet->ip_protocol); + } } } else if (ours) { if (parsed_packet->questions && !parsed_packet->probe) { From 11e4aebefd00528ca76bca5e9c877e0292af1e9d Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 15 Feb 2019 15:54:18 +0100 Subject: [PATCH 057/289] mdns example: fix print result for IPv6 addresses * Original commit: espressif/esp-idf@fbef5297fcc587310142c06df8b561171847ede5 --- examples/protocols/mdns/main/mdns_example_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index ed32f5ac3..27d7d2b43 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -147,7 +147,7 @@ static void mdns_print_results(mdns_result_t * results){ } a = r->addr; while(a){ - if(a->addr.type == MDNS_IP_PROTOCOL_V6){ + if(a->addr.type == IPADDR_TYPE_V6){ printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); } else { printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); From b6efc688b56d43621e679f62cb2b69ed5f3e51b3 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 15 Feb 2019 15:59:11 +0100 Subject: [PATCH 058/289] mdns: fix memory leak in pbuf if tcpipadapter failed to get netif * Original commit: espressif/esp-idf@8462751f95a3ff18bdc1b01d02fabd1829fd9135 --- components/mdns/mdns_networking.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index 981b9d825..bb3400f0a 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -301,6 +301,7 @@ static err_t _mdns_udp_pcb_write_api(struct tcpip_api_call_data *api_call_msg) mdns_pcb_t * _pcb = &_mdns_server->interfaces[msg->tcpip_if].pcbs[msg->ip_protocol]; esp_err_t err = tcpip_adapter_get_netif(msg->tcpip_if, &nif); if (err) { + pbuf_free(msg->pbt); msg->err = err; return err; } From 34f6d8dd336e598d4b26c03f4e70cceb6e81ff05 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 4 Mar 2019 16:59:09 +0800 Subject: [PATCH 059/289] mdns: use binary semaphore instead of mutex when searching mdns_search_once_t::lock is used to synchronize tasks (taken by one task and given by the other) so it should not be a mutex. Convert to semaphore, and rename to indicate its purpose. * Original commit: espressif/esp-idf@eef0b5090aee87efef1a6a37772b3b88c9ce8df8 --- components/mdns/mdns.c | 14 ++++++-------- components/mdns/private_include/mdns_private.h | 5 +---- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 84d578b3c..40b2cc038 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3074,7 +3074,7 @@ static void _mdns_search_free(mdns_search_once_t * search) free(search->instance); free(search->service); free(search->proto); - vSemaphoreDelete(search->lock); + vSemaphoreDelete(search->done_semaphore); free(search); } @@ -3090,8 +3090,8 @@ static mdns_search_once_t * _mdns_search_init(const char * name, const char * se } memset(search, 0, sizeof(mdns_search_once_t)); - search->lock = xSemaphoreCreateMutex(); - if (!search->lock) { + search->done_semaphore = xSemaphoreCreateBinary(); + if (!search->done_semaphore) { free(search); return NULL; } @@ -3130,8 +3130,6 @@ static mdns_search_once_t * _mdns_search_init(const char * name, const char * se search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS; search->next = NULL; - xSemaphoreTake(search->lock, 0); - return search; } @@ -3142,7 +3140,7 @@ static void _mdns_search_finish(mdns_search_once_t * search) { search->state = SEARCH_OFF; queueDetach(mdns_search_once_t, _mdns_server->search_once, search); - xSemaphoreGive(search->lock); + xSemaphoreGive(search->done_semaphore); } /** @@ -4148,7 +4146,7 @@ void mdns_free() free(h->instance); free(h->service); free(h->proto); - vSemaphoreDelete(h->lock); + vSemaphoreDelete(h->done_semaphore); if (h->result) { mdns_query_results_free(h->result); } @@ -4543,7 +4541,7 @@ esp_err_t mdns_query(const char * name, const char * service, const char * proto _mdns_search_free(search); return ESP_ERR_NO_MEM; } - xSemaphoreTake(search->lock, portMAX_DELAY); + xSemaphoreTake(search->done_semaphore, portMAX_DELAY); *results = search->result; _mdns_search_free(search); diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 934b9427e..9efd23ae7 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -115,9 +115,6 @@ #define PCB_STATE_IS_ANNOUNCING(s) (s->state > PCB_PROBE_3 && s->state < PCB_RUNNING) #define PCB_STATE_IS_RUNNING(s) (s->state == PCB_RUNNING) -#define MDNS_SEARCH_LOCK() xSemaphoreTake(_mdns_server->search.lock, portMAX_DELAY) -#define MDNS_SEARCH_UNLOCK() xSemaphoreGive(_mdns_server->search.lock) - #ifndef HOOK_MALLOC_FAILED #define HOOK_MALLOC_FAILED ESP_LOGE(TAG, "Cannot allocate memory (line: %d, free heap: %d bytes)", __LINE__, esp_get_free_heap_size()); #endif @@ -318,7 +315,7 @@ typedef struct mdns_search_once_s { uint32_t started_at; uint32_t sent_at; uint32_t timeout; - SemaphoreHandle_t lock; + SemaphoreHandle_t done_semaphore; uint16_t type; uint8_t max_results; uint8_t num_results; From 450cbf03cfd53b1c6ddac9e1dae7fbf68b4289f3 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 25 Feb 2019 14:29:39 +0100 Subject: [PATCH 060/289] mdns: fix possible crash when packet scheduled to transmit contained service which might have been already removed packets scheduled to transmit are pushed to action queue and removed from tx_queue_head structure, which is searched for all remaining services and while service is removed, then service questions/asnwers are also removed from this structure. This update fixes possible crash when packet is pushed to action queue, and when service is removed, its answers are removed from tx_queue_head, but not from action queue. this could lead to a crash when the packet is poped from action queue containing questions/answers to already removed (freed) service Closes IDF-504 * Original commit: espressif/esp-idf@67051a286ba60a01d4755c3682129153c2f95953 --- components/mdns/mdns.c | 24 ++++++++++++++++--- .../mdns/private_include/mdns_private.h | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 40b2cc038..18fe1a993 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3819,7 +3819,17 @@ static void _mdns_execute_action(mdns_action_t * action) _mdns_search_finish(action->data.search_add.search); break; case ACTION_TX_HANDLE: - _mdns_tx_handle_packet(action->data.tx_handle.packet); + { + mdns_tx_packet_t * p = _mdns_server->tx_queue_head; + // packet to be handled should be at tx head, but must be consistent with the one pushed to action queue + if (p && p==action->data.tx_handle.packet && p->queued) { + p->queued = false; // clearing, as the packet might be reused (pushed and transmitted again) + _mdns_server->tx_queue_head = p->next; + _mdns_tx_handle_packet(p); + } else { + ESP_LOGD(TAG, "Skipping transmit of an unexpected packet!"); + } + } break; case ACTION_RX_HANDLE: mdns_parse_packet(action->data.rx_handle.packet); @@ -3856,6 +3866,10 @@ static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_o /** * @brief Called from timer task to run mDNS responder + * + * periodically checks first unqueued packet (from tx head). + * if it is scheduled to be transmitted, then pushes the packet to action queue to be handled. + * */ static void _mdns_scheduler_run() { @@ -3863,6 +3877,10 @@ static void _mdns_scheduler_run() mdns_tx_packet_t * p = _mdns_server->tx_queue_head; mdns_action_t * action = NULL; + // find first unqueued packet + while (p && p->queued) { + p = p->next; + } if (!p) { MDNS_SERVICE_UNLOCK(); return; @@ -3870,12 +3888,12 @@ static void _mdns_scheduler_run() if ((int32_t)(p->send_at - (xTaskGetTickCount() * portTICK_PERIOD_MS)) < 0) { action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (action) { - _mdns_server->tx_queue_head = p->next; action->type = ACTION_TX_HANDLE; action->data.tx_handle.packet = p; + p->queued = true; if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { free(action); - _mdns_server->tx_queue_head = p; + p->queued = false; } } else { HOOK_MALLOC_FAILED; diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 9efd23ae7..a7383c03d 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -289,6 +289,7 @@ typedef struct mdns_tx_packet_s { mdns_out_answer_t * answers; mdns_out_answer_t * servers; mdns_out_answer_t * additional; + bool queued; } mdns_tx_packet_t; typedef struct { From 2ec3b558eaf69d3628f8f2a0933cc596d58e971f Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 1 Mar 2019 16:59:38 +0100 Subject: [PATCH 061/289] mdsn: fix race condition in updating packet data from user task when failed to allocate or queue a new service Issue: mdns_service_add API allocates and queues an action to be processed in mdns task context; when allocation or queueing fails, allocated structure needs to be freed. Function _mdns_free_service did not only fee all the structures, but also updates packet data. Resolution: Moved removal of packet data outside of _mdns_free_service function. * Original commit: espressif/esp-idf@021dc5d453e21e2d1707f194668e69cf63ef4e84 --- components/mdns/mdns.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 18fe1a993..de66d9432 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1863,6 +1863,9 @@ static void _mdns_dealloc_scheduled_service_answers(mdns_out_answer_t ** destina */ static void _mdns_remove_scheduled_service_packets(mdns_service_t * service) { + if (!service) { + return; + } mdns_tx_packet_t * p = NULL; mdns_tx_packet_t * q = _mdns_server->tx_queue_head; while (q) { @@ -1951,7 +1954,6 @@ static void _mdns_free_service(mdns_service_t * service) if (!service) { return; } - _mdns_remove_scheduled_service_packets(service); free((char *)service->instance); free((char *)service->service); free((char *)service->proto); @@ -3781,6 +3783,7 @@ static void _mdns_execute_action(mdns_action_t * action) 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 { @@ -3791,6 +3794,7 @@ static void _mdns_execute_action(mdns_action_t * action) 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); } @@ -3804,6 +3808,7 @@ static void _mdns_execute_action(mdns_action_t * action) while (a) { mdns_srv_item_t * s = a; a = a->next; + _mdns_remove_scheduled_service_packets(s->service); _mdns_free_service(s->service); free(s); } From fdd27dc9fa4f6d9683b4c1e20600f94ae410a2d6 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 4 Mar 2019 11:13:52 +0100 Subject: [PATCH 062/289] mdns: fix possible deadlock on mdns deinit calling mdns_free() mnds_free() initiates stop and delete timer tasks, which after locking the mutex could lead to a dead lock in case timer task executed before deleting the task, as it would wait indefinitelly for unlocking the mutex. This condition is fixed by calling _mdns_stop_timer without locking the mutex, because there's no need to protect any data when stopping and deleting the timer task Closes https://github.com/espressif/esp-idf/issues/1696 * Original commit: espressif/esp-idf@48b5501c250ed90da51a55ad4fc18e09f466a517 --- components/mdns/mdns.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index de66d9432..378816ba7 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4038,9 +4038,7 @@ static esp_err_t _mdns_service_task_start() */ static esp_err_t _mdns_service_task_stop() { - MDNS_SERVICE_LOCK(); _mdns_stop_timer(); - MDNS_SERVICE_UNLOCK(); if (_mdns_service_task_handle) { mdns_action_t action; mdns_action_t * a = &action; From 75deebbf039ee27324a4f37241c93dbf77b1f861 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 4 Mar 2019 12:32:10 +0100 Subject: [PATCH 063/289] mdns: enable pcbs before starting service thread to avoid updating pcb's internal variables from concurent tasks possible race condition: user task runs mdns_init, which enables pcbs while mdns-task already created could execute enable/disable of the same pcbs if an appropriate system event received * Original commit: espressif/esp-idf@c87f0cb6cad3c36b077f4aaeb1ca52fe6ed0cdaf --- components/mdns/mdns.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 378816ba7..d302ded24 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4107,12 +4107,6 @@ esp_err_t mdns_init() goto free_lock; } - if (_mdns_service_task_start()) { - //service start failed! - err = ESP_FAIL; - goto free_all; - } - uint8_t i; ip6_addr_t tmp_addr6; tcpip_adapter_ip_info_t if_ip_info; @@ -4126,9 +4120,19 @@ esp_err_t mdns_init() } } + if (_mdns_service_task_start()) { + //service start failed! + err = ESP_FAIL; + goto free_all_and_disable_pcbs; + } + return ESP_OK; -free_all: +free_all_and_disable_pcbs: + for (i=0; iaction_queue); free_lock: vSemaphoreDelete(_mdns_server->lock); From 985e69117e1c6bf8e39912a879a99ce83b09a350 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 11 Mar 2019 11:49:29 +0100 Subject: [PATCH 064/289] mdns: fix possible crash when probing on particular interface with duplicated service instances due to naming conflicts on network Issue: MDNS server initially sends probing packets to resolve naming confilicts with already registered service instances. In case of a conflict, instance name is altered and probing restarts. Original instance however wasnnot removed from the structure and upon service removal only one entry was removed and a dangling service might have been kept in the structure to bring about a crash. Resolution: Keep only one instance of a service in the probing structure. Closes IDF-498 * Original commit: espressif/esp-idf@265e983a452a7eaefc1662cdc0e6ed839a37fe1a --- components/mdns/mdns.c | 55 +++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index d302ded24..0f52ecf8e 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1452,20 +1452,13 @@ static void _mdns_pcb_send_bye(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t i } /** - * @brief Send probe for particular services on particular PCB + * @brief Send probe for additional services on particular PCB */ -static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) +static void _mdns_init_pcb_probe_new_service(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) { mdns_pcb_t * pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; size_t services_final_len = len; - _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); - - if (_str_null_or_empty(_mdns_server->hostname)) { - pcb->state = PCB_RUNNING; - return; - } - if (PCB_STATE_IS_PROBING(pcb)) { services_final_len += pcb->probe_services_len; } @@ -1510,6 +1503,50 @@ static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t pcb->state = PCB_PROBE_1; } +/** + * @brief Send probe for particular services on particular PCB + * + * Tests possible duplication on probing service structure and probes only for new entries. + * - If pcb probing then add only non-probing services and restarts probing + * - If pcb not probing, run probing for all specified services + */ +static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) +{ + mdns_pcb_t * pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; + + _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); + + if (_str_null_or_empty(_mdns_server->hostname)) { + pcb->state = PCB_RUNNING; + return; + } + + if (PCB_STATE_IS_PROBING(pcb)) { + // Looking for already probing services to resolve duplications + mdns_srv_item_t * new_probe_services[len]; + int new_probe_service_len = 0; + bool found; + for (int j=0; j < len; ++j) { + found = false; + for (int i=0; i < pcb->probe_services_len; ++i) { + if (pcb->probe_services[i] == services[j]) { + found = true; + break; + } + } + if (!found) { + new_probe_services[new_probe_service_len++] = services[j]; + } + } + // init probing for newly added services + _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, + new_probe_service_len?new_probe_services:NULL, new_probe_service_len, probe_ip); + } else { + // not probing, so init for all services + _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, services, len, probe_ip); + } +} + /** * @brief Restart the responder on particular PCB */ From d9aec9fc713b6889dd3d7f3f8a5cf6864a579d1b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 19 Feb 2019 14:38:59 +0100 Subject: [PATCH 065/289] fuzzer tests: update of mdns and lwip host compilation for fuzzer testing Closes IDF-540 * Original commit: espressif/esp-idf@bc60bbbeaf89f2bbfc5db4bd4f1e7ace81a2ab37 --- components/mdns/test_afl_fuzz_host/Makefile | 4 +++- components/mdns/test_afl_fuzz_host/esp32_compat.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 61bedc520..6d19d3bf0 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -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 diff --git a/components/mdns/test_afl_fuzz_host/esp32_compat.h b/components/mdns/test_afl_fuzz_host/esp32_compat.h index 7a662607c..e054c18bb 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_compat.h +++ b/components/mdns/test_afl_fuzz_host/esp32_compat.h @@ -57,6 +57,7 @@ #define portMAX_DELAY 0xFFFFFFFF #define portTICK_PERIOD_MS 1 +#define ESP_LOGD(a,b) #define xSemaphoreTake(s,d) #define xTaskDelete(a) @@ -65,6 +66,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) From 6ea0ea93fa1cbf801c616dd3412960bbb5746c4b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 21 Nov 2018 13:46:45 +0800 Subject: [PATCH 066/289] mdns: use esp_event library to handle events * Original commit: espressif/esp-idf@a2d59525e53099ee1ad63c3d60ff853f573ab535 --- components/mdns/mdns.c | 142 ++++++++++++------ .../mdns/private_include/mdns_networking.h | 3 +- .../mdns/private_include/mdns_private.h | 5 +- .../protocols/mdns/main/mdns_example_main.c | 2 +- 4 files changed, 99 insertions(+), 53 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 0f52ecf8e..8c9767942 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3048,56 +3048,69 @@ 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_STARTED) { + _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 == ETH_EVENT) { + switch (event_id) { + case ETHERNET_EVENT_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 ETHERNET_EVENT_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; + } + } 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); - } - } - 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_announce_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V6, NULL, 0, true); + break; + case IP_EVENT_ETH_GOT_IP: _mdns_enable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V4); - } + 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_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 +3722,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); @@ -4098,23 +4112,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 +4169,16 @@ 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; + } + if ((err = esp_event_handler_register(ETH_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 +4205,10 @@ 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); + esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler); vQueueDelete(_mdns_server->action_queue); free_lock: vSemaphoreDelete(_mdns_server->lock); @@ -4215,6 +4254,9 @@ void mdns_free() free(h); } vSemaphoreDelete(_mdns_server->lock); + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler); + esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler); + esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler); free(_mdns_server); _mdns_server = NULL; } diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h index 5b56f8066..1d13e308f 100644 --- a/components/mdns/private_include/mdns_networking.h +++ b/components/mdns/private_include/mdns_networking.h @@ -20,7 +20,8 @@ #include "esp_wifi.h" #include "esp_system.h" #include "esp_timer.h" -#include "esp_event_loop.h" +#include "esp_event.h" +#include "esp_eth.h" /** diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index a7383c03d..a5b0747aa 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -14,6 +14,8 @@ #ifndef MDNS_PRIVATE_H_ #define MDNS_PRIVATE_H_ +#include "esp_event_base.h" + //#define MDNS_ENABLE_DEBUG #ifdef MDNS_ENABLE_DEBUG @@ -346,7 +348,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 { diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 27d7d2b43..20cdbc3b0 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -247,8 +247,8 @@ static void mdns_example_task(void *pvParameters) void app_main() { ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_mdns(); initialise_wifi(); + initialise_mdns(); initialise_button(); xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL); } From 25f8656fbc0eca585163392270e676e510300c17 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 21 Nov 2018 00:40:26 +0800 Subject: [PATCH 067/289] examples: add component for protocol examples network functionality * Original commit: espressif/esp-idf@22bef90bd3eb771a4b7c129d3fee62cffbdb5ca6 --- .../protocol_examples_common/CMakeLists.txt | 5 + .../Kconfig.projbuild | 153 +++++++++ .../protocol_examples_common/component.mk | 0 .../protocol_examples_common/connect.c | 291 ++++++++++++++++++ .../include/protocol_examples_common.h | 59 ++++ .../protocol_examples_common/stdin_out.c | 30 ++ 6 files changed, 538 insertions(+) create mode 100644 examples/common_components/protocol_examples_common/CMakeLists.txt create mode 100644 examples/common_components/protocol_examples_common/Kconfig.projbuild create mode 100644 examples/common_components/protocol_examples_common/component.mk create mode 100644 examples/common_components/protocol_examples_common/connect.c create mode 100644 examples/common_components/protocol_examples_common/include/protocol_examples_common.h create mode 100644 examples/common_components/protocol_examples_common/stdin_out.c diff --git a/examples/common_components/protocol_examples_common/CMakeLists.txt b/examples/common_components/protocol_examples_common/CMakeLists.txt new file mode 100644 index 000000000..784909da0 --- /dev/null +++ b/examples/common_components/protocol_examples_common/CMakeLists.txt @@ -0,0 +1,5 @@ +set(COMPONENT_SRCS "connect.c" + "stdin_out.c") +set(COMPONENT_ADD_INCLUDEDIRS "include") + +register_component() diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild new file mode 100644 index 000000000..fe095582b --- /dev/null +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -0,0 +1,153 @@ +menu "Example Connection Configuration" + + choice EXAMPLE_CONNECT_INTERFACE + prompt "Connect using" + default EXAMPLE_CONNECT_WIFI + help + Protocol examples can use Wi-Fi or Ethernet to connect to the network. + Choose which interface to use. + + config EXAMPLE_CONNECT_WIFI + bool "Wi-Fi" + + config EXAMPLE_CONNECT_ETHERNET + bool "Ethernet" + + endchoice + + config EXAMPLE_WIFI_SSID + depends on EXAMPLE_CONNECT_WIFI + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + + config EXAMPLE_WIFI_PASSWORD + depends on EXAMPLE_CONNECT_WIFI + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + Can be left blank if the network has no security set. + + + choice PHY_MODEL + prompt "Ethernet PHY" + depends on EXAMPLE_CONNECT_ETHERNET + default CONFIG_PHY_TLK110 + help + Select the PHY driver to use for the example. + + config PHY_IP101 + bool "IP101" + help + IP101 is a single port 10/100 MII/RMII/TP/Fiber Fast Ethernet Transceiver. + Goto http://www.icplus.com.tw/pp-IP101G.html for more information about it. + + config PHY_TLK110 + bool "TI TLK110 PHY" + help + Select this to use the TI TLK110 PHY + + config PHY_LAN8720 + bool "Microchip LAN8720 PHY" + help + Select this to use the Microchip LAN8720 PHY + + endchoice + + + config PHY_ADDRESS + int "PHY Address (0-31)" + depends on EXAMPLE_CONNECT_ETHERNET + default 31 + range 0 31 + help + Select the PHY Address (0-31) for the hardware configuration and PHY model. + TLK110 default 31 + LAN8720 default 1 or 0 + + + choice PHY_CLOCK_MODE + prompt "EMAC clock mode" + depends on EXAMPLE_CONNECT_ETHERNET + default PHY_CLOCK_GPIO0_IN + help + Select external (input on GPIO0) or internal (output on GPIO16 or GPIO17) clock + + + config PHY_CLOCK_GPIO0_IN + bool "GPIO0 input" + depends on EXAMPLE_CONNECT_ETHERNET + help + Input of 50MHz PHY clock on GPIO0. + + config PHY_CLOCK_GPIO0_OUT + bool "GPIO0 Output" + help + Output the internal 50MHz RMII clock on GPIO0. + + config PHY_CLOCK_GPIO16_OUT + bool "GPIO16 output" + depends on EXAMPLE_CONNECT_ETHERNET + help + Output the internal 50MHz APLL clock on GPIO16. + + config PHY_CLOCK_GPIO17_OUT + bool "GPIO17 output (inverted)" + depends on EXAMPLE_CONNECT_ETHERNET + help + Output the internal 50MHz APLL clock on GPIO17 (inverted signal). + + endchoice + + config PHY_CLOCK_MODE + int + depends on EXAMPLE_CONNECT_ETHERNET + default 0 if PHY_CLOCK_GPIO0_IN + default 1 if PHY_CLOCK_GPIO0_OUT + default 2 if PHY_CLOCK_GPIO16_OUT + default 3 if PHY_CLOCK_GPIO17_OUT + + + config PHY_USE_POWER_PIN + bool "Use PHY Power (enable/disable) pin" + depends on EXAMPLE_CONNECT_ETHERNET + default y + help + Use a GPIO "power pin" to power the PHY on/off during operation. + Consult the example README for more details + + config PHY_POWER_PIN + int "PHY Power GPIO" + depends on EXAMPLE_CONNECT_ETHERNET + default 17 + range 0 33 + depends on PHY_USE_POWER_PIN + help + GPIO number to use for powering on/off the PHY. + + config PHY_SMI_MDC_PIN + int "SMI MDC Pin" + depends on EXAMPLE_CONNECT_ETHERNET + default 23 + range 0 33 + help + GPIO number to use for SMI clock output MDC to PHY. + + config PHY_SMI_MDIO_PIN + int "SMI MDIO Pin" + depends on EXAMPLE_CONNECT_ETHERNET + default 18 + range 0 33 + help + GPIO number to use for SMI data pin MDIO to/from PHY. + + config EXAMPLE_CONNECT_IPV6 + bool "Obtain IPv6 link-local address" + default y + help + By default, examples will wait until IPv4 and IPv6 addresses are obtained. + Disable this option if the network does not support IPv6. + +endmenu diff --git a/examples/common_components/protocol_examples_common/component.mk b/examples/common_components/protocol_examples_common/component.mk new file mode 100644 index 000000000..e69de29bb diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c new file mode 100644 index 000000000..37d9df6db --- /dev/null +++ b/examples/common_components/protocol_examples_common/connect.c @@ -0,0 +1,291 @@ +/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection. + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + */ + +#include +#include "protocol_examples_common.h" +#include "sdkconfig.h" +#include "esp_event.h" +#include "esp_wifi.h" +#include "esp_eth.h" +#include "esp_log.h" +#include "tcpip_adapter.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "lwip/err.h" +#include "lwip/sys.h" + +#define GOT_IPV4_BIT BIT(0) +#define GOT_IPV6_BIT BIT(1) + +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 +#define CONNECTED_BITS (GOT_IPV4_BIT | GOT_IPV6_BIT) +#else +#define CONNECTED_BITS (GOT_IPV4_BIT) +#endif + +static EventGroupHandle_t s_connect_event_group; +static ip4_addr_t s_ip_addr; +static const char* s_connection_name; + +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 +static ip6_addr_t s_ipv6_addr; +#endif + + +static const char *TAG = "example_connect"; + +/* set up connection, Wi-Fi or Ethernet */ +static void start(); + +/* tear down connection, release resources */ +static void stop(); + +static void on_got_ip(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; + memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr)); + xEventGroupSetBits(s_connect_event_group, GOT_IPV4_BIT); +} + +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + +static void on_got_ipv6(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + ip_event_got_ip6_t* event = (ip_event_got_ip6_t*) event_data; + memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); + xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); +} + +#endif // CONFIG_EXAMPLE_CONNECT_IPV6 + +esp_err_t example_connect() +{ + if (s_connect_event_group != NULL) { + return ESP_ERR_INVALID_STATE; + } + s_connect_event_group = xEventGroupCreate(); + start(); + xEventGroupWaitBits(s_connect_event_group, CONNECTED_BITS, true, true, portMAX_DELAY); + ESP_LOGI(TAG, "Connected to %s", s_connection_name); + ESP_LOGI(TAG, "IPv4 address: " IPSTR, IP2STR(&s_ip_addr)); +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + ESP_LOGI(TAG, "IPv6 address: " IPV6STR, IPV62STR(s_ipv6_addr)); +#endif + return ESP_OK; +} + +esp_err_t example_disconnect() +{ + if (s_connect_event_group == NULL) { + return ESP_ERR_INVALID_STATE; + } + vEventGroupDelete(s_connect_event_group); + s_connect_event_group = NULL; + stop(); + ESP_LOGI(TAG, "Disconnected from %s", s_connection_name); + s_connection_name = NULL; + return ESP_OK; +} + +#ifdef CONFIG_EXAMPLE_CONNECT_WIFI + +static void on_wifi_disconnect(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect..."); + ESP_ERROR_CHECK( esp_wifi_connect() ); +} + +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + +static void on_wifi_connect(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); +} + +#endif // CONFIG_EXAMPLE_CONNECT_IPV6 + +static void start() +{ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL)); +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL)); +#endif + + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + wifi_config_t wifi_config = { + .sta = { + .ssid = CONFIG_EXAMPLE_WIFI_SSID, + .password = CONFIG_EXAMPLE_WIFI_PASSWORD, + }, + }; + ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + ESP_ERROR_CHECK(esp_wifi_connect()); + s_connection_name = CONFIG_EXAMPLE_WIFI_SSID; +} + +static void stop() +{ + ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect)); + ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip)); +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6)); + ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect)); +#endif + ESP_ERROR_CHECK(esp_wifi_stop()); + ESP_ERROR_CHECK(esp_wifi_deinit()); +} +#endif // CONFIG_EXAMPLE_CONNECT_WIFI + + +#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET + +#include "driver/gpio.h" + +#ifdef CONFIG_PHY_LAN8720 +#include "eth_phy/phy_lan8720.h" +#define DEFAULT_ETHERNET_PHY_CONFIG phy_lan8720_default_ethernet_config +#endif +#ifdef CONFIG_PHY_TLK110 +#include "eth_phy/phy_tlk110.h" +#define DEFAULT_ETHERNET_PHY_CONFIG phy_tlk110_default_ethernet_config +#elif CONFIG_PHY_IP101 +#include "eth_phy/phy_ip101.h" +#define DEFAULT_ETHERNET_PHY_CONFIG phy_ip101_default_ethernet_config +#endif + +#define PIN_PHY_POWER CONFIG_PHY_POWER_PIN +#define PIN_SMI_MDC CONFIG_PHY_SMI_MDC_PIN +#define PIN_SMI_MDIO CONFIG_PHY_SMI_MDIO_PIN + +#ifdef CONFIG_PHY_USE_POWER_PIN +/** + * @brief re-define power enable func for phy + * + * @param enable true to enable, false to disable + * + * @note This function replaces the default PHY power on/off function. + * If this GPIO is not connected on your device (and PHY is always powered), + * you can use the default PHY-specific power on/off function. + */ +static void phy_device_power_enable_via_gpio(bool enable) +{ + assert(DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable); + + if (!enable) { + DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable(false); + } + + gpio_pad_select_gpio(PIN_PHY_POWER); + gpio_set_direction(PIN_PHY_POWER, GPIO_MODE_OUTPUT); + if (enable == true) { + gpio_set_level(PIN_PHY_POWER, 1); + ESP_LOGI(TAG, "Power On Ethernet PHY"); + } else { + gpio_set_level(PIN_PHY_POWER, 0); + ESP_LOGI(TAG, "Power Off Ethernet PHY"); + } + + vTaskDelay(1); // Allow the power up/down to take effect, min 300us + + if (enable) { + /* call the default PHY-specific power on function */ + DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable(true); + } +} +#endif + +/** + * @brief gpio specific init + * + * @note RMII data pins are fixed in esp32: + * TXD0 <=> GPIO19 + * TXD1 <=> GPIO22 + * TX_EN <=> GPIO21 + * RXD0 <=> GPIO25 + * RXD1 <=> GPIO26 + * CLK <=> GPIO0 + * + */ +static void eth_gpio_config_rmii(void) +{ + phy_rmii_configure_data_interface_pins(); + phy_rmii_smi_configure_pins(PIN_SMI_MDC, PIN_SMI_MDIO); +} + +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + +/** Event handler for Ethernet events */ +static void on_eth_event(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + switch (event_id) { + case ETHERNET_EVENT_CONNECTED: + ESP_LOGI(TAG, "Ethernet Link Up"); + tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_ETH); + break; + default: + break; + } +} + +#endif // CONFIG_EXAMPLE_CONNECT_IPV6 + +static void start() +{ + eth_config_t config = DEFAULT_ETHERNET_PHY_CONFIG; + config.phy_addr = CONFIG_PHY_ADDRESS; + config.gpio_config = eth_gpio_config_rmii; + config.tcpip_input = tcpip_adapter_eth_input; + config.clock_mode = CONFIG_PHY_CLOCK_MODE; + +#ifdef CONFIG_PHY_USE_POWER_PIN + /* Replace the default 'power enable' function with an example-specific one + that toggles a power GPIO. */ + config.phy_power_enable = phy_device_power_enable_via_gpio; +#endif + + ESP_ERROR_CHECK(esp_eth_init(&config)); + + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL)); +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL)); +#endif + + ESP_ERROR_CHECK(esp_eth_enable()); + + s_connection_name = "Ethernet"; +} + +static void stop() +{ + ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip)); +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6)); + ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event)); +#endif + + ESP_ERROR_CHECK(esp_eth_disable()); + ESP_ERROR_CHECK(esp_eth_deinit()); +} + +#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET diff --git a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h new file mode 100644 index 000000000..e250db14d --- /dev/null +++ b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h @@ -0,0 +1,59 @@ +/* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection. + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" +#include "tcpip_adapter.h" + +#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET +#define EXAMPLE_INTERFACE TCPIP_ADAPTER_IF_ETH +#endif + +#ifdef CONFIG_EXAMPLE_CONNECT_WIFI +#define EXAMPLE_INTERFACE TCPIP_ADAPTER_IF_STA +#endif + +/** + * @brief Configure Wi-Fi or Ethernet, connect, wait for IP + * + * This all-in-one helper function is used in protocols examples to + * reduce the amount of boilerplate in the example. + * + * It is not intended to be used in real world applications. + * See examples under examples/wifi/getting_started/ and examples/ethernet/ + * for more complete Wi-Fi or Ethernet initialization code. + * + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + * + * @return ESP_OK on successful connection + */ +esp_err_t example_connect(); + +/** + * Counterpart to example_connect, de-initializes Wi-Fi or Ethernet + */ +esp_err_t example_disconnect(); + +/** + * @brief Configure stdin and stdout to use blocking I/O + * + * This helper function is used in ASIO examples. It wraps installing the + * UART driver and configuring VFS layer to use UART driver for console I/O. + */ +esp_err_t example_configure_stdin_stdout(); + +#ifdef __cplusplus +} +#endif diff --git a/examples/common_components/protocol_examples_common/stdin_out.c b/examples/common_components/protocol_examples_common/stdin_out.c new file mode 100644 index 000000000..a4bc2cca4 --- /dev/null +++ b/examples/common_components/protocol_examples_common/stdin_out.c @@ -0,0 +1,30 @@ +/* Common functions for protocol examples, to configure stdin and stdout. + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + */ + +#include "protocol_examples_common.h" +#include "esp_err.h" +#include "esp_vfs_dev.h" +#include "driver/uart.h" +#include "sdkconfig.h" + +esp_err_t example_configure_stdin_stdout() +{ + // Initialize VFS & UART so we can use std::cout/cin + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + /* Install UART driver for interrupt-driven reads and writes */ + ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, + 256, 0, 0, NULL, 0) ); + /* Tell VFS to use UART driver */ + esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); + esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + /* Move the caret to the beginning of the next line on '\n' */ + esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); + return ESP_OK; +} From 778eaa6cedec4ef06b479225d70d814ef8824e52 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 21 Nov 2018 13:52:08 +0800 Subject: [PATCH 068/289] examples/protocols/mdns: use common network component * Original commit: espressif/esp-idf@9628c60a1d5a162674d90808298d8de23ec5f708 --- examples/protocols/mdns/CMakeLists.txt | 4 + examples/protocols/mdns/Makefile | 2 + examples/protocols/mdns/README.md | 9 +- .../protocols/mdns/main/Kconfig.projbuild | 14 --- .../protocols/mdns/main/mdns_example_main.c | 102 ++++-------------- 5 files changed, 32 insertions(+), 99 deletions(-) diff --git a/examples/protocols/mdns/CMakeLists.txt b/examples/protocols/mdns/CMakeLists.txt index 88b7c1e3f..ddd7263c5 100644 --- a/examples/protocols/mdns/CMakeLists.txt +++ b/examples/protocols/mdns/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mdns-test) diff --git a/examples/protocols/mdns/Makefile b/examples/protocols/mdns/Makefile index 0353c51c0..91a417c7c 100644 --- a/examples/protocols/mdns/Makefile +++ b/examples/protocols/mdns/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := mdns-test +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/mdns/README.md b/examples/protocols/mdns/README.md index d787099af..182434e58 100644 --- a/examples/protocols/mdns/README.md +++ b/examples/protocols/mdns/README.md @@ -12,12 +12,10 @@ Shows how to use mDNS to advertise lookup services and hosts ### Configure the project -``` -make menuconfig -``` +* Run `make menuconfig` (or `idf.py menuconfig` if using CMake build system) -* Set `Default serial port` under `Serial flasher config`. -* Set `WiFi SSID` and `WiFi Password` for the board to connect to AP. +* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../README.md) for more details. +* When using Make build system, set `Default serial port` under `Serial flasher config`. * Set `mDNS Hostname` as host name prefix for the device and its instance name in `mDNS Instance Name` * Disable `Resolve test services` to prevent the example from querying defined names/services on startup (cause warnings in example logs, as illustrated below) @@ -28,6 +26,7 @@ Build the project and flash it to the board, then run monitor tool to view seria ``` make -j4 flash monitor ``` + - Wait for WiFi to connect to your access point - You can now ping the device at `[board-hostname].local`, where `[board-hostname]` is preconfigured hostname, `esp32-mdns` by default. - You can also browse for `_http._tcp` on the same network to find the advertised service diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index 731696060..7e7b22640 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -1,19 +1,5 @@ menu "Example Configuration" - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - config MDNS_HOSTNAME string "mDNS Hostname" default "esp32-mdns" diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 20cdbc3b0..115840584 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -12,90 +12,24 @@ #include "freertos/event_groups.h" #include "esp_system.h" #include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_event.h" #include "esp_log.h" #include "nvs_flash.h" +#include "tcpip_adapter.h" +#include "protocol_examples_common.h" #include "mdns.h" #include "driver/gpio.h" #include #include -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD #define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE - - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int IP4_CONNECTED_BIT = BIT0; -const int IP6_CONNECTED_BIT = BIT1; +static const char c_config_hostname[] = CONFIG_MDNS_HOSTNAME; +#define EXAMPLE_BUTTON_GPIO 0 static const char *TAG = "mdns-test"; -static bool auto_reconnect = true; static char* generate_hostname(); -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_CONNECTED: - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IP4_CONNECTED_BIT); - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: - xEventGroupSetBits(wifi_event_group, IP6_CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently - auto-reassociate. */ - if (auto_reconnect) { - esp_wifi_connect(); - } - xEventGroupClearBits(wifi_event_group, IP4_CONNECTED_BIT | IP6_CONNECTED_BIT); - break; - default: - break; - } - mdns_handle_system_event(ctx, event); - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - static void initialise_mdns(void) { char* hostname = generate_hostname(); @@ -123,7 +57,10 @@ static void initialise_mdns(void) free(hostname); } +/* these strings match tcpip_adapter_if_t enumeration */ static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; + +/* these strings match mdns_ip_protocol_t enumeration */ static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; static void mdns_print_results(mdns_result_t * results){ @@ -200,9 +137,9 @@ static void query_mdns_host(const char * host_name) static void initialise_button(void) { - gpio_config_t io_conf; + gpio_config_t io_conf = {0}; io_conf.intr_type = GPIO_PIN_INTR_DISABLE; - io_conf.pin_bit_mask = 1; + io_conf.pin_bit_mask = BIT64(EXAMPLE_BUTTON_GPIO); io_conf.mode = GPIO_MODE_INPUT; io_conf.pull_up_en = 1; io_conf.pull_down_en = 0; @@ -212,7 +149,7 @@ static void initialise_button(void) static void check_button(void) { static bool old_level = true; - bool new_level = gpio_get_level(GPIO_NUM_0); + bool new_level = gpio_get_level(EXAMPLE_BUTTON_GPIO); if (!new_level && old_level) { query_mdns_host("esp32"); query_mdns_service("_arduino", "_tcp"); @@ -229,10 +166,6 @@ static void check_button(void) static void mdns_example_task(void *pvParameters) { - /* Wait for the callback to set the CONNECTED_BIT in the event group. */ - xEventGroupWaitBits(wifi_event_group, IP4_CONNECTED_BIT | IP6_CONNECTED_BIT, - false, true, portMAX_DELAY); - #if CONFIG_RESOLVE_TEST_SERVICES == 1 /* Send initial queries that are started by CI tester */ query_mdns_host("tinytester"); @@ -246,9 +179,18 @@ static void mdns_example_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); + ESP_ERROR_CHECK(nvs_flash_init()); + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + initialise_mdns(); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + initialise_button(); xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL); } From c0f65a6997cfc5397c321c8e71cbe70931be251c Mon Sep 17 00:00:00 2001 From: Anton Maklakov Date: Tue, 16 Apr 2019 15:32:49 +0700 Subject: [PATCH 069/289] mdns example: Remove a warned unused constant * Original commit: espressif/esp-idf@453a33ce79adadb548418f187ffbbcf60bb5abb0 --- examples/protocols/mdns/main/mdns_example_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 115840584..1004475f3 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -24,7 +24,6 @@ #define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE -static const char c_config_hostname[] = CONFIG_MDNS_HOSTNAME; #define EXAMPLE_BUTTON_GPIO 0 static const char *TAG = "mdns-test"; From c440114d142dc138aa196968695b6ecad2cdeb59 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 15 Mar 2019 16:02:13 +0100 Subject: [PATCH 070/289] mdns: update mdns_out_question_s to be in line with mdns_parsed_question_s struct Closes https://github.com/espressif/esp-idf/issues/1568 * Original commit: espressif/esp-idf@eddd5c4f2c686d9a1d6d3258569cc33752e78880 --- components/mdns/private_include/mdns_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index a5b0747aa..e3becf28f 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -260,7 +260,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; From 4c6818ee971d16a16635b3aa873592d725bc8b69 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 22 Mar 2019 08:49:12 +0100 Subject: [PATCH 071/289] mdns: updated doxygen comments documenting mdns api Closes https://github.com/espressif/esp-idf/issues/1718 * Original commit: espressif/esp-idf@a851aac255311124529f504486ca55bad15c1951 --- components/mdns/include/mdns.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index a5ebb809f..751535b96 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -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 From 84cbb1f3cfc2b7519724dc14efc8f312bfd1a5cc Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 3 May 2019 16:31:11 +0200 Subject: [PATCH 072/289] mdns: use const char* for mdns txt items types to remove warning when assigning * Original commit: espressif/esp-idf@c050a75616803c7871ef11c060e440fae09000d9 --- components/mdns/include/mdns.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 751535b96..4370969d7 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -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; /** From 98d2c1a0736e715ad5d433dfb3d51d101475a4c6 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 3 May 2019 16:37:43 +0200 Subject: [PATCH 073/289] mdns: fixed mdns crashing on reception of txt packet without a corresponding service closes #2866 * Original commit: espressif/esp-idf@af48977f21cea6b18dae10b2c8b64a78acfc647f --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 8c9767942..e88672f82 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2886,7 +2886,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) { From 7e3b35efd9ba5bd506db675cdfba273fc46b1af3 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 14 May 2019 16:41:07 +0200 Subject: [PATCH 074/289] mdns: documentation: fixed inconsistent enum in example of reading mdns results * Original commit: espressif/esp-idf@786f5641f7131a4bc9d595cc011d50c4a0a48f15 --- docs/en/api-reference/protocols/mdns.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/api-reference/protocols/mdns.rst b/docs/en/api-reference/protocols/mdns.rst index d01e24149..5a31fb613 100644 --- a/docs/en/api-reference/protocols/mdns.rst +++ b/docs/en/api-reference/protocols/mdns.rst @@ -126,7 +126,7 @@ Example method to resolve local services:: } a = r->addr; while(a){ - if(a->addr.type == MDNS_IP_PROTOCOL_V6){ + if(a->addr.type == IPADDR_TYPE_V6){ printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); } else { printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); From 05ddd5f0e4c9bbf34bffa800d94d29f7c6965568 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Tue, 30 Apr 2019 12:51:55 +0200 Subject: [PATCH 075/289] Rename Kconfig options (components/esp32) * Original commit: espressif/esp-idf@0ae53691bae8b841d35ed0d5a4d43e1f1a873d2a --- .../common_components/protocol_examples_common/stdin_out.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/common_components/protocol_examples_common/stdin_out.c b/examples/common_components/protocol_examples_common/stdin_out.c index a4bc2cca4..cb2220db4 100644 --- a/examples/common_components/protocol_examples_common/stdin_out.c +++ b/examples/common_components/protocol_examples_common/stdin_out.c @@ -19,10 +19,10 @@ esp_err_t example_configure_stdin_stdout() setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); /* Install UART driver for interrupt-driven reads and writes */ - ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, + ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM, 256, 0, 0, NULL, 0) ); /* Tell VFS to use UART driver */ - esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); + esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); /* Move the caret to the beginning of the next line on '\n' */ esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); From 9a0803ad7e80d2ae0f0edb98ebec284181da0664 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Thu, 9 May 2019 16:43:06 +0200 Subject: [PATCH 076/289] Rename Kconfig options (examples) * Original commit: espressif/esp-idf@151f757912c0de4bc85ad1d2c68c8ce743914ca5 --- .../Kconfig.projbuild | 44 +++++++++---------- .../protocol_examples_common/connect.c | 20 ++++----- examples/protocols/mdns/README.md | 2 +- .../protocols/mdns/main/Kconfig.projbuild | 2 +- .../protocols/mdns/main/mdns_example_main.c | 2 +- examples/protocols/mdns/sdkconfig.ci | 2 +- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index fe095582b..4a370b563 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -31,25 +31,25 @@ menu "Example Connection Configuration" Can be left blank if the network has no security set. - choice PHY_MODEL + choice EXAMPLE_PHY_MODEL prompt "Ethernet PHY" depends on EXAMPLE_CONNECT_ETHERNET - default CONFIG_PHY_TLK110 + default EXAMPLE_PHY_TLK110 help Select the PHY driver to use for the example. - config PHY_IP101 + config EXAMPLE_PHY_IP101 bool "IP101" help IP101 is a single port 10/100 MII/RMII/TP/Fiber Fast Ethernet Transceiver. Goto http://www.icplus.com.tw/pp-IP101G.html for more information about it. - config PHY_TLK110 + config EXAMPLE_PHY_TLK110 bool "TI TLK110 PHY" help Select this to use the TI TLK110 PHY - config PHY_LAN8720 + config EXAMPLE_PHY_LAN8720 bool "Microchip LAN8720 PHY" help Select this to use the Microchip LAN8720 PHY @@ -57,7 +57,7 @@ menu "Example Connection Configuration" endchoice - config PHY_ADDRESS + config EXAMPLE_PHY_ADDRESS int "PHY Address (0-31)" depends on EXAMPLE_CONNECT_ETHERNET default 31 @@ -68,32 +68,32 @@ menu "Example Connection Configuration" LAN8720 default 1 or 0 - choice PHY_CLOCK_MODE + choice EXAMPLE_PHY_CLOCK_MODE prompt "EMAC clock mode" depends on EXAMPLE_CONNECT_ETHERNET - default PHY_CLOCK_GPIO0_IN + default EXAMPLE_PHY_CLOCK_GPIO0_IN help Select external (input on GPIO0) or internal (output on GPIO16 or GPIO17) clock - config PHY_CLOCK_GPIO0_IN + config EXAMPLE_PHY_CLOCK_GPIO0_IN bool "GPIO0 input" depends on EXAMPLE_CONNECT_ETHERNET help Input of 50MHz PHY clock on GPIO0. - config PHY_CLOCK_GPIO0_OUT + config EXAMPLE_PHY_CLOCK_GPIO0_OUT bool "GPIO0 Output" help Output the internal 50MHz RMII clock on GPIO0. - config PHY_CLOCK_GPIO16_OUT + config EXAMPLE_PHY_CLOCK_GPIO16_OUT bool "GPIO16 output" depends on EXAMPLE_CONNECT_ETHERNET help Output the internal 50MHz APLL clock on GPIO16. - config PHY_CLOCK_GPIO17_OUT + config EXAMPLE_PHY_CLOCK_GPIO17_OUT bool "GPIO17 output (inverted)" depends on EXAMPLE_CONNECT_ETHERNET help @@ -101,16 +101,16 @@ menu "Example Connection Configuration" endchoice - config PHY_CLOCK_MODE + config EXAMPLE_PHY_CLOCK_MODE int depends on EXAMPLE_CONNECT_ETHERNET - default 0 if PHY_CLOCK_GPIO0_IN - default 1 if PHY_CLOCK_GPIO0_OUT - default 2 if PHY_CLOCK_GPIO16_OUT - default 3 if PHY_CLOCK_GPIO17_OUT + default 0 if EXAMPLE_PHY_CLOCK_GPIO0_IN + default 1 if EXAMPLE_PHY_CLOCK_GPIO0_OUT + default 2 if EXAMPLE_PHY_CLOCK_GPIO16_OUT + default 3 if EXAMPLE_PHY_CLOCK_GPIO17_OUT - config PHY_USE_POWER_PIN + config EXAMPLE_PHY_USE_POWER_PIN bool "Use PHY Power (enable/disable) pin" depends on EXAMPLE_CONNECT_ETHERNET default y @@ -118,16 +118,16 @@ menu "Example Connection Configuration" Use a GPIO "power pin" to power the PHY on/off during operation. Consult the example README for more details - config PHY_POWER_PIN + config EXAMPLE_PHY_POWER_PIN int "PHY Power GPIO" depends on EXAMPLE_CONNECT_ETHERNET default 17 range 0 33 - depends on PHY_USE_POWER_PIN + depends on EXAMPLE_PHY_USE_POWER_PIN help GPIO number to use for powering on/off the PHY. - config PHY_SMI_MDC_PIN + config EXAMPLE_PHY_SMI_MDC_PIN int "SMI MDC Pin" depends on EXAMPLE_CONNECT_ETHERNET default 23 @@ -135,7 +135,7 @@ menu "Example Connection Configuration" help GPIO number to use for SMI clock output MDC to PHY. - config PHY_SMI_MDIO_PIN + config EXAMPLE_PHY_SMI_MDIO_PIN int "SMI MDIO Pin" depends on EXAMPLE_CONNECT_ETHERNET default 18 diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 37d9df6db..718d498f7 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -160,23 +160,23 @@ static void stop() #include "driver/gpio.h" -#ifdef CONFIG_PHY_LAN8720 +#ifdef CONFIG_EXAMPLE_PHY_LAN8720 #include "eth_phy/phy_lan8720.h" #define DEFAULT_ETHERNET_PHY_CONFIG phy_lan8720_default_ethernet_config #endif -#ifdef CONFIG_PHY_TLK110 +#ifdef CONFIG_EXAMPLE_PHY_TLK110 #include "eth_phy/phy_tlk110.h" #define DEFAULT_ETHERNET_PHY_CONFIG phy_tlk110_default_ethernet_config -#elif CONFIG_PHY_IP101 +#elif CONFIG_EXAMPLE_PHY_IP101 #include "eth_phy/phy_ip101.h" #define DEFAULT_ETHERNET_PHY_CONFIG phy_ip101_default_ethernet_config #endif -#define PIN_PHY_POWER CONFIG_PHY_POWER_PIN -#define PIN_SMI_MDC CONFIG_PHY_SMI_MDC_PIN -#define PIN_SMI_MDIO CONFIG_PHY_SMI_MDIO_PIN +#define PIN_PHY_POWER CONFIG_EXAMPLE_PHY_POWER_PIN +#define PIN_SMI_MDC CONFIG_EXAMPLE_PHY_SMI_MDC_PIN +#define PIN_SMI_MDIO CONFIG_EXAMPLE_PHY_SMI_MDIO_PIN -#ifdef CONFIG_PHY_USE_POWER_PIN +#ifdef CONFIG_EXAMPLE_PHY_USE_POWER_PIN /** * @brief re-define power enable func for phy * @@ -252,12 +252,12 @@ static void on_eth_event(void* arg, esp_event_base_t event_base, static void start() { eth_config_t config = DEFAULT_ETHERNET_PHY_CONFIG; - config.phy_addr = CONFIG_PHY_ADDRESS; + config.phy_addr = CONFIG_EXAMPLE_PHY_ADDRESS; config.gpio_config = eth_gpio_config_rmii; config.tcpip_input = tcpip_adapter_eth_input; - config.clock_mode = CONFIG_PHY_CLOCK_MODE; + config.clock_mode = CONFIG_EXAMPLE_PHY_CLOCK_MODE; -#ifdef CONFIG_PHY_USE_POWER_PIN +#ifdef CONFIG_EXAMPLE_PHY_USE_POWER_PIN /* Replace the default 'power enable' function with an example-specific one that toggles a power GPIO. */ config.phy_power_enable = phy_device_power_enable_via_gpio; diff --git a/examples/protocols/mdns/README.md b/examples/protocols/mdns/README.md index 182434e58..2c3516764 100644 --- a/examples/protocols/mdns/README.md +++ b/examples/protocols/mdns/README.md @@ -31,7 +31,7 @@ make -j4 flash monitor - You can now ping the device at `[board-hostname].local`, where `[board-hostname]` is preconfigured hostname, `esp32-mdns` by default. - You can also browse for `_http._tcp` on the same network to find the advertised service - Pressing the BOOT button will start querying the local network for the predefined in `check_button` hosts and services -- Note that for purpose of CI tests, configuration options of `RESOLVE_TEST_SERVICES` and `MDNS_ADD_MAC_TO_HOSTNAME` are available, but disabled by default. If enabled, then the hostname suffix of last 3 bytes from device MAC address is added, e.g. `esp32-mdns-80FFFF`, and a query for test service is issued. +- Note that for purpose of CI tests, configuration options of `MDNS_RESOLVE_TEST_SERVICES` and `MDNS_ADD_MAC_TO_HOSTNAME` are available, but disabled by default. If enabled, then the hostname suffix of last 3 bytes from device MAC address is added, e.g. `esp32-mdns-80FFFF`, and a query for test service is issued. (To exit the serial monitor, type ``Ctrl-]``.) diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index 7e7b22640..c4ae7e13b 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -12,7 +12,7 @@ menu "Example Configuration" help mDNS Instance Name for example to use - config RESOLVE_TEST_SERVICES + config MDNS_RESOLVE_TEST_SERVICES bool "Resolve test services" default n help diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 1004475f3..11bee313b 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -165,7 +165,7 @@ static void check_button(void) static void mdns_example_task(void *pvParameters) { -#if CONFIG_RESOLVE_TEST_SERVICES == 1 +#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 /* Send initial queries that are started by CI tester */ query_mdns_host("tinytester"); #endif diff --git a/examples/protocols/mdns/sdkconfig.ci b/examples/protocols/mdns/sdkconfig.ci index 8d9206d0e..13b56273e 100644 --- a/examples/protocols/mdns/sdkconfig.ci +++ b/examples/protocols/mdns/sdkconfig.ci @@ -1,2 +1,2 @@ -CONFIG_RESOLVE_TEST_SERVICES=y +CONFIG_MDNS_RESOLVE_TEST_SERVICES=y CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y From 417221922583c6676f36cd47c38e2b56c9799372 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 30 Apr 2019 13:54:08 +0200 Subject: [PATCH 077/289] mdns tests: adapt mdns fuzzer test to compile with event loop library * Original commit: espressif/esp-idf@38d15cbd637e8b8baacda9fc43e8e99d224530f5 --- .../mdns/test_afl_fuzz_host/esp32_compat.h | 86 ++++++++++--------- .../mdns/test_afl_fuzz_host/esp32_mock.c | 17 ++++ .../mdns/test_afl_fuzz_host/esp32_mock.h | 4 + 3 files changed, 67 insertions(+), 40 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/esp32_compat.h b/components/mdns/test_afl_fuzz_host/esp32_compat.h index e054c18bb..acdafa31a 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_compat.h +++ b/components/mdns/test_afl_fuzz_host/esp32_compat.h @@ -20,7 +20,6 @@ // Not to include #define ESP_MDNS_NETWORKING_H_ #define _TCPIP_ADAPTER_H_ -#define __ESP_EVENT_H__ #ifdef USE_BSD_STRING @@ -116,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 */ @@ -124,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; }; @@ -180,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 */ @@ -191,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) { diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.c b/components/mdns/test_afl_fuzz_host/esp32_mock.c index 8cc986dfd..2607b40cc 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.c +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.c @@ -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; diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h index 5ff5ad633..fb4a21a43 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.h @@ -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_ */ \ No newline at end of file From 181a22ec2b5b8ee20f4ad65356e42380006cd478 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 27 May 2019 16:06:48 +0200 Subject: [PATCH 078/289] mdns: added initial suite of api unit tests * Original commit: espressif/esp-idf@e6801912c5c4861f828ab1f447280628bba9a5d7 --- components/mdns/test/CMakeLists.txt | 3 + components/mdns/test/component.mk | 4 ++ components/mdns/test/test_mdns.c | 99 +++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 components/mdns/test/CMakeLists.txt create mode 100644 components/mdns/test/component.mk create mode 100644 components/mdns/test/test_mdns.c diff --git a/components/mdns/test/CMakeLists.txt b/components/mdns/test/CMakeLists.txt new file mode 100644 index 000000000..7e694470f --- /dev/null +++ b/components/mdns/test/CMakeLists.txt @@ -0,0 +1,3 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_PRIV_REQUIRES unity test_utils mdns) +register_component() \ No newline at end of file diff --git a/components/mdns/test/component.mk b/components/mdns/test/component.mk new file mode 100644 index 000000000..5be873488 --- /dev/null +++ b/components/mdns/test/component.mk @@ -0,0 +1,4 @@ +# +#Component Makefile +# +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive \ No newline at end of file diff --git a/components/mdns/test/test_mdns.c b/components/mdns/test/test_mdns.c new file mode 100644 index 000000000..6ae5e835f --- /dev/null +++ b/components/mdns/test/test_mdns.c @@ -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 Date: Wed, 29 May 2019 17:07:39 +0200 Subject: [PATCH 079/289] mdns: fix static analysis warnings * Original commit: espressif/esp-idf@c34de4cba658e8331f8a3ab2f466190c7640595b --- components/mdns/mdns.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index e88672f82..ad3dfb49e 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1312,6 +1312,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); } @@ -2801,7 +2802,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)) { @@ -3831,23 +3832,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); + } } } From 7fb668671682277e292534bdcd177a3cb11d637a Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Sun, 28 Apr 2019 15:38:23 +0800 Subject: [PATCH 080/289] components: use new component registration api * Original commit: espressif/esp-idf@9eccd7c0826d6cc2e9de59304d1e5f76c0063ccf --- components/mdns/CMakeLists.txt | 14 ++++++-------- components/mdns/test/CMakeLists.txt | 5 ++--- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 0933e3005..7b744dde5 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -1,9 +1,7 @@ -set(COMPONENT_SRCS "mdns.c" - "mdns_console.c" - "mdns_networking.c") -set(COMPONENT_ADD_INCLUDEDIRS "include") -set(COMPONENT_PRIV_INCLUDEDIRS "private_include") -set(COMPONENT_REQUIRES lwip mbedtls console tcpip_adapter) - -register_component() +idf_component_register(SRCS "mdns.c" + "mdns_console.c" + "mdns_networking.c" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "private_include" + REQUIRES lwip mbedtls console tcpip_adapter) diff --git a/components/mdns/test/CMakeLists.txt b/components/mdns/test/CMakeLists.txt index 7e694470f..516ee0097 100644 --- a/components/mdns/test/CMakeLists.txt +++ b/components/mdns/test/CMakeLists.txt @@ -1,3 +1,2 @@ -set(COMPONENT_SRCDIRS ".") -set(COMPONENT_PRIV_REQUIRES unity test_utils mdns) -register_component() \ No newline at end of file +idf_component_register(SRC_DIRS "." + PRIV_REQUIRES unity test_utils mdns) \ No newline at end of file From 271665e0cb27710f634d79314436317df3853e09 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Sun, 28 Apr 2019 15:38:46 +0800 Subject: [PATCH 081/289] examples: use new component registration api * Original commit: espressif/esp-idf@6771eead80534c51efb2033c04769ef5893b4838 --- .../protocol_examples_common/CMakeLists.txt | 7 ++----- examples/protocols/mdns/main/CMakeLists.txt | 6 ++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/examples/common_components/protocol_examples_common/CMakeLists.txt b/examples/common_components/protocol_examples_common/CMakeLists.txt index 784909da0..0ccb219b4 100644 --- a/examples/common_components/protocol_examples_common/CMakeLists.txt +++ b/examples/common_components/protocol_examples_common/CMakeLists.txt @@ -1,5 +1,2 @@ -set(COMPONENT_SRCS "connect.c" - "stdin_out.c") -set(COMPONENT_ADD_INCLUDEDIRS "include") - -register_component() +idf_component_register(SRCS "connect.c" "stdin_out.c" + INCLUDE_DIRS "include") diff --git a/examples/protocols/mdns/main/CMakeLists.txt b/examples/protocols/mdns/main/CMakeLists.txt index 814837ea9..141d1e30d 100644 --- a/examples/protocols/mdns/main/CMakeLists.txt +++ b/examples/protocols/mdns/main/CMakeLists.txt @@ -1,4 +1,2 @@ -set(COMPONENT_SRCS "mdns_example_main.c") -set(COMPONENT_ADD_INCLUDEDIRS ".") - -register_component() +idf_component_register(SRCS "mdns_example_main.c" + INCLUDE_DIRS ".") \ No newline at end of file From 680bad646faac789df3335dadb4ec941f542746c Mon Sep 17 00:00:00 2001 From: suda-morris <362953310@qq.com> Date: Wed, 10 Apr 2019 16:24:50 +0800 Subject: [PATCH 082/289] add esp_eth component * Original commit: espressif/esp-idf@90c4827bd22aa61894a5b22b3b39247a7e44d6cf --- components/mdns/mdns.c | 10 +- .../Kconfig.projbuild | 116 +++---------- .../protocol_examples_common/connect.c | 152 +++++------------- 3 files changed, 63 insertions(+), 215 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index ad3dfb49e..97156194e 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3049,13 +3049,13 @@ void _mdns_disable_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protoc /** * @brief Dispatch interface changes based on system events */ -static void _mdns_handle_system_event(esp_event_base_t event_base, +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; if (event_base == WIFI_EVENT) { switch(event_id) { @@ -3723,7 +3723,7 @@ 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_base, + _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: @@ -4120,7 +4120,7 @@ esp_err_t mdns_handle_system_event(void *ctx, system_event_t *event) return ESP_OK; } -static void event_handler(void* arg, esp_event_base_t event_base, +static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (!_mdns_server) { @@ -4142,7 +4142,7 @@ static void event_handler(void* arg, esp_event_base_t event_base, if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { free(action); - } + } } esp_err_t mdns_init() diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index 4a370b563..7de1c4359 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -30,119 +30,39 @@ menu "Example Connection Configuration" WiFi password (WPA or WPA2) for the example to use. Can be left blank if the network has no security set. - - choice EXAMPLE_PHY_MODEL - prompt "Ethernet PHY" + choice EXAMPLE_ETH_PHY_MODEL depends on EXAMPLE_CONNECT_ETHERNET - default EXAMPLE_PHY_TLK110 + prompt "Ethernet PHY Device" + default EXAMPLE_ETH_PHY_IP101 help Select the PHY driver to use for the example. - config EXAMPLE_PHY_IP101 + config EXAMPLE_ETH_PHY_IP101 bool "IP101" help IP101 is a single port 10/100 MII/RMII/TP/Fiber Fast Ethernet Transceiver. Goto http://www.icplus.com.tw/pp-IP101G.html for more information about it. - config EXAMPLE_PHY_TLK110 - bool "TI TLK110 PHY" + config EXAMPLE_ETH_PHY_RTL8201 + bool "RTL8201/SR8201" help - Select this to use the TI TLK110 PHY + RTL8201F/SR8201F is a single port 10/100Mb Ethernet Transceiver with auto MDIX. + Goto http://www.corechip-sz.com/productsview.asp?id=22 for more information about it. - config EXAMPLE_PHY_LAN8720 - bool "Microchip LAN8720 PHY" + config EXAMPLE_ETH_PHY_LAN8720 + bool "LAN8720" help - Select this to use the Microchip LAN8720 PHY + LAN8720A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX Support. + Goto https://www.microchip.com/LAN8720A for more information about it. + + config EXAMPLE_ETH_PHY_DP83848 + bool "DP83848" + help + DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver. + Goto http://www.ti.com/product/DP83848J for more information about it. endchoice - - config EXAMPLE_PHY_ADDRESS - int "PHY Address (0-31)" - depends on EXAMPLE_CONNECT_ETHERNET - default 31 - range 0 31 - help - Select the PHY Address (0-31) for the hardware configuration and PHY model. - TLK110 default 31 - LAN8720 default 1 or 0 - - - choice EXAMPLE_PHY_CLOCK_MODE - prompt "EMAC clock mode" - depends on EXAMPLE_CONNECT_ETHERNET - default EXAMPLE_PHY_CLOCK_GPIO0_IN - help - Select external (input on GPIO0) or internal (output on GPIO16 or GPIO17) clock - - - config EXAMPLE_PHY_CLOCK_GPIO0_IN - bool "GPIO0 input" - depends on EXAMPLE_CONNECT_ETHERNET - help - Input of 50MHz PHY clock on GPIO0. - - config EXAMPLE_PHY_CLOCK_GPIO0_OUT - bool "GPIO0 Output" - help - Output the internal 50MHz RMII clock on GPIO0. - - config EXAMPLE_PHY_CLOCK_GPIO16_OUT - bool "GPIO16 output" - depends on EXAMPLE_CONNECT_ETHERNET - help - Output the internal 50MHz APLL clock on GPIO16. - - config EXAMPLE_PHY_CLOCK_GPIO17_OUT - bool "GPIO17 output (inverted)" - depends on EXAMPLE_CONNECT_ETHERNET - help - Output the internal 50MHz APLL clock on GPIO17 (inverted signal). - - endchoice - - config EXAMPLE_PHY_CLOCK_MODE - int - depends on EXAMPLE_CONNECT_ETHERNET - default 0 if EXAMPLE_PHY_CLOCK_GPIO0_IN - default 1 if EXAMPLE_PHY_CLOCK_GPIO0_OUT - default 2 if EXAMPLE_PHY_CLOCK_GPIO16_OUT - default 3 if EXAMPLE_PHY_CLOCK_GPIO17_OUT - - - config EXAMPLE_PHY_USE_POWER_PIN - bool "Use PHY Power (enable/disable) pin" - depends on EXAMPLE_CONNECT_ETHERNET - default y - help - Use a GPIO "power pin" to power the PHY on/off during operation. - Consult the example README for more details - - config EXAMPLE_PHY_POWER_PIN - int "PHY Power GPIO" - depends on EXAMPLE_CONNECT_ETHERNET - default 17 - range 0 33 - depends on EXAMPLE_PHY_USE_POWER_PIN - help - GPIO number to use for powering on/off the PHY. - - config EXAMPLE_PHY_SMI_MDC_PIN - int "SMI MDC Pin" - depends on EXAMPLE_CONNECT_ETHERNET - default 23 - range 0 33 - help - GPIO number to use for SMI clock output MDC to PHY. - - config EXAMPLE_PHY_SMI_MDIO_PIN - int "SMI MDIO Pin" - depends on EXAMPLE_CONNECT_ETHERNET - default 18 - range 0 33 - help - GPIO number to use for SMI data pin MDIO to/from PHY. - config EXAMPLE_CONNECT_IPV6 bool "Obtain IPv6 link-local address" default y diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 718d498f7..f12d40dda 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -21,24 +21,23 @@ #include "lwip/err.h" #include "lwip/sys.h" -#define GOT_IPV4_BIT BIT(0) -#define GOT_IPV6_BIT BIT(1) +#define GOT_IPV4_BIT BIT(0) +#define GOT_IPV6_BIT BIT(1) #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 -#define CONNECTED_BITS (GOT_IPV4_BIT | GOT_IPV6_BIT) +#define CONNECTED_BITS (GOT_IPV4_BIT | GOT_IPV6_BIT) #else -#define CONNECTED_BITS (GOT_IPV4_BIT) +#define CONNECTED_BITS (GOT_IPV4_BIT) #endif static EventGroupHandle_t s_connect_event_group; static ip4_addr_t s_ip_addr; -static const char* s_connection_name; +static const char *s_connection_name; #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 static ip6_addr_t s_ipv6_addr; #endif - static const char *TAG = "example_connect"; /* set up connection, Wi-Fi or Ethernet */ @@ -47,20 +46,20 @@ static void start(); /* tear down connection, release resources */ static void stop(); -static void on_got_ip(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) +static void on_got_ip(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { - ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; + ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr)); xEventGroupSetBits(s_connect_event_group, GOT_IPV4_BIT); } #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 -static void on_got_ipv6(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) +static void on_got_ipv6(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { - ip_event_got_ip6_t* event = (ip_event_got_ip6_t*) event_data; + ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data; memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); } @@ -98,17 +97,17 @@ esp_err_t example_disconnect() #ifdef CONFIG_EXAMPLE_CONNECT_WIFI -static void on_wifi_disconnect(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) +static void on_wifi_disconnect(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect..."); - ESP_ERROR_CHECK( esp_wifi_connect() ); + ESP_ERROR_CHECK(esp_wifi_connect()); } #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 -static void on_wifi_connect(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) +static void on_wifi_connect(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); } @@ -155,87 +154,13 @@ static void stop() } #endif // CONFIG_EXAMPLE_CONNECT_WIFI - #ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET -#include "driver/gpio.h" - -#ifdef CONFIG_EXAMPLE_PHY_LAN8720 -#include "eth_phy/phy_lan8720.h" -#define DEFAULT_ETHERNET_PHY_CONFIG phy_lan8720_default_ethernet_config -#endif -#ifdef CONFIG_EXAMPLE_PHY_TLK110 -#include "eth_phy/phy_tlk110.h" -#define DEFAULT_ETHERNET_PHY_CONFIG phy_tlk110_default_ethernet_config -#elif CONFIG_EXAMPLE_PHY_IP101 -#include "eth_phy/phy_ip101.h" -#define DEFAULT_ETHERNET_PHY_CONFIG phy_ip101_default_ethernet_config -#endif - -#define PIN_PHY_POWER CONFIG_EXAMPLE_PHY_POWER_PIN -#define PIN_SMI_MDC CONFIG_EXAMPLE_PHY_SMI_MDC_PIN -#define PIN_SMI_MDIO CONFIG_EXAMPLE_PHY_SMI_MDIO_PIN - -#ifdef CONFIG_EXAMPLE_PHY_USE_POWER_PIN -/** - * @brief re-define power enable func for phy - * - * @param enable true to enable, false to disable - * - * @note This function replaces the default PHY power on/off function. - * If this GPIO is not connected on your device (and PHY is always powered), - * you can use the default PHY-specific power on/off function. - */ -static void phy_device_power_enable_via_gpio(bool enable) -{ - assert(DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable); - - if (!enable) { - DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable(false); - } - - gpio_pad_select_gpio(PIN_PHY_POWER); - gpio_set_direction(PIN_PHY_POWER, GPIO_MODE_OUTPUT); - if (enable == true) { - gpio_set_level(PIN_PHY_POWER, 1); - ESP_LOGI(TAG, "Power On Ethernet PHY"); - } else { - gpio_set_level(PIN_PHY_POWER, 0); - ESP_LOGI(TAG, "Power Off Ethernet PHY"); - } - - vTaskDelay(1); // Allow the power up/down to take effect, min 300us - - if (enable) { - /* call the default PHY-specific power on function */ - DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable(true); - } -} -#endif - -/** - * @brief gpio specific init - * - * @note RMII data pins are fixed in esp32: - * TXD0 <=> GPIO19 - * TXD1 <=> GPIO22 - * TX_EN <=> GPIO21 - * RXD0 <=> GPIO25 - * RXD1 <=> GPIO26 - * CLK <=> GPIO0 - * - */ -static void eth_gpio_config_rmii(void) -{ - phy_rmii_configure_data_interface_pins(); - phy_rmii_smi_configure_pins(PIN_SMI_MDC, PIN_SMI_MDIO); -} - #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 /** Event handler for Ethernet events */ -static void on_eth_event(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) +static void on_eth_event(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { switch (event_id) { case ETHERNET_EVENT_CONNECTED: @@ -249,30 +174,33 @@ static void on_eth_event(void* arg, esp_event_base_t event_base, #endif // CONFIG_EXAMPLE_CONNECT_IPV6 +static esp_eth_handle_t s_eth_handle = NULL; +static esp_eth_mac_t *s_mac = NULL; +static esp_eth_phy_t *s_phy = NULL; + static void start() { - eth_config_t config = DEFAULT_ETHERNET_PHY_CONFIG; - config.phy_addr = CONFIG_EXAMPLE_PHY_ADDRESS; - config.gpio_config = eth_gpio_config_rmii; - config.tcpip_input = tcpip_adapter_eth_input; - config.clock_mode = CONFIG_EXAMPLE_PHY_CLOCK_MODE; - -#ifdef CONFIG_EXAMPLE_PHY_USE_POWER_PIN - /* Replace the default 'power enable' function with an example-specific one - that toggles a power GPIO. */ - config.phy_power_enable = phy_device_power_enable_via_gpio; -#endif - - ESP_ERROR_CHECK(esp_eth_init(&config)); - + ESP_ERROR_CHECK(tcpip_adapter_set_default_eth_handlers()); ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL)); #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, NULL)); ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL)); #endif + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); + s_mac = esp_eth_mac_new_esp32(&mac_config); + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); +#if CONFIG_EXAMPLE_ETH_PHY_IP101 + s_phy = esp_eth_phy_new_ip101(&phy_config); +#elif CONFIG_EXAMPLE_ETH_PHY_RTL8201 + s_phy = esp_eth_phy_new_rtl8201(&phy_config); +#elif CONFIG_EXAMPLE_ETH_PHY_LAN8720 + s_phy = esp_eth_phy_new_lan8720(&phy_config); +#elif CONFIG_EXAMPLE_ETH_PHY_DP83848 + s_phy = esp_eth_phy_new_dp83848(&phy_config); +#endif + esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy); - ESP_ERROR_CHECK(esp_eth_enable()); - + ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle)); s_connection_name = "Ethernet"; } @@ -283,9 +211,9 @@ static void stop() ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6)); ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event)); #endif - - ESP_ERROR_CHECK(esp_eth_disable()); - ESP_ERROR_CHECK(esp_eth_deinit()); + ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle)); + ESP_ERROR_CHECK(s_phy->del(s_phy)); + ESP_ERROR_CHECK(s_mac->del(s_mac)); } #endif // CONFIG_EXAMPLE_CONNECT_ETHERNET From ed71a239a8e19f8a92a93ea50731101693833def Mon Sep 17 00:00:00 2001 From: suda-morris <362953310@qq.com> Date: Tue, 25 Jun 2019 19:36:56 +0800 Subject: [PATCH 083/289] ethernet: support dm9051 1. move resource allocation from xxx_init to xxx_new 2. fix enabling tx checksum insertion by mistake 3. iperf example: enlarge max arguments 4. add examples for spi-ethernet Closes https://github.com/espressif/esp-idf/issues/3715 Closes https://github.com/espressif/esp-idf/issues/3711 * Original commit: espressif/esp-idf@cb42c292525f38723ca596d8acef533873019be7 --- .../Kconfig.projbuild | 149 +++++++++++++----- .../protocol_examples_common/connect.c | 29 +++- 2 files changed, 134 insertions(+), 44 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index 7de1c4359..f5d288e9a 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -1,5 +1,4 @@ menu "Example Connection Configuration" - choice EXAMPLE_CONNECT_INTERFACE prompt "Connect using" default EXAMPLE_CONNECT_WIFI @@ -15,53 +14,120 @@ menu "Example Connection Configuration" endchoice - config EXAMPLE_WIFI_SSID - depends on EXAMPLE_CONNECT_WIFI - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config EXAMPLE_WIFI_PASSWORD - depends on EXAMPLE_CONNECT_WIFI - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - - choice EXAMPLE_ETH_PHY_MODEL - depends on EXAMPLE_CONNECT_ETHERNET - prompt "Ethernet PHY Device" - default EXAMPLE_ETH_PHY_IP101 - help - Select the PHY driver to use for the example. - - config EXAMPLE_ETH_PHY_IP101 - bool "IP101" + if EXAMPLE_CONNECT_WIFI + config EXAMPLE_WIFI_SSID + string "WiFi SSID" + default "myssid" help - IP101 is a single port 10/100 MII/RMII/TP/Fiber Fast Ethernet Transceiver. - Goto http://www.icplus.com.tw/pp-IP101G.html for more information about it. + SSID (network name) for the example to connect to. - config EXAMPLE_ETH_PHY_RTL8201 - bool "RTL8201/SR8201" + config EXAMPLE_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" help - RTL8201F/SR8201F is a single port 10/100Mb Ethernet Transceiver with auto MDIX. - Goto http://www.corechip-sz.com/productsview.asp?id=22 for more information about it. + WiFi password (WPA or WPA2) for the example to use. + Can be left blank if the network has no security set. + endif - config EXAMPLE_ETH_PHY_LAN8720 - bool "LAN8720" + if EXAMPLE_CONNECT_ETHERNET + choice EXAMPLE_USE_ETHERNET + prompt "Ethernet Type" + default EXAMPLE_USE_INTERNAL_ETHERNET if IDF_TARGET_ESP32 + default EXAMPLE_USE_SPI_ETHERNET if !IDF_TARGET_ESP32 help - LAN8720A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX Support. - Goto https://www.microchip.com/LAN8720A for more information about it. + Select which kind of Ethernet will be used in the example. - config EXAMPLE_ETH_PHY_DP83848 - bool "DP83848" - help - DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver. - Goto http://www.ti.com/product/DP83848J for more information about it. + config EXAMPLE_USE_INTERNAL_ETHERNET + depends on IDF_TARGET_ESP32 + select ETH_USE_ESP32_EMAC + bool "Internal EMAC" + help + Select internal Ethernet MAC controller. - endchoice + config EXAMPLE_USE_SPI_ETHERNET + bool "SPI Ethernet Module" + select ETH_USE_SPI_ETHERNET + help + Select external SPI-Ethernet module. + endchoice + + if EXAMPLE_USE_INTERNAL_ETHERNET + choice EXAMPLE_ETH_PHY_MODEL + prompt "Ethernet PHY Device" + default EXAMPLE_ETH_PHY_IP101 + help + Select the Ethernet PHY device to use in the example. + + config EXAMPLE_ETH_PHY_IP101 + bool "IP101" + help + IP101 is a single port 10/100 MII/RMII/TP/Fiber Fast Ethernet Transceiver. + Goto http://www.icplus.com.tw/pp-IP101G.html for more information about it. + + config EXAMPLE_ETH_PHY_RTL8201 + bool "RTL8201/SR8201" + help + RTL8201F/SR8201F is a single port 10/100Mb Ethernet Transceiver with auto MDIX. + Goto http://www.corechip-sz.com/productsview.asp?id=22 for more information about it. + + config EXAMPLE_ETH_PHY_LAN8720 + bool "LAN8720" + help + LAN8720A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX Support. + Goto https://www.microchip.com/LAN8720A for more information about it. + + config EXAMPLE_ETH_PHY_DP83848 + bool "DP83848" + help + DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver. + Goto http://www.ti.com/product/DP83848J for more information about it. + endchoice + endif + + if EXAMPLE_USE_SPI_ETHERNET + config EXAMPLE_ETH_SPI_HOST + int "SPI Host Number" + range 0 2 + default 1 + help + Set the SPI host used to communicate with DM9051. + + config EXAMPLE_ETH_SCLK_GPIO + int "SPI SCLK GPIO number" + range 0 33 + default 19 + help + Set the GPIO number used by SPI SCLK. + + config EXAMPLE_ETH_MOSI_GPIO + int "SPI MOSI GPIO number" + range 0 33 + default 23 + help + Set the GPIO number used by SPI MOSI. + + config EXAMPLE_ETH_MISO_GPIO + int "SPI MISO GPIO number" + range 0 33 + default 25 + help + Set the GPIO number used by SPI MISO. + + config EXAMPLE_ETH_CS_GPIO + int "SPI CS GPIO number" + range 0 33 + default 22 + help + Set the GPIO number used by SPI CS. + + config EXAMPLE_ETH_SPI_CLOCK_MHZ + int "SPI clock speed (MHz)" + range 20 80 + default 20 + help + Set the clock speed (MHz) of SPI interface. + endif + endif config EXAMPLE_CONNECT_IPV6 bool "Obtain IPv6 link-local address" @@ -69,5 +135,4 @@ menu "Example Connection Configuration" help By default, examples will wait until IPv4 and IPv6 addresses are obtained. Disable this option if the network does not support IPv6. - endmenu diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index f12d40dda..68895905a 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -187,8 +187,9 @@ static void start() ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL)); #endif eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - s_mac = esp_eth_mac_new_esp32(&mac_config); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); +#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET + s_mac = esp_eth_mac_new_esp32(&mac_config); #if CONFIG_EXAMPLE_ETH_PHY_IP101 s_phy = esp_eth_phy_new_ip101(&phy_config); #elif CONFIG_EXAMPLE_ETH_PHY_RTL8201 @@ -197,9 +198,33 @@ static void start() s_phy = esp_eth_phy_new_lan8720(&phy_config); #elif CONFIG_EXAMPLE_ETH_PHY_DP83848 s_phy = esp_eth_phy_new_dp83848(&phy_config); +#endif +#elif CONFIG_EXAMPLE_USE_SPI_ETHERNET + gpio_install_isr_service(0); + spi_device_handle_t spi_handle = NULL; + spi_bus_config_t buscfg = { + .miso_io_num = CONFIG_EXAMPLE_ETH_MISO_GPIO, + .mosi_io_num = CONFIG_EXAMPLE_ETH_MOSI_GPIO, + .sclk_io_num = CONFIG_EXAMPLE_ETH_SCLK_GPIO, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + }; + ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1)); + spi_device_interface_config_t devcfg = { + .command_bits = 1, + .address_bits = 7, + .mode = 0, + .clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000, + .spics_io_num = CONFIG_EXAMPLE_ETH_CS_GPIO, + .queue_size = 20 + }; + ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle)); + /* dm9051 ethernet driver is based on spi driver, so need to specify the spi handle */ + mac_config.spi_hdl = spi_handle; + s_mac = esp_eth_mac_new_dm9051(&mac_config); + s_phy = esp_eth_phy_new_dm9051(&phy_config); #endif esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy); - ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle)); s_connection_name = "Ethernet"; } From e431b6b7fe363999c2e9ba5563a3540c8ad8c987 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sun, 23 Jun 2019 11:54:31 +1000 Subject: [PATCH 084/289] build system: Use CMake-based build system as default when describing commands * Original commit: espressif/esp-idf@47bbb107a8deaa80692ebc3b9369ae0618c3bc56 --- examples/protocols/mdns/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/protocols/mdns/README.md b/examples/protocols/mdns/README.md index 2c3516764..2392699b6 100644 --- a/examples/protocols/mdns/README.md +++ b/examples/protocols/mdns/README.md @@ -4,15 +4,15 @@ Shows how to use mDNS to advertise lookup services and hosts ## Example workflow -- mDNS is initialized with host name and instance name defined through `make menuconfig` and `_http._tcp` service is added to be advertised -- WiFi STA is started and trying to connect to the access point defined through `make menuconfig` +- mDNS is initialized with host name and instance name defined through the project configuration and `_http._tcp` service is added to be advertised +- WiFi STA is started and trying to connect to the access point defined through the project configuration - The system event handler is used to pass the network events to mDNS so the service is aware when the interface comes up or down - GPIO0 (BOOT Button) is initialized as pulled-up input that can be monitored for button press - Example task is started to check if the button is pressed so it can execute the mDNS queries defined ### Configure the project -* Run `make menuconfig` (or `idf.py menuconfig` if using CMake build system) +* Open the project configuration menu (`idf.py menuconfig`) * Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../README.md) for more details. * When using Make build system, set `Default serial port` under `Serial flasher config`. From 144d4ad1d4bd520108c655a23de60a4c6463812b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 20 Jun 2019 14:12:15 +0200 Subject: [PATCH 085/289] mdns: fix ignoring mdns packet with some invalid name entries in question field In case of invalid name entry, only this entry is invalidated and parsing continues as other query entries could contain questions to be responded to * Original commit: espressif/esp-idf@4bd4c7caf3f9ef8402c5a27ab44561537407eb60 --- components/mdns/mdns.c | 9 +++++---- components/mdns/private_include/mdns_private.h | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 97156194e..92909e2de 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -174,7 +174,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 +195,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); } @@ -2316,6 +2316,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]; @@ -2323,7 +2324,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) { @@ -2621,7 +2622,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; } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index e3becf28f..ed7e89cb8 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -184,6 +184,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 { From aaba3fc47a4ad9ef1e2db0e0daca327071bac626 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 2 Aug 2019 09:01:20 +0530 Subject: [PATCH 086/289] examples: change default build instructions in docs to CMake * Original commit: espressif/esp-idf@e7dba7d7bc6218eea440dfe6f55592b8c21f6083 --- examples/protocols/mdns/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/mdns/README.md b/examples/protocols/mdns/README.md index 2392699b6..2b99f2d4c 100644 --- a/examples/protocols/mdns/README.md +++ b/examples/protocols/mdns/README.md @@ -24,7 +24,7 @@ Shows how to use mDNS to advertise lookup services and hosts Build the project and flash it to the board, then run monitor tool to view serial output: ``` -make -j4 flash monitor +idf.py -p PORT flash monitor ``` - Wait for WiFi to connect to your access point From 3e753f5e2de3889772f727c27c550319a6be4e59 Mon Sep 17 00:00:00 2001 From: Anton Maklakov Date: Tue, 16 Jul 2019 16:33:30 +0700 Subject: [PATCH 087/289] tools: Mass fixing of empty prototypes (for -Wstrict-prototypes) * Original commit: espressif/esp-idf@afbaf74007e89d016dbade4072bf2e7a3874139a --- components/mdns/include/mdns.h | 6 +-- components/mdns/include/mdns_console.h | 2 +- components/mdns/mdns.c | 30 +++++++------- components/mdns/mdns_console.c | 40 +++++++++---------- components/mdns/mdns_networking.c | 6 +-- .../mdns/test_afl_fuzz_host/esp32_compat.h | 2 +- .../mdns/test_afl_fuzz_host/esp32_mock.c | 4 +- .../mdns/test_afl_fuzz_host/esp32_mock.h | 2 +- components/mdns/test_afl_fuzz_host/mdns_di.h | 2 +- components/mdns/test_afl_fuzz_host/test.c | 4 +- .../protocol_examples_common/connect.c | 16 ++++---- .../include/protocol_examples_common.h | 6 +-- .../protocol_examples_common/stdin_out.c | 2 +- .../protocols/mdns/main/mdns_example_main.c | 6 +-- 14 files changed, 64 insertions(+), 64 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 4370969d7..a30534640 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -85,13 +85,13 @@ typedef struct mdns_result_s { * - ESP_ERR_NO_MEM on memory error * - ESP_FAIL when failed to start mdns task */ -esp_err_t mdns_init(); +esp_err_t mdns_init(void); /** * @brief Stop and free mDNS server * */ -void mdns_free(); +void mdns_free(void); /** * @brief Set the hostname for mDNS server @@ -235,7 +235,7 @@ esp_err_t mdns_service_txt_item_remove(const char * service_type, const char * p * - ESP_OK success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t mdns_service_remove_all(); +esp_err_t mdns_service_remove_all(void); /** * @brief Query mDNS for host or service diff --git a/components/mdns/include/mdns_console.h b/components/mdns/include/mdns_console.h index 5c8b0b5a4..059e03de5 100644 --- a/components/mdns/include/mdns_console.h +++ b/components/mdns/include/mdns_console.h @@ -17,6 +17,6 @@ /** * @brief Register MDNS functions with the console component */ -void mdns_console_register(); +void mdns_console_register(void); #endif /* _MDNS_CONSOLE_H_ */ diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 92909e2de..7331353d2 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -32,7 +32,7 @@ static const char *TAG = "MDNS"; static volatile TaskHandle_t _mdns_service_task_handle = NULL; static SemaphoreHandle_t _mdns_service_semaphore = NULL; -static void _mdns_search_finish_done(); +static void _mdns_search_finish_done(void); static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * search, mdns_name_t * name, uint16_t type, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, ip_addr_t * ip, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); @@ -1010,7 +1010,7 @@ static void _mdns_schedule_tx_packet(mdns_tx_packet_t * packet, uint32_t ms_afte /** * @brief free all packets scheduled for sending */ -static void _mdns_clear_tx_queue_head() +static void _mdns_clear_tx_queue_head(void) { mdns_tx_packet_t * q; while (_mdns_server->tx_queue_head) { @@ -1699,7 +1699,7 @@ static void _mdns_send_final_bye(bool include_ip) /** * @brief Stop the responder on all services without instance */ -static void _mdns_send_bye_all_pcbs_no_instance() +static void _mdns_send_bye_all_pcbs_no_instance(void) { size_t srv_count = 0; mdns_srv_item_t * a = _mdns_server->services; @@ -1727,7 +1727,7 @@ static void _mdns_send_bye_all_pcbs_no_instance() /** * @brief Restart the responder on all services without instance */ -static void _mdns_restart_all_pcbs_no_instance() +static void _mdns_restart_all_pcbs_no_instance(void) { size_t srv_count = 0; mdns_srv_item_t * a = _mdns_server->services; @@ -1755,7 +1755,7 @@ static void _mdns_restart_all_pcbs_no_instance() /** * @brief Restart the responder on all active PCBs */ -static void _mdns_restart_all_pcbs() +static void _mdns_restart_all_pcbs(void) { _mdns_clear_tx_queue_head(); size_t srv_count = 0; @@ -3209,7 +3209,7 @@ static void _mdns_search_add(mdns_search_once_t * search) /** * @brief Called from parser to finish any searches that have reached maximum results */ -static void _mdns_search_finish_done() +static void _mdns_search_finish_done(void) { mdns_search_once_t * search = _mdns_server->search_once; mdns_search_once_t * s = NULL; @@ -3931,7 +3931,7 @@ static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_o * if it is scheduled to be transmitted, then pushes the packet to action queue to be handled. * */ -static void _mdns_scheduler_run() +static void _mdns_scheduler_run(void) { MDNS_SERVICE_LOCK(); mdns_tx_packet_t * p = _mdns_server->tx_queue_head; @@ -3966,7 +3966,7 @@ static void _mdns_scheduler_run() /** * @brief Called from timer task to run active searches */ -static void _mdns_search_run() +static void _mdns_search_run(void) { MDNS_SERVICE_LOCK(); mdns_search_once_t * s = _mdns_server->search_once; @@ -4025,7 +4025,7 @@ static void _mdns_timer_cb(void * arg) _mdns_search_run(); } -static esp_err_t _mdns_start_timer(){ +static esp_err_t _mdns_start_timer(void){ esp_timer_create_args_t timer_conf = { .callback = _mdns_timer_cb, .arg = NULL, @@ -4039,7 +4039,7 @@ static esp_err_t _mdns_start_timer(){ return esp_timer_start_periodic(_mdns_server->timer_handle, MDNS_TIMER_PERIOD_US); } -static esp_err_t _mdns_stop_timer(){ +static esp_err_t _mdns_stop_timer(void){ esp_err_t err = ESP_OK; if (_mdns_server->timer_handle) { err = esp_timer_stop(_mdns_server->timer_handle); @@ -4058,7 +4058,7 @@ static esp_err_t _mdns_stop_timer(){ * - ESP_OK on success * - ESP_FAIL on error */ -static esp_err_t _mdns_service_task_start() +static esp_err_t _mdns_service_task_start(void) { if (!_mdns_service_semaphore) { _mdns_service_semaphore = xSemaphoreCreateMutex(); @@ -4091,7 +4091,7 @@ static esp_err_t _mdns_service_task_start() * @return * - ESP_OK */ -static esp_err_t _mdns_service_task_stop() +static esp_err_t _mdns_service_task_stop(void) { _mdns_stop_timer(); if (_mdns_service_task_handle) { @@ -4146,7 +4146,7 @@ static void event_handler(void* arg, esp_event_base_t event_base, } } -esp_err_t mdns_init() +esp_err_t mdns_init(void) { esp_err_t err = ESP_OK; @@ -4222,7 +4222,7 @@ free_server: return err; } -void mdns_free() +void mdns_free(void) { uint8_t i, j; if (!_mdns_server) { @@ -4571,7 +4571,7 @@ esp_err_t mdns_service_remove(const char * service, const char * proto) return ESP_OK; } -esp_err_t mdns_service_remove_all() +esp_err_t mdns_service_remove_all(void) { if (!_mdns_server) { return ESP_ERR_INVALID_ARG; diff --git a/components/mdns/mdns_console.c b/components/mdns/mdns_console.c index 17bffa55b..adbbf0b8f 100644 --- a/components/mdns/mdns_console.c +++ b/components/mdns/mdns_console.c @@ -99,7 +99,7 @@ static int cmd_mdns_query_a(int argc, char** argv) return 0; } -static void register_mdns_query_a() +static void register_mdns_query_a(void) { mdns_query_a_args.hostname = arg_str1(NULL, NULL, "", "Hostname that is searched for"); mdns_query_a_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); @@ -156,7 +156,7 @@ static int cmd_mdns_query_aaaa(int argc, char** argv) return 0; } -static void register_mdns_query_aaaa() +static void register_mdns_query_aaaa(void) { mdns_query_a_args.hostname = arg_str1(NULL, NULL, "", "Hostname that is searched for"); mdns_query_a_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); @@ -215,7 +215,7 @@ static int cmd_mdns_query_srv(int argc, char** argv) return 0; } -static void register_mdns_query_srv() +static void register_mdns_query_srv(void) { mdns_query_srv_args.instance = arg_str1(NULL, NULL, "", "Instance to search for"); mdns_query_srv_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); @@ -277,7 +277,7 @@ static int cmd_mdns_query_txt(int argc, char** argv) return 0; } -static void register_mdns_query_txt() +static void register_mdns_query_txt(void) { mdns_query_txt_args.instance = arg_str1(NULL, NULL, "", "Instance to search for"); mdns_query_txt_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); @@ -343,7 +343,7 @@ static int cmd_mdns_query_ptr(int argc, char** argv) return 0; } -static void register_mdns_query_ptr() +static void register_mdns_query_ptr(void) { mdns_query_ptr_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); mdns_query_ptr_args.proto = arg_str1(NULL, NULL, "", "Protocol to search for (_tcp, _udp, etc.)"); @@ -412,7 +412,7 @@ static int cmd_mdns_query_ip(int argc, char** argv) return 0; } -static void register_mdns_query_ip() +static void register_mdns_query_ip(void) { mdns_query_ip_args.hostname = arg_str1(NULL, NULL, "", "Hostname that is searched for"); mdns_query_ip_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); @@ -479,7 +479,7 @@ static int cmd_mdns_query_svc(int argc, char** argv) return 0; } -static void register_mdns_query_svc() +static void register_mdns_query_svc(void) { mdns_query_svc_args.instance = arg_str1(NULL, NULL, "", "Instance to search for"); mdns_query_svc_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); @@ -528,7 +528,7 @@ static int cmd_mdns_init(int argc, char** argv) return 0; } -static void register_mdns_init() +static void register_mdns_init(void) { mdns_init_args.hostname = arg_str0("h", "hostname", "", "Hostname that the server will advertise"); mdns_init_args.instance = arg_str0("i", "instance", "", "Default instance name for services"); @@ -551,7 +551,7 @@ static int cmd_mdns_free(int argc, char** argv) return 0; } -static void register_mdns_free() +static void register_mdns_free(void) { const esp_console_cmd_t cmd_free = { .command = "mdns_free", @@ -586,7 +586,7 @@ static int cmd_mdns_set_hostname(int argc, char** argv) return 0; } -static void register_mdns_set_hostname() +static void register_mdns_set_hostname(void) { mdns_set_hostname_args.hostname = arg_str1(NULL, NULL, "", "Hostname that the server will advertise"); mdns_set_hostname_args.end = arg_end(2); @@ -624,7 +624,7 @@ static int cmd_mdns_set_instance(int argc, char** argv) return 0; } -static void register_mdns_set_instance() +static void register_mdns_set_instance(void) { mdns_set_instance_args.instance = arg_str1(NULL, NULL, "", "Default instance name for services"); mdns_set_instance_args.end = arg_end(2); @@ -733,7 +733,7 @@ static int cmd_mdns_service_add(int argc, char** argv) return 0; } -static void register_mdns_service_add() +static void register_mdns_service_add(void) { mdns_add_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); mdns_add_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); @@ -776,7 +776,7 @@ static int cmd_mdns_service_remove(int argc, char** argv) return 0; } -static void register_mdns_service_remove() +static void register_mdns_service_remove(void) { mdns_remove_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); mdns_remove_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); @@ -817,7 +817,7 @@ static int cmd_mdns_service_instance_set(int argc, char** argv) return 0; } -static void register_mdns_service_instance_set() +static void register_mdns_service_instance_set(void) { mdns_service_instance_set_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); mdns_service_instance_set_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); @@ -858,7 +858,7 @@ static int cmd_mdns_service_port_set(int argc, char** argv) { return 0; } -static void register_mdns_service_port_set() +static void register_mdns_service_port_set(void) { mdns_service_port_set_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); mdns_service_port_set_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); @@ -910,7 +910,7 @@ static int cmd_mdns_service_txt_replace(int argc, char** argv) return 0; } -static void register_mdns_service_txt_replace() +static void register_mdns_service_txt_replace(void) { mdns_txt_replace_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); mdns_txt_replace_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); @@ -953,7 +953,7 @@ static int cmd_mdns_service_txt_set(int argc, char** argv) return 0; } -static void register_mdns_service_txt_set() +static void register_mdns_service_txt_set(void) { mdns_txt_set_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); mdns_txt_set_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); @@ -996,7 +996,7 @@ static int cmd_mdns_service_txt_remove(int argc, char** argv) return 0; } -static void register_mdns_service_txt_remove() +static void register_mdns_service_txt_remove(void) { mdns_txt_remove_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); mdns_txt_remove_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); @@ -1020,7 +1020,7 @@ static int cmd_mdns_service_remove_all(int argc, char** argv) return 0; } -static void register_mdns_service_remove_all() +static void register_mdns_service_remove_all(void) { const esp_console_cmd_t cmd_free = { .command = "mdns_service_remove_all", @@ -1033,7 +1033,7 @@ static void register_mdns_service_remove_all() ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_free) ); } -void mdns_console_register() +void mdns_console_register(void) { register_mdns_init(); register_mdns_free(); diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index bb3400f0a..ac69b093d 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -23,7 +23,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip /** * @brief Low level UDP PCB Initialize */ -static esp_err_t _udp_pcb_main_init() +static esp_err_t _udp_pcb_main_init(void) { if(_pcb_main) { return ESP_OK; @@ -47,7 +47,7 @@ static esp_err_t _udp_pcb_main_init() /** * @brief Low level UDP PCB Free */ -static void _udp_pcb_main_deinit() +static void _udp_pcb_main_deinit(void) { if(_pcb_main){ udp_recv(_pcb_main, NULL, NULL); @@ -177,7 +177,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip /** * @brief Check if any of the interfaces is up */ -static bool _udp_pcb_is_in_use(){ +static bool _udp_pcb_is_in_use(void){ int i, p; for (i=0; i Date: Fri, 11 Jan 2019 09:40:34 +0100 Subject: [PATCH 088/289] mdns: mdns_service_remove_all doesn't take an argument Merges https://github.com/espressif/esp-idf/pull/2937 * Original commit: espressif/esp-idf@c2764f6fe85681cfaf5dbbe168295284f09c09cd --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 7331353d2..095651634 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4228,7 +4228,7 @@ void mdns_free(void) if (!_mdns_server) { return; } - mdns_service_remove_all(_mdns_server); + mdns_service_remove_all(); _mdns_service_task_stop(); for (i=0; i Date: Thu, 20 Jun 2019 17:27:29 +0200 Subject: [PATCH 089/289] mdns: fix missing bye packet if services removed with mdns_service_remove_all() or mdns_free() Closes https://github.com/espressif/esp-idf/issues/3660 * Original commit: espressif/esp-idf@a001998d5283b29ca9a374adf7cef3357b39a03a --- components/mdns/mdns.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 095651634..4bf5bce4a 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1676,9 +1676,7 @@ static void _mdns_send_final_bye(bool include_ip) size_t srv_count = 0; mdns_srv_item_t * a = _mdns_server->services; while (a) { - if (!a->service->instance) { - srv_count++; - } + srv_count++; a = a->next; } if (!srv_count) { @@ -1688,9 +1686,7 @@ static void _mdns_send_final_bye(bool include_ip) size_t i = 0; a = _mdns_server->services; while (a) { - if (!a->service->instance) { - services[i++] = a; - } + services[i++] = a; a = a->next; } _mdns_send_bye(services, srv_count, include_ip); @@ -1699,7 +1695,7 @@ static void _mdns_send_final_bye(bool include_ip) /** * @brief Stop the responder on all services without instance */ -static void _mdns_send_bye_all_pcbs_no_instance(void) +static void _mdns_send_bye_all_pcbs_no_instance(bool include_ip) { size_t srv_count = 0; mdns_srv_item_t * a = _mdns_server->services; @@ -1721,7 +1717,7 @@ static void _mdns_send_bye_all_pcbs_no_instance(void) } a = a->next; } - _mdns_send_bye(services, srv_count, false); + _mdns_send_bye(services, srv_count, include_ip); } /** @@ -3728,14 +3724,14 @@ static void _mdns_execute_action(mdns_action_t * action) action->data.sys_event.event_id, action->data.sys_event.interface); break; case ACTION_HOSTNAME_SET: - _mdns_send_final_bye(true); + _mdns_send_bye_all_pcbs_no_instance(true); free((char*)_mdns_server->hostname); _mdns_server->hostname = action->data.hostname; _mdns_restart_all_pcbs(); break; case ACTION_INSTANCE_SET: - _mdns_send_bye_all_pcbs_no_instance(); + _mdns_send_bye_all_pcbs_no_instance(false); free((char*)_mdns_server->instance); _mdns_server->instance = action->data.instance; _mdns_restart_all_pcbs_no_instance(); From c70d527d8091edaa96974d2b58daf09f4992d348 Mon Sep 17 00:00:00 2001 From: liu zhifu Date: Fri, 5 Jul 2019 16:58:04 +0800 Subject: [PATCH 090/289] esp_wifi: wifi support new event mechanism 1. WiFi support new event mechanism 2. Update examples to use new event mechanism * Original commit: espressif/esp-idf@003a9872b7de69d799e9d37521cfbcaff9b37e85 --- components/mdns/include/mdns.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index a30534640..1ffa312c0 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -354,7 +354,7 @@ esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, ip6_addr_t * * @param ctx The system event context * @param event The system event */ -esp_err_t mdns_handle_system_event(void *ctx, system_event_t *event); +esp_err_t mdns_handle_system_event(void *ctx, system_event_t *event) __attribute__((deprecated)); #ifdef __cplusplus } From 28d5b74a0045ebeec846008dae25017b7ccc4311 Mon Sep 17 00:00:00 2001 From: suda-morris <362953310@qq.com> Date: Wed, 18 Sep 2019 18:28:55 +0800 Subject: [PATCH 091/289] ethernet: update spi-ethernet api * Original commit: espressif/esp-idf@546ac64a9e98b56d7014d33bb98ee976f9dc7d38 --- .../common_components/protocol_examples_common/connect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 8ee8aea9d..38d68a3a5 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -219,9 +219,9 @@ static void start(void) .queue_size = 20 }; ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle)); - /* dm9051 ethernet driver is based on spi driver, so need to specify the spi handle */ - mac_config.spi_hdl = spi_handle; - s_mac = esp_eth_mac_new_dm9051(&mac_config); + /* dm9051 ethernet driver is based on spi driver */ + eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle); + s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); s_phy = esp_eth_phy_new_dm9051(&phy_config); #endif esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy); From 0582187b9a358fc9509db9040029114ca67c9048 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 7 Oct 2019 16:46:25 +0200 Subject: [PATCH 092/289] examples: gracefully shut down Wi-Fi before restart This fixes the issue that if Wi-Fi is stopped from a shutdown handler, the code in connect.c tries to reconnect, and fails because Wi-Fi is already stopped. Also make the error check in connect.c less strict. * Original commit: espressif/esp-idf@28a440521e9f6c6f6c5cec5f583fb32bdc41fd97 --- .../protocol_examples_common/connect.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 38d68a3a5..36e5326eb 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -73,6 +73,7 @@ esp_err_t example_connect(void) } s_connect_event_group = xEventGroupCreate(); start(); + ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop)); xEventGroupWaitBits(s_connect_event_group, CONNECTED_BITS, true, true, portMAX_DELAY); ESP_LOGI(TAG, "Connected to %s", s_connection_name); ESP_LOGI(TAG, "IPv4 address: " IPSTR, IP2STR(&s_ip_addr)); @@ -101,7 +102,11 @@ static void on_wifi_disconnect(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect..."); - ESP_ERROR_CHECK(esp_wifi_connect()); + esp_err_t err = esp_wifi_connect(); + if (err == ESP_ERR_WIFI_NOT_STARTED) { + return; + } + ESP_ERROR_CHECK(err); } #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 @@ -149,7 +154,11 @@ static void stop(void) ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6)); ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect)); #endif - ESP_ERROR_CHECK(esp_wifi_stop()); + esp_err_t err = esp_wifi_stop(); + if (err == ESP_ERR_WIFI_NOT_INIT) { + return; + } + ESP_ERROR_CHECK(err); ESP_ERROR_CHECK(esp_wifi_deinit()); } #endif // CONFIG_EXAMPLE_CONNECT_WIFI From 286c6467253e8481b8c0871b5e70f418c7c0bf01 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 24 Sep 2019 12:12:58 +0200 Subject: [PATCH 093/289] mdns: use constant size of AAAA answer in mdns packets instead of deriving from lwip struct size, since the struct could contain also zones closes WIFI-771 * Original commit: espressif/esp-idf@e5e31c5d0172d68fd207fa31cc5d3bba82dad020 --- components/mdns/mdns.c | 18 +++++++++++------- components/mdns/private_include/mdns_private.h | 1 + 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 4bf5bce4a..b34452ba0 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -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"; @@ -734,11 +738,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 +821,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; } @@ -2185,7 +2189,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) { @@ -2197,7 +2201,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); @@ -2898,7 +2902,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) { @@ -4934,7 +4938,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; diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index ed7e89cb8..3c495dd82 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -52,6 +52,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 From 7dfe14c83dd969ce049f74b68ee7b7b4d65b0915 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 1 Oct 2019 18:50:34 +0200 Subject: [PATCH 094/289] ethernet: support OpenCores ethernet MAC OpenCores Ethernet MAC has a relatively simple interface, and is already supported in QEMU. This makes it a good candidate for enabling network support when running IDF apps in QEMU, compared to the relatively more complex task of writing a QEMU model of ESP32 EMAC. This driver is written with QEMU in mind: it does not implement or handle things that aren't implemented or handled in the QEMU model: error flags, error interrupts. The transmit part of the driver also assumes that the TX operation is done immediately when the TX descriptor is written (which is the case with QEMU), hence waiting for the TX operation to complete is not necessary. For simplicity, the driver assumes that the peripheral register occupy the same memory range as the ESP32 EMAC registers, and the same interrupt source number is used. * Original commit: espressif/esp-idf@31dac92e5f0daac98190fd603df213a0a25a3807 --- .../protocol_examples_common/Kconfig.projbuild | 11 +++++++++++ .../protocol_examples_common/connect.c | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index f5d288e9a..e1fee9b61 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -49,6 +49,17 @@ menu "Example Connection Configuration" select ETH_USE_SPI_ETHERNET help Select external SPI-Ethernet module. + + config EXAMPLE_USE_OPENETH + bool "OpenCores Ethernet MAC (EXPERIMENTAL)" + select ETH_USE_OPENETH + help + When this option is enabled, the example is built with support for + OpenCores Ethernet MAC, which allows testing the example in QEMU. + Note that this option is used for internal testing purposes, and + not officially supported. Examples built with this option enabled + will not run on a real ESP32 chip. + endchoice if EXAMPLE_USE_INTERNAL_ETHERNET diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 36e5326eb..1c6bd98d1 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -232,7 +232,12 @@ static void start(void) eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle); s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); s_phy = esp_eth_phy_new_dm9051(&phy_config); +#elif CONFIG_EXAMPLE_USE_OPENETH + phy_config.autonego_timeout_ms = 100; + s_mac = esp_eth_mac_new_openeth(&mac_config); + s_phy = esp_eth_phy_new_dp83848(&phy_config); #endif + esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy); ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle)); s_connection_name = "Ethernet"; From f44c5694228eebebe25720aeadbc6157c8635314 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 8 Oct 2019 19:53:56 +0200 Subject: [PATCH 095/289] mdns: fix possible race condition when checking DHCP status on WIFI_EVENT_STA_CONNECTED event. tcpip_adapter_dhcpc_get_status() returns the actual internal value of dhcp client without any locking or TCP/IP stack context call, so when CONNECTED event fired with default settings it started DHCP client in TCP/IP stack context and at the same time mdns event handler checking actual DHCP state, which could still be INIT (not STARTED). Purpose of this check is to enable PCB if DHCP was stopped before setting network interface up (typically static IP settings), so the solutin is to check against TCPIP_ADAPTER_DHCP_STOPPED state * Original commit: espressif/esp-idf@7f410a0bcbafa85dba05807c53c3c38999506509 --- components/mdns/mdns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index b34452ba0..d4a68963c 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3062,7 +3062,7 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, switch(event_id) { case WIFI_EVENT_STA_CONNECTED: if (!tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &dcst)) { - if (dcst != TCPIP_ADAPTER_DHCP_STARTED) { + if (dcst == TCPIP_ADAPTER_DHCP_STOPPED) { _mdns_enable_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V4); } } @@ -3085,7 +3085,7 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, switch (event_id) { case ETHERNET_EVENT_CONNECTED: if (!tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_ETH, &dcst)) { - if (dcst != TCPIP_ADAPTER_DHCP_STARTED) { + if (dcst == TCPIP_ADAPTER_DHCP_STOPPED) { _mdns_enable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V4); } } From d8d6b355539f400bd38260772c746990e894359b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 19 Jun 2019 13:20:58 +0200 Subject: [PATCH 096/289] mdns: updated example test to exercise also hostnames resolved by lwip gethostbyname and getaddrinfo * Original commit: espressif/esp-idf@f3cb91ef717b5044bfd36ed449dd2f37aca1b07a --- .../protocols/mdns/main/mdns_example_main.c | 49 +++++++++ examples/protocols/mdns/mdns_example_test.py | 101 +++++++++++------- examples/protocols/mdns/sdkconfig.ci | 1 + 3 files changed, 112 insertions(+), 39 deletions(-) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index a406b74d1..003c8e784 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -29,6 +29,11 @@ static const char *TAG = "mdns-test"; static char* generate_hostname(void); +#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 +static void query_mdns_host_with_gethostbyname(char * host); +static void query_mdns_host_with_getaddrinfo(char * host); +#endif + static void initialise_mdns(void) { char* hostname = generate_hostname(); @@ -168,6 +173,8 @@ static void mdns_example_task(void *pvParameters) #if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 /* Send initial queries that are started by CI tester */ query_mdns_host("tinytester"); + query_mdns_host_with_gethostbyname("tinytester-lwip.local"); + query_mdns_host_with_getaddrinfo("tinytester-lwip.local"); #endif while(1) { @@ -211,3 +218,45 @@ static char* generate_hostname(void) return hostname; #endif } + +#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 +/** + * @brief Executes gethostbyname and displays list of resolved addresses. + * Note: This function is used only to test advertised mdns hostnames resolution + */ +static void query_mdns_host_with_gethostbyname(char * host) +{ + struct hostent *res = gethostbyname(host); + if (res) { + unsigned int i = 0; + while (res->h_addr_list[i] != NULL) { + ESP_LOGI(TAG, "gethostbyname: %s resolved to: %s", host, inet_ntoa(*(struct in_addr *) (res->h_addr_list[i]))); + i++; + } + } +} + +/** + * @brief Executes getaddrinfo and displays list of resolved addresses. + * Note: This function is used only to test advertised mdns hostnames resolution + */ +static void query_mdns_host_with_getaddrinfo(char * host) +{ + struct addrinfo hints; + struct addrinfo * res; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if (!getaddrinfo(host, NULL, &hints, &res)) { + while (res) { + ESP_LOGI(TAG, "getaddrinfo: %s resolved to: %s", host, + res->ai_family == AF_INET? + inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr): + inet_ntoa(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr)); + res = res->ai_next; + } + } +} +#endif \ No newline at end of file diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index cb527989a..a06623fcc 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -6,7 +6,7 @@ import time import struct import dpkt import dpkt.dns -from threading import Thread +from threading import Thread, Event # this is a test case write with tiny-test-fw. @@ -24,52 +24,78 @@ except ImportError: import DUT -g_run_server = True -g_done = False +# g_run_server = True +# g_done = False +stop_mdns_server = Event() +esp_answered = Event() + + +def get_dns_query_for_esp(esp_host): + dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') + dns.qd[0].name = esp_host + u'.local' + print("Created query for esp host: {} ".format(dns.__repr__())) + return dns.pack() + + +def get_dns_answer_to_mdns(tester_host): + dns = dpkt.dns.DNS(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA + dns.rcode = dpkt.dns.DNS_RCODE_NOERR + arr = dpkt.dns.DNS.RR() + arr.cls = dpkt.dns.DNS_IN + arr.type = dpkt.dns.DNS_A + arr.name = tester_host + arr.ip = socket.inet_aton('127.0.0.1') + dns. an.append(arr) + print("Created answer to mdns query: {} ".format(dns.__repr__())) + return dns.pack() + + +def get_dns_answer_to_mdns_lwip(tester_host, id): + dns = dpkt.dns.DNS(b"\x5e\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x0a\x64\x61\x76\x69\x64" + b"\x2d\x63\x6f\x6d\x70\x05\x6c\x6f\x63\x61\x6c\x00\x00\x01\x00\x01\xc0\x0c" + b"\x00\x01\x00\x01\x00\x00\x00\x0a\x00\x04\xc0\xa8\x0a\x6c") + dns.qd[0].name = tester_host + dns.an[0].name = tester_host + dns.an[0].ip = socket.inet_aton('127.0.0.1') + dns.an[0].rdata = socket.inet_aton('127.0.0.1') + dns.id = id + print("Created answer to mdns (lwip) query: {} ".format(dns.__repr__())) + return dns.pack() def mdns_server(esp_host): - global g_done + global esp_answered UDP_IP = "0.0.0.0" UDP_PORT = 5353 MCAST_GRP = '224.0.0.251' + TESTER_NAME = u'tinytester.local' + TESTER_NAME_LWIP = u'tinytester-lwip.local' sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) sock.bind((UDP_IP,UDP_PORT)) mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) - dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') sock.settimeout(30) - resp_dns = dpkt.dns.DNS(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') - resp_dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA - resp_dns.rcode = dpkt.dns.DNS_RCODE_NOERR - arr = dpkt.dns.DNS.RR() - arr.cls = dpkt.dns.DNS_IN - arr.type = dpkt.dns.DNS_A - arr.name = u'tinytester.local' - arr.ip = socket.inet_aton('127.0.0.1') - resp_dns. an.append(arr) - sock.sendto(resp_dns.pack(),(MCAST_GRP,UDP_PORT)) - while g_run_server: + while not stop_mdns_server.is_set(): try: - m = sock.recvfrom(1024) - dns = dpkt.dns.DNS(m[0]) + if not esp_answered.is_set(): + sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT)) + time.sleep(0.2) + data, addr = sock.recvfrom(1024) + dns = dpkt.dns.DNS(data) if len(dns.qd) > 0 and dns.qd[0].type == dpkt.dns.DNS_A: - if dns.qd[0].name == u'tinytester.local': - print(dns.__repr__(),dns.qd[0].name) - sock.sendto(resp_dns.pack(),(MCAST_GRP,UDP_PORT)) + if dns.qd[0].name == TESTER_NAME: + print("Received query: {} ".format(dns.__repr__())) + sock.sendto(get_dns_answer_to_mdns(TESTER_NAME), (MCAST_GRP,UDP_PORT)) + elif dns.qd[0].name == TESTER_NAME_LWIP: + print("Received query: {} ".format(dns.__repr__())) + sock.sendto(get_dns_answer_to_mdns_lwip(TESTER_NAME_LWIP, dns.id), addr) if len(dns.an) > 0 and dns.an[0].type == dpkt.dns.DNS_A: if dns.an[0].name == esp_host + u'.local': - print("Received answer esp32-mdns query") - g_done = True - print(dns.an[0].name) - dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') - dns.qd[0].name = esp_host + u'.local' - sock.sendto(dns.pack(),(MCAST_GRP,UDP_PORT)) - print("Sending esp32-mdns query") - time.sleep(0.5) - sock.sendto(resp_dns.pack(),(MCAST_GRP,UDP_PORT)) + print("Received answer to esp32-mdns query: {}".format(dns.__repr__())) + esp_answered.set() except socket.timeout: break except dpkt.UnpackError: @@ -78,7 +104,7 @@ def mdns_server(esp_host): @IDF.idf_example_test(env_tag="Example_WIFI") def test_examples_protocol_mdns(env, extra_data): - global g_run_server + global stop_mdns_server """ steps: | 1. join AP + init mdns example @@ -102,22 +128,19 @@ def test_examples_protocol_mdns(env, extra_data): try: dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) except DUT.ExpectTimeout: - g_run_server = False + stop_mdns_server.set() thread1.join() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') # 3. check the mdns name is accessible - start = time.time() - while (time.time() - start) <= 60: - if g_done: - break - time.sleep(0.5) - if g_done is False: + if not esp_answered.wait(timeout=30): raise ValueError('Test has failed: did not receive mdns answer within timeout') # 4. check DUT output if mdns advertized host is resolved try: dut1.expect(re.compile(r"mdns-test: Query A: tinytester.local resolved to: 127.0.0.1"), timeout=30) + dut1.expect(re.compile(r"mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) + dut1.expect(re.compile(r"mdns-test: getaddrinfo: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) finally: - g_run_server = False + stop_mdns_server.set() thread1.join() diff --git a/examples/protocols/mdns/sdkconfig.ci b/examples/protocols/mdns/sdkconfig.ci index 13b56273e..60158c45c 100644 --- a/examples/protocols/mdns/sdkconfig.ci +++ b/examples/protocols/mdns/sdkconfig.ci @@ -1,2 +1,3 @@ CONFIG_MDNS_RESOLVE_TEST_SERVICES=y CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y \ No newline at end of file From f6ff165be9440b46d537ed9ff8be95b98c7574ba Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Thu, 24 Oct 2019 16:41:53 +0800 Subject: [PATCH 097/289] mdns: fix crash for hostname queries Receiving TXT, PTR, SDPTR and SRV record type queries would crash the application if the hostname was used as instance name. Closes https://github.com/espressif/esp-idf/issues/4224 * Original commit: espressif/esp-idf@3d1170031b340a231949fdc0d9c46d87af0d1b5d --- components/mdns/mdns.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index d4a68963c..0392b1fce 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -445,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; @@ -489,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"; @@ -534,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; @@ -602,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; @@ -1151,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; From 901124b7ee08c02862e2ce0c406acab091489082 Mon Sep 17 00:00:00 2001 From: suda-morris <362953310@qq.com> Date: Thu, 6 Jun 2019 10:57:29 +0800 Subject: [PATCH 098/289] build and link hello-world for esp32s2beta * Original commit: espressif/esp-idf@84b2f9f14d16533c84db2210f13a24cd817e0b0a --- components/mdns/mdns.c | 18 ++++++++++++++---- .../mdns/private_include/mdns_networking.h | 4 +++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 0392b1fce..24c2f4b57 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3098,7 +3098,9 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, default: break; } - } else if (event_base == ETH_EVENT) { + } +#if CONFIG_IDF_TARGET_ESP32 + else if (event_base == ETH_EVENT) { switch (event_id) { case ETHERNET_EVENT_CONNECTED: if (!tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_ETH, &dcst)) { @@ -3114,15 +3116,19 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, default: break; } - } else if (event_base == IP_EVENT) { + } +#endif + 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; +#if CONFIG_IDF_TARGET_ESP32 case IP_EVENT_ETH_GOT_IP: _mdns_enable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V4); break; +#endif case IP_EVENT_GOT_IP6: _mdns_enable_pcb(interface, MDNS_IP_PROTOCOL_V6); _mdns_announce_pcb(interface, MDNS_IP_PROTOCOL_V4, NULL, 0, true); @@ -4189,17 +4195,17 @@ esp_err_t mdns_init(void) err = ESP_ERR_NO_MEM; 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; } +#if CONFIG_IDF_TARGET_ESP32 if ((err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)) != ESP_OK) { goto free_event_handlers; } - +#endif uint8_t i; ip6_addr_t tmp_addr6; tcpip_adapter_ip_info_t if_ip_info; @@ -4229,7 +4235,9 @@ free_all_and_disable_pcbs: 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); +#if CONFIG_IDF_TARGET_ESP32 esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler); +#endif vQueueDelete(_mdns_server->action_queue); free_lock: vSemaphoreDelete(_mdns_server->lock); @@ -4277,7 +4285,9 @@ void mdns_free(void) vSemaphoreDelete(_mdns_server->lock); esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler); esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler); +#if CONFIG_IDF_TARGET_ESP32 esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler); +#endif free(_mdns_server); _mdns_server = NULL; } diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h index 1d13e308f..174022dfd 100644 --- a/components/mdns/private_include/mdns_networking.h +++ b/components/mdns/private_include/mdns_networking.h @@ -3,7 +3,7 @@ /* * MDNS Server Networking -- private include - * + * */ #include "mdns.h" #include "mdns_private.h" @@ -21,7 +21,9 @@ #include "esp_system.h" #include "esp_timer.h" #include "esp_event.h" +#if CONFIG_IDF_TARGET_ESP32 #include "esp_eth.h" +#endif /** From 67d310b988b5523a456275fdaa84d653be2e7403 Mon Sep 17 00:00:00 2001 From: Xia Xiaotian Date: Mon, 17 Jun 2019 11:50:37 +0800 Subject: [PATCH 099/289] run WiFi on ESP32SBETA * Original commit: espressif/esp-idf@99ef587a05e24fad18fe66398df86f3a9e5929e5 --- .../protocol_examples_common/Kconfig.projbuild | 2 ++ examples/common_components/protocol_examples_common/connect.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index e1fee9b61..0e6997983 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -142,6 +142,8 @@ menu "Example Connection Configuration" config EXAMPLE_CONNECT_IPV6 bool "Obtain IPv6 link-local address" + depends on IDF_TARGET_ESP32 + # ToDo: remove once IPV6 is supported on esp32s2 default y help By default, examples will wait until IPv4 and IPv6 addresses are obtained. diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 1c6bd98d1..0e9b6a5ea 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -12,7 +12,9 @@ #include "sdkconfig.h" #include "esp_event.h" #include "esp_wifi.h" +#if CONFIG_EXAMPLE_CONNECT_ETHERNET #include "esp_eth.h" +#endif #include "esp_log.h" #include "tcpip_adapter.h" #include "freertos/FreeRTOS.h" From d52dddfea57bcd934f778af33608c7e810381e34 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Thu, 29 Aug 2019 17:54:14 +0800 Subject: [PATCH 100/289] ci: limit example test to ESP32s * Original commit: espressif/esp-idf@63329b169bd1a3bc153bf37a7187f4ea17012852 --- examples/protocols/mdns/mdns_example_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index a06623fcc..e86b84e42 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -16,6 +16,7 @@ from threading import Thread, Event try: import IDF + from IDF.IDFDUT import ESP32DUT except ImportError: test_fw_path = os.getenv("TEST_FW_PATH") if test_fw_path and test_fw_path not in sys.path: @@ -112,7 +113,7 @@ def test_examples_protocol_mdns(env, extra_data): 3. check the mdns name is accessible 4. check DUT output if mdns advertized host is resolved """ - dut1 = env.get_dut("mdns-test", "examples/protocols/mdns") + dut1 = env.get_dut("mdns-test", "examples/protocols/mdns", dut_class=ESP32DUT) # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "mdns-test.bin") bin_size = os.path.getsize(binary_file) From 248b11bb0abc3b3d7b977b2e5e23ac7fb31d6a96 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 3 Oct 2019 10:52:53 +0200 Subject: [PATCH 101/289] esp_event, mdns: fixes for CONFIG_ETH_ENABLED=n * Original commit: espressif/esp-idf@569ad7545c32a2f1d0eff3f1e81df70fb76ad125 --- components/mdns/mdns.c | 10 +++++----- components/mdns/private_include/mdns_networking.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 24c2f4b57..8ee6b5d91 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3099,7 +3099,7 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, break; } } -#if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_ETH_ENABLED else if (event_base == ETH_EVENT) { switch (event_id) { case ETHERNET_EVENT_CONNECTED: @@ -3124,7 +3124,7 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, _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; -#if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_ETH_ENABLED case IP_EVENT_ETH_GOT_IP: _mdns_enable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V4); break; @@ -4201,7 +4201,7 @@ esp_err_t mdns_init(void) if ((err = esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)) != ESP_OK) { goto free_event_handlers; } -#if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_ETH_ENABLED if ((err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)) != ESP_OK) { goto free_event_handlers; } @@ -4235,7 +4235,7 @@ free_all_and_disable_pcbs: 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); -#if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_ETH_ENABLED esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler); #endif vQueueDelete(_mdns_server->action_queue); @@ -4285,7 +4285,7 @@ void mdns_free(void) vSemaphoreDelete(_mdns_server->lock); esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler); esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler); -#if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_ETH_ENABLED esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler); #endif free(_mdns_server); diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h index 174022dfd..6b32ec7f1 100644 --- a/components/mdns/private_include/mdns_networking.h +++ b/components/mdns/private_include/mdns_networking.h @@ -21,7 +21,7 @@ #include "esp_system.h" #include "esp_timer.h" #include "esp_event.h" -#if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_ETH_ENABLED #include "esp_eth.h" #endif From 3cc64469c163c5b240c98a1453df283ce8e541b3 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 20 Aug 2019 14:40:34 +0200 Subject: [PATCH 102/289] examples: removed ip4addr_ntoa and used prefered IP2STR for displaying IP addresses * Original commit: espressif/esp-idf@ec9f245dd35d3e8e7b19a8dec5e05e003dc21f39 --- components/mdns/test/test_mdns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/mdns/test/test_mdns.c b/components/mdns/test/test_mdns.c index 6ae5e835f..9e1e50dc4 100644 --- a/components/mdns/test/test_mdns.c +++ b/components/mdns/test/test_mdns.c @@ -73,8 +73,8 @@ TEST_CASE("mdns api return expected err-code and do not leak memory", "[mdns][le 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; + esp_ip6_addr_t addr6; + esp_ip4_addr_t addr4; test_case_uses_tcpip(); TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); From 53e2aa3241d6408b76e442cde7a16236e520d95b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 28 Jun 2019 16:47:34 +0200 Subject: [PATCH 103/289] esp_netif: Introduction of esp-netif component as a replacement of tcpip_adpter - provides object oriented access to network intefaces - not limited to default netifs - more generic abstraction to network input output functions - event handler registration removed from component responsibility - backward compatibility layer for legacy tcpip_apapter APIs Closes IDF-39 * Original commit: espressif/esp-idf@ffe043b1a81a0f9e1cc2cfa8873e21318ec89143 --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 8ee6b5d91..31d0a96ce 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4161,7 +4161,7 @@ static void event_handler(void* arg, esp_event_base_t 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; + action->data.sys_event.interface = tcpip_adapter_if_from_esp_netif(event->esp_netif); } if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { From 879a6cdfa30f232b10a17aa0bb8adab4794e8ac5 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Sat, 31 Aug 2019 16:08:46 +0200 Subject: [PATCH 104/289] examples: common component initialization code to use new esp_netif instead of tcpip_adapter * Original commit: espressif/esp-idf@21464465ea1468de4d57a57392df399d96c5df1c --- .../protocol_examples_common/CMakeLists.txt | 4 +- .../protocol_examples_common/connect.c | 58 +++++++++++++++---- .../include/protocol_examples_common.h | 11 +++- 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/examples/common_components/protocol_examples_common/CMakeLists.txt b/examples/common_components/protocol_examples_common/CMakeLists.txt index 0ccb219b4..7c4ebe34d 100644 --- a/examples/common_components/protocol_examples_common/CMakeLists.txt +++ b/examples/common_components/protocol_examples_common/CMakeLists.txt @@ -1,2 +1,4 @@ idf_component_register(SRCS "connect.c" "stdin_out.c" - INCLUDE_DIRS "include") + INCLUDE_DIRS "include" + PRIV_REQUIRES esp_netif + ) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 0e9b6a5ea..b261e0b4f 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -16,7 +16,7 @@ #include "esp_eth.h" #endif #include "esp_log.h" -#include "tcpip_adapter.h" +#include "esp_netif.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" @@ -33,11 +33,12 @@ #endif static EventGroupHandle_t s_connect_event_group; -static ip4_addr_t s_ip_addr; +static esp_ip4_addr_t s_ip_addr; static const char *s_connection_name; +static esp_netif_t *s_example_esp_netif = NULL; #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 -static ip6_addr_t s_ipv6_addr; +static esp_ip6_addr_t s_ipv6_addr; #endif static const char *TAG = "example_connect"; @@ -51,6 +52,7 @@ static void stop(void); static void on_got_ip(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { + ESP_LOGI(TAG, "Got IP event!"); ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr)); xEventGroupSetBits(s_connect_event_group, GOT_IPV4_BIT); @@ -61,6 +63,7 @@ static void on_got_ip(void *arg, esp_event_base_t event_base, static void on_got_ipv6(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { + ESP_LOGI(TAG, "Got IPv6 event!"); ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data; memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); @@ -76,6 +79,7 @@ esp_err_t example_connect(void) s_connect_event_group = xEventGroupCreate(); start(); ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop)); + ESP_LOGI(TAG, "Waiting for IP"); xEventGroupWaitBits(s_connect_event_group, CONNECTED_BITS, true, true, portMAX_DELAY); ESP_LOGI(TAG, "Connected to %s", s_connection_name); ESP_LOGI(TAG, "IPv4 address: " IPSTR, IP2STR(&s_ip_addr)); @@ -113,10 +117,10 @@ static void on_wifi_disconnect(void *arg, esp_event_base_t event_base, #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 -static void on_wifi_connect(void *arg, esp_event_base_t event_base, +static void on_wifi_connect(void *esp_netif, esp_event_base_t event_base, int32_t event_id, void *event_data) { - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); + esp_netif_create_ip6_linklocal(esp_netif); } #endif // CONFIG_EXAMPLE_CONNECT_IPV6 @@ -126,10 +130,20 @@ static void start(void) wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_WIFI_STA(); + + esp_netif_t* netif = esp_netif_new(&netif_config); + + assert(netif); + + esp_wifi_set_default_wifi_sta_handlers(netif); + + s_example_esp_netif = netif; + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL)); ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL)); #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 - ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect, netif)); ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL)); #endif @@ -162,6 +176,9 @@ static void stop(void) } ESP_ERROR_CHECK(err); ESP_ERROR_CHECK(esp_wifi_deinit()); + + esp_netif_destroy(s_example_esp_netif); + s_example_esp_netif = NULL; } #endif // CONFIG_EXAMPLE_CONNECT_WIFI @@ -170,13 +187,13 @@ static void stop(void) #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 /** Event handler for Ethernet events */ -static void on_eth_event(void *arg, esp_event_base_t event_base, +static void on_eth_event(void *esp_netif, esp_event_base_t event_base, int32_t event_id, void *event_data) { switch (event_id) { case ETHERNET_EVENT_CONNECTED: ESP_LOGI(TAG, "Ethernet Link Up"); - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_ETH); + esp_netif_create_ip6_linklocal(esp_netif); break; default: break; @@ -191,10 +208,19 @@ static esp_eth_phy_t *s_phy = NULL; static void start(void) { - ESP_ERROR_CHECK(tcpip_adapter_set_default_eth_handlers()); + esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_ETH(); + + esp_netif_t* netif = esp_netif_new(&netif_config); + + assert(netif); + + ESP_ERROR_CHECK(esp_eth_set_default_handlers(netif)); + + s_example_esp_netif = netif; + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL)); #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 - ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif)); ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL)); #endif eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); @@ -241,7 +267,10 @@ static void start(void) #endif esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy); + ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle)); + + esp_netif_attach(netif, s_eth_handle); s_connection_name = "Ethernet"; } @@ -255,6 +284,15 @@ static void stop(void) ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle)); ESP_ERROR_CHECK(s_phy->del(s_phy)); ESP_ERROR_CHECK(s_mac->del(s_mac)); + + esp_eth_clear_default_handlers(s_example_esp_netif); + esp_netif_destroy(s_example_esp_netif); + s_example_esp_netif = NULL; } #endif // CONFIG_EXAMPLE_CONNECT_ETHERNET + +esp_netif_t *get_example_netif(void) +{ + return s_example_esp_netif; +} \ No newline at end of file diff --git a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h index d4f6e1fbb..98f67e348 100644 --- a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h +++ b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h @@ -14,14 +14,14 @@ extern "C" { #endif #include "esp_err.h" -#include "tcpip_adapter.h" +#include "esp_netif.h" #ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET -#define EXAMPLE_INTERFACE TCPIP_ADAPTER_IF_ETH +#define EXAMPLE_INTERFACE get_example_netif() #endif #ifdef CONFIG_EXAMPLE_CONNECT_WIFI -#define EXAMPLE_INTERFACE TCPIP_ADAPTER_IF_STA +#define EXAMPLE_INTERFACE get_example_netif() #endif /** @@ -54,6 +54,11 @@ esp_err_t example_disconnect(void); */ esp_err_t example_configure_stdin_stdout(void); +/** + * @brief Returns esp-netif pointer created by example_connect() + * + */ +esp_netif_t *get_example_netif(void); #ifdef __cplusplus } #endif From dfcefc38fddf5f22208b990cbd1ab820c0a454cb Mon Sep 17 00:00:00 2001 From: David Cermak Date: Sat, 31 Aug 2019 16:19:21 +0200 Subject: [PATCH 105/289] examples: protocol examples which use common connection component updated to use esp_netif_init instead of tcpip_adapter in initialization code * Original commit: espressif/esp-idf@a49b934ef895690f2b5e3709340db856e27475e2 --- examples/protocols/mdns/main/mdns_example_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 003c8e784..76cb3b1b6 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -186,7 +186,7 @@ static void mdns_example_task(void *pvParameters) void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); - tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); initialise_mdns(); From 48b819bbc1ec7f7ca386f5a2b2099939685b70b0 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Sat, 31 Aug 2019 19:06:54 +0200 Subject: [PATCH 106/289] mdns: update mdns to use esp-netif for mdns supported services such as STA, AP, ETH removes also include dependency on lwip to use esp_netif defined address fields and structures * Original commit: espressif/esp-idf@19e24fe61ed5ea6698dfd5e1f427e783360aa846 --- components/mdns/CMakeLists.txt | 2 +- components/mdns/include/mdns.h | 18 +- components/mdns/mdns.c | 269 +++++++++++------- components/mdns/mdns_console.c | 6 +- components/mdns/mdns_networking.c | 48 ++-- .../mdns/private_include/mdns_networking.h | 6 +- .../mdns/private_include/mdns_private.h | 30 +- .../protocols/mdns/main/mdns_example_main.c | 11 +- 8 files changed, 226 insertions(+), 164 deletions(-) diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 7b744dde5..15b0d40f8 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -3,5 +3,5 @@ idf_component_register(SRCS "mdns.c" "mdns_networking.c" INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "private_include" - REQUIRES lwip mbedtls console tcpip_adapter) + REQUIRES lwip mbedtls console esp_netif) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 1ffa312c0..5e93d2fc2 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -18,7 +18,7 @@ extern "C" { #endif -#include +#include #include "esp_event.h" #define MDNS_TYPE_A 0x0001 @@ -52,17 +52,25 @@ typedef struct { * @brief mDNS query linked list IP item */ typedef struct mdns_ip_addr_s { - ip_addr_t addr; /*!< IP address */ + esp_ip_addr_t addr; /*!< IP address */ struct mdns_ip_addr_s * next; /*!< next IP, or NULL for the last IP in the list */ } mdns_ip_addr_t; +typedef enum mdns_if_internal { + MDNS_IF_STA = 0, + MDNS_IF_AP = 1, + MDNS_IF_ETH = 2, + MDNS_IF_MAX +} mdns_if_t; + /** * @brief mDNS query result structure */ typedef struct mdns_result_s { struct mdns_result_s * next; /*!< next result, or NULL for the last result in the list */ - tcpip_adapter_if_t tcpip_if; /*!< interface on which the result came (AP/STA/ETH) */ + mdns_if_t tcpip_if; /*!< interface index */ + mdns_ip_protocol_t ip_protocol; /*!< ip_protocol type of the interface (v4/v6) */ // PTR char * instance_name; /*!< instance name */ @@ -329,7 +337,7 @@ esp_err_t mdns_query_txt(const char * instance_name, const char * service_type, * - ESP_ERR_NO_MEM memory error * - ESP_ERR_INVALID_ARG parameter error */ -esp_err_t mdns_query_a(const char * host_name, uint32_t timeout, ip4_addr_t * addr); +esp_err_t mdns_query_a(const char * host_name, uint32_t timeout, esp_ip4_addr_t * addr); /** * @brief Query mDNS for A record @@ -344,7 +352,7 @@ esp_err_t mdns_query_a(const char * host_name, uint32_t timeout, ip4_addr_t * ad * - ESP_ERR_NO_MEM memory error * - ESP_ERR_INVALID_ARG parameter error */ -esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, ip6_addr_t * addr); +esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, esp_ip6_addr_t * addr); /** * @brief System event handler diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 31d0a96ce..cb5f86ea0 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -37,11 +37,42 @@ static volatile TaskHandle_t _mdns_service_task_handle = NULL; static SemaphoreHandle_t _mdns_service_semaphore = NULL; static void _mdns_search_finish_done(void); -static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * search, mdns_name_t * name, uint16_t type, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, ip_addr_t * ip, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * search, mdns_name_t * name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, esp_ip_addr_t * ip, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/* + * @brief Internal collection of mdns supported interfaces + * + */ +static esp_netif_t * s_esp_netifs[MDNS_IF_MAX] = {}; + +/* + * @brief Convert mnds if to esp-netif handle + */ +esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) +{ + if (tcpip_if < MDNS_IF_MAX) { + return s_esp_netifs[tcpip_if]; + } + return NULL; +} + +/* + * @brief Convert esp-netif handle to mnds if + */ +static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *interface) +{ + for (int i=0; iinterfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP @@ -833,7 +864,7 @@ static bool _mdns_if_is_dup(tcpip_adapter_if_t tcpip_if) /** * @brief Check if IPv6 address is NULL */ -static bool _ipv6_address_is_zero(ip6_addr_t ip6) +static bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) { uint8_t i; uint8_t * data = (uint8_t *)ip6.addr; @@ -850,7 +881,7 @@ static bool _ipv6_address_is_zero(ip6_addr_t ip6) * * @return number of answers added to the packet */ -static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_answer_t * answer, tcpip_adapter_if_t tcpip_if) +static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_answer_t * answer, mdns_if_t tcpip_if) { if (answer->type == MDNS_TYPE_PTR) { @@ -871,11 +902,11 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ } else if (answer->type == MDNS_TYPE_SDPTR) { return _mdns_append_sdptr_record(packet, index, answer->service, answer->flush, answer->bye) > 0; } else if (answer->type == MDNS_TYPE_A) { - tcpip_adapter_ip_info_t if_ip_info; + esp_netif_ip_info_t if_ip_info; if (!_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state != PCB_DUP) { return 0; } - if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info)) { + if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { return 0; } if (_mdns_append_a_record(packet, index, if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { @@ -884,8 +915,8 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ if (!_mdns_if_is_dup(tcpip_if)) { return 1; } - tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); - if (tcpip_adapter_get_ip_info(other_if, &if_ip_info)) { + mdns_if_t other_if = _mdns_get_other_if (tcpip_if); + if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &if_ip_info)) { return 1; } if (_mdns_append_a_record(packet, index, if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { @@ -893,11 +924,11 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ } return 1; } else if (answer->type == MDNS_TYPE_AAAA) { - struct ip6_addr if_ip6; + struct esp_ip6_addr if_ip6; if (!_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state != PCB_DUP) { return 0; } - if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &if_ip6)) { + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(tcpip_if), &if_ip6)) { return 0; } if (_ipv6_address_is_zero(if_ip6)) { @@ -909,8 +940,8 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ if (!_mdns_if_is_dup(tcpip_if)) { return 1; } - tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); - if (tcpip_adapter_get_ip6_linklocal(other_if, &if_ip6)) { + mdns_if_t other_if = _mdns_get_other_if (tcpip_if); + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &if_ip6)) { return 1; } if (_mdns_append_aaaa_record(packet, index, (uint8_t*)if_ip6.addr, answer->flush, answer->bye) > 0) { @@ -1046,7 +1077,7 @@ static void _mdns_clear_tx_queue_head(void) * @param tcpip_if the interface * @param ip_protocol pcb type V4/V6 */ -static void _mdns_clear_pcb_tx_queue_head(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_tx_packet_t * q, * p; while (_mdns_server->tx_queue_head && _mdns_server->tx_queue_head->tcpip_if == tcpip_if && _mdns_server->tx_queue_head->ip_protocol == ip_protocol) { @@ -1074,7 +1105,7 @@ static void _mdns_clear_pcb_tx_queue_head(tcpip_adapter_if_t tcpip_if, mdns_ip_p * @param tcpip_if the interface * @param ip_protocol pcb type V4/V6 */ -static mdns_tx_packet_t * _mdns_get_next_pcb_packet(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static mdns_tx_packet_t * _mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_tx_packet_t * q = _mdns_server->tx_queue_head; while (q) { @@ -1089,7 +1120,7 @@ static mdns_tx_packet_t * _mdns_get_next_pcb_packet(tcpip_adapter_if_t tcpip_if, /** * @brief Find, remove and free answer from the scheduled packets */ -static void _mdns_remove_scheduled_answer(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t * service) +static void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t * service) { mdns_srv_item_t s = {NULL, NULL}; if (!service) { @@ -1178,7 +1209,7 @@ static bool _mdns_alloc_answer(mdns_out_answer_t ** destnation, uint16_t type, m /** * @brief Allocate new packet for sending */ -static mdns_tx_packet_t * _mdns_alloc_packet_default(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static mdns_tx_packet_t * _mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_tx_packet_t * packet = (mdns_tx_packet_t*)malloc(sizeof(mdns_tx_packet_t)); if (!packet) { @@ -1192,8 +1223,8 @@ static mdns_tx_packet_t * _mdns_alloc_packet_default(tcpip_adapter_if_t tcpip_if if (ip_protocol == MDNS_IP_PROTOCOL_V4) { IP_ADDR4(&packet->dst, 224, 0, 0, 251); } else { - ip_addr_t addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); - memcpy(&packet->dst, &addr, sizeof(ip_addr_t)); + esp_ip_addr_t addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); + memcpy(&packet->dst, &addr, sizeof(esp_ip_addr_t)); } return packet; } @@ -1275,7 +1306,7 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed q = q->next; } if (unicast || !send_flush) { - memcpy(&packet->dst, &parsed_packet->src, sizeof(ip_addr_t)); + memcpy(&packet->dst, &parsed_packet->src, sizeof(esp_ip_addr_t)); packet->port = parsed_packet->src_port; } @@ -1309,7 +1340,7 @@ static bool _mdns_question_exists(mdns_out_question_t * needle, mdns_out_questio /** * @brief Create probe packet for particular services on particular PCB */ -static mdns_tx_packet_t * _mdns_create_probe_packet(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t * services[], size_t len, bool first, bool include_ip) +static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t * services[], size_t len, bool first, bool include_ip) { mdns_tx_packet_t * packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); if (!packet) { @@ -1385,7 +1416,7 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(tcpip_adapter_if_t tcpip_if, /** * @brief Create announce packet for particular services on particular PCB */ -static mdns_tx_packet_t * _mdns_create_announce_packet(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t * services[], size_t len, bool include_ip) +static mdns_tx_packet_t * _mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t * services[], size_t len, bool include_ip) { mdns_tx_packet_t * packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); if (!packet) { @@ -1451,7 +1482,7 @@ static mdns_tx_packet_t * _mdns_create_announce_from_probe(mdns_tx_packet_t * pr /** * @brief Send by for particular services on particular PCB */ -static void _mdns_pcb_send_bye(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool include_ip) +static void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool include_ip) { mdns_tx_packet_t * packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); if (!packet) { @@ -1476,7 +1507,7 @@ static void _mdns_pcb_send_bye(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t i /** * @brief Send probe for additional services on particular PCB */ -static void _mdns_init_pcb_probe_new_service(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) +static void _mdns_init_pcb_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) { mdns_pcb_t * pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; size_t services_final_len = len; @@ -1532,7 +1563,7 @@ static void _mdns_init_pcb_probe_new_service(tcpip_adapter_if_t tcpip_if, mdns_i * - If pcb probing then add only non-probing services and restarts probing * - If pcb not probing, run probing for all specified services */ -static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) +static void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool probe_ip) { mdns_pcb_t * pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; @@ -1572,7 +1603,7 @@ static void _mdns_init_pcb_probe(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t /** * @brief Restart the responder on particular PCB */ -static void _mdns_restart_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { size_t srv_count = 0; mdns_srv_item_t * a = _mdns_server->services; @@ -1600,10 +1631,10 @@ static void _mdns_send_bye(mdns_srv_item_t ** services, size_t len, bool include return; } - for (i=0; iinterfaces[i].pcbs[j].pcb && _mdns_server->interfaces[i].pcbs[j].state == PCB_RUNNING) { - _mdns_pcb_send_bye((tcpip_adapter_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); + _mdns_pcb_send_bye((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); } } } @@ -1612,7 +1643,7 @@ static void _mdns_send_bye(mdns_srv_item_t ** services, size_t len, bool include /** * @brief Send announcement on particular PCB */ -static void _mdns_announce_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool include_ip) +static void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t ** services, size_t len, bool include_ip) { mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; size_t i; @@ -1659,7 +1690,7 @@ static void _mdns_announce_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t i static void _mdns_probe_all_pcbs(mdns_srv_item_t ** services, size_t len, bool probe_ip, bool clear_old_probe) { uint8_t i, j; - for (i=0; iinterfaces[i].pcbs[j].pcb) { mdns_pcb_t * _pcb = &_mdns_server->interfaces[i].pcbs[j]; @@ -1669,7 +1700,7 @@ static void _mdns_probe_all_pcbs(mdns_srv_item_t ** services, size_t len, bool p _pcb->probe_services_len = 0; _pcb->probe_running = false; } - _mdns_init_pcb_probe((tcpip_adapter_if_t)i, (mdns_ip_protocol_t)j, services, len, probe_ip); + _mdns_init_pcb_probe((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, probe_ip); } } } @@ -1681,9 +1712,9 @@ static void _mdns_probe_all_pcbs(mdns_srv_item_t ** services, size_t len, bool p static void _mdns_announce_all_pcbs(mdns_srv_item_t ** services, size_t len, bool include_ip) { uint8_t i, j; - for (i=0; iinterfaces[other_if].pcbs[i].pcb) { //stop this interface and mark as dup @@ -2161,27 +2192,27 @@ static void _mdns_dup_interface(tcpip_adapter_if_t tcpip_if) /** * @brief Detect IPv4 address collision */ -static int _mdns_check_a_collision(ip4_addr_t * ip, tcpip_adapter_if_t tcpip_if) +static int _mdns_check_a_collision(esp_ip4_addr_t * ip, mdns_if_t tcpip_if) { - tcpip_adapter_ip_info_t if_ip_info; - tcpip_adapter_ip_info_t other_ip_info; + esp_netif_ip_info_t if_ip_info; + esp_netif_ip_info_t other_ip_info; if (!ip->addr) { return 1;//denial! they win } - if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info)) { + if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { return 1;//they win } - int ret = memcmp((uint8_t*)&if_ip_info.ip.addr, (uint8_t*)&ip->addr, sizeof(ip4_addr_t)); + int ret = memcmp((uint8_t*)&if_ip_info.ip.addr, (uint8_t*)&ip->addr, sizeof(esp_ip4_addr_t)); if (ret > 0) { return -1;//we win } else if (ret < 0) { //is it the other interface? - tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); - if (other_if == TCPIP_ADAPTER_IF_MAX) { + mdns_if_t other_if = _mdns_get_other_if (tcpip_if); + if (other_if == MDNS_IF_MAX) { return 1;//AP interface! They win } - if (tcpip_adapter_get_ip_info(other_if, &other_ip_info)) { + if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &other_ip_info)) { return 1;//IPv4 not active! They win } if (ip->addr != other_ip_info.ip.addr) { @@ -2196,14 +2227,14 @@ static int _mdns_check_a_collision(ip4_addr_t * ip, tcpip_adapter_if_t tcpip_if) /** * @brief Detect IPv6 address collision */ -static int _mdns_check_aaaa_collision(ip6_addr_t * ip, tcpip_adapter_if_t tcpip_if) +static int _mdns_check_aaaa_collision(esp_ip6_addr_t * ip, mdns_if_t tcpip_if) { - struct ip6_addr if_ip6; - struct ip6_addr other_ip6; + struct esp_ip6_addr if_ip6; + struct esp_ip6_addr other_ip6; if (_ipv6_address_is_zero(*ip)) { return 1;//denial! they win } - if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &if_ip6)) { + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(tcpip_if), &if_ip6)) { return 1;//they win } int ret = memcmp((uint8_t*)&if_ip6.addr, (uint8_t*)ip->addr, _MDNS_SIZEOF_IP6_ADDR); @@ -2211,11 +2242,11 @@ static int _mdns_check_aaaa_collision(ip6_addr_t * ip, tcpip_adapter_if_t tcpip_ return -1;//we win } else if (ret < 0) { //is it the other interface? - tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); - if (other_if == TCPIP_ADAPTER_IF_MAX) { + mdns_if_t other_if = _mdns_get_other_if (tcpip_if); + if (other_if == MDNS_IF_MAX) { return 1;//AP interface! They win } - if (tcpip_adapter_get_ip6_linklocal(other_if, &other_ip6)) { + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &other_ip6)) { return 1;//IPv6 not active! They win } if (memcmp((uint8_t*)&other_ip6.addr, (uint8_t*)ip->addr, _MDNS_SIZEOF_IP6_ADDR)) { @@ -2917,7 +2948,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } } else if (type == MDNS_TYPE_AAAA) {//ipv6 - ip_addr_t ip6; + esp_ip_addr_t ip6; ip6.type = IPADDR_TYPE_V6; memcpy(ip6.u_addr.ip6.addr, data_ptr, MDNS_ANSWER_AAAA_SIZE); if (search_result) { @@ -2963,7 +2994,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } } else if (type == MDNS_TYPE_A) { - ip_addr_t ip; + esp_ip_addr_t ip; ip.type = IPADDR_TYPE_V4; memcpy(&(ip.u_addr.ip4.addr), data_ptr, 4); if (search_result) { @@ -3037,7 +3068,7 @@ clear_rx_packet: /** * @brief Enable mDNS interface */ -void _mdns_enable_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +void _mdns_enable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { if (!_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) { if (_mdns_pcb_init(tcpip_if, ip_protocol)) { @@ -3050,13 +3081,13 @@ void _mdns_enable_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protoco /** * @brief Disable mDNS interface */ -void _mdns_disable_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) { _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); _mdns_pcb_deinit(tcpip_if, ip_protocol); - tcpip_adapter_if_t other_if = _mdns_get_other_if (tcpip_if); - if (other_if != TCPIP_ADAPTER_IF_MAX && _mdns_server->interfaces[other_if].pcbs[ip_protocol].state == PCB_DUP) { + mdns_if_t other_if = _mdns_get_other_if (tcpip_if); + if (other_if != MDNS_IF_MAX && _mdns_server->interfaces[other_if].pcbs[ip_protocol].state == PCB_DUP) { _mdns_server->interfaces[other_if].pcbs[ip_protocol].state = PCB_OFF; _mdns_enable_pcb(other_if, ip_protocol); } @@ -3068,32 +3099,41 @@ void _mdns_disable_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protoc * @brief Dispatch interface changes based on system events */ static void _mdns_handle_system_event(esp_event_base_t event_base, - int32_t event_id, tcpip_adapter_if_t interface) + int32_t event_id, esp_netif_t* interface) { if (!_mdns_server) { return; } - tcpip_adapter_dhcp_status_t dcst; + // Initialize handles to esp-netif if appropriate mdns supported interface started + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + s_esp_netifs[MDNS_IF_STA] = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_START) { + s_esp_netifs[MDNS_IF_AP] = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); + } else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_START) { + s_esp_netifs[MDNS_IF_ETH] = esp_netif_get_handle_from_ifkey("ETH_DEF"); + } + + esp_netif_dhcp_status_t dcst; 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); + if (!esp_netif_dhcpc_get_status(_mdns_get_esp_netif(MDNS_IF_STA), &dcst)) { + if (dcst == ESP_NETIF_DHCP_STOPPED) { + _mdns_enable_pcb(MDNS_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); + _mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + _mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6); break; case WIFI_EVENT_AP_START: - _mdns_enable_pcb(TCPIP_ADAPTER_IF_AP, MDNS_IP_PROTOCOL_V4); + _mdns_enable_pcb(MDNS_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); + _mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); + _mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V6); break; default: break; @@ -3103,15 +3143,15 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, else if (event_base == ETH_EVENT) { switch (event_id) { case ETHERNET_EVENT_CONNECTED: - if (!tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_ETH, &dcst)) { - if (dcst == TCPIP_ADAPTER_DHCP_STOPPED) { - _mdns_enable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V4); + if (!esp_netif_dhcpc_get_status(_mdns_get_esp_netif(MDNS_IF_ETH), &dcst)) { + if (dcst == ESP_NETIF_DHCP_STOPPED) { + _mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); } } break; case ETHERNET_EVENT_DISCONNECTED: - _mdns_disable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V4); - _mdns_disable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V6); + _mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + _mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V6); break; default: break; @@ -3121,17 +3161,21 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, 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); + _mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + _mdns_announce_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6, NULL, 0, true); break; #if CONFIG_ETH_ENABLED case IP_EVENT_ETH_GOT_IP: - _mdns_enable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V4); + _mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); break; #endif case IP_EVENT_GOT_IP6: - _mdns_enable_pcb(interface, MDNS_IP_PROTOCOL_V6); - _mdns_announce_pcb(interface, MDNS_IP_PROTOCOL_V4, NULL, 0, true); + { + mdns_if_t mdns_if = _mdns_get_if_from_esp_netif(interface); + _mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); + _mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4, NULL, 0, true); + + } break; default: break; @@ -3248,7 +3292,7 @@ static void _mdns_search_finish_done(void) /** * @brief Create linked IP (copy) from parsed one */ -static mdns_ip_addr_t * _mdns_result_addr_create_ip(ip_addr_t * ip) +static mdns_ip_addr_t * _mdns_result_addr_create_ip(esp_ip_addr_t * ip) { mdns_ip_addr_t * a = (mdns_ip_addr_t *)malloc(sizeof(mdns_ip_addr_t)); if (!a) { @@ -3268,7 +3312,7 @@ static mdns_ip_addr_t * _mdns_result_addr_create_ip(ip_addr_t * ip) /** * @brief Chain new IP to search result */ -static void _mdns_result_add_ip(mdns_result_t * r, ip_addr_t * ip) +static void _mdns_result_add_ip(mdns_result_t * r, esp_ip_addr_t * ip) { mdns_ip_addr_t * a = r->addr; while (a) { @@ -3293,7 +3337,7 @@ static void _mdns_result_add_ip(mdns_result_t * r, ip_addr_t * ip) /** * @brief Called from parser to add A/AAAA data to search result */ -static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, ip_addr_t * ip, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, esp_ip_addr_t * ip, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_result_t * r = NULL; mdns_ip_addr_t * a = NULL; @@ -3346,7 +3390,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * /** * @brief Called from parser to add PTR data to search result */ -static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_result_t * r = search->result; while (r) { @@ -3382,7 +3426,7 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, /** * @brief Called from parser to add SRV data to search result */ -static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_result_t * r = search->result; while (r) { @@ -3416,7 +3460,7 @@ static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char /** * @brief Called from parser to add TXT data to search result */ -static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { int i; mdns_result_t * r = search->result; @@ -3460,7 +3504,7 @@ free_txt: /** * @brief Called from packet parser to find matching running search */ -static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * s, mdns_name_t * name, uint16_t type, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * s, mdns_name_t * name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_result_t * r = NULL; while (s) { @@ -3530,7 +3574,7 @@ static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * s, mdns_ /** * @brief Create search packet for partidular interface */ -static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_result_t * r = NULL; mdns_tx_packet_t * packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); @@ -3586,7 +3630,7 @@ static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search /** * @brief Send search packet to particular interface */ -static void _mdns_search_send_pcb(mdns_search_once_t * search, tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_search_send_pcb(mdns_search_once_t * search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_tx_packet_t * packet = NULL; if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb && _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state > PCB_INIT) { @@ -3621,9 +3665,9 @@ static void _mdns_search_send(mdns_search_once_t * search) } uint8_t i, j; - for (i=0; idata.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 = tcpip_adapter_if_from_esp_netif(event->esp_netif); + action->data.sys_event.interface = event->esp_netif; } if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { @@ -4207,14 +4251,14 @@ esp_err_t mdns_init(void) } #endif uint8_t i; - ip6_addr_t tmp_addr6; - tcpip_adapter_ip_info_t if_ip_info; + esp_ip6_addr_t tmp_addr6; + esp_netif_ip_info_t if_ip_info; - for (i=0; i>>>>>> mdns: update mdns to use esp-netif for mdns supported services such as STA, AP, ETH _mdns_dbg_printf(IPV6STR "\n", IPV62STR(ip6)); } else if (type == MDNS_TYPE_A) { - ip4_addr_t ip; - memcpy(&ip, data_ptr, sizeof(ip4_addr_t)); + esp_ip4_addr_t ip; + memcpy(&ip, data_ptr, sizeof(esp_ip4_addr_t)); _mdns_dbg_printf(IPSTR "\n", IP2STR(&ip)); } else if (type == MDNS_TYPE_NSEC) { const uint8_t * old_ptr = data_ptr; diff --git a/components/mdns/mdns_console.c b/components/mdns/mdns_console.c index adbbf0b8f..2c36a6aee 100644 --- a/components/mdns/mdns_console.c +++ b/components/mdns/mdns_console.c @@ -42,7 +42,7 @@ static void mdns_print_results(mdns_result_t * results) } a = r->addr; while (a) { - if (a->addr.type == IPADDR_TYPE_V6) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); } else { printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); @@ -81,7 +81,7 @@ static int cmd_mdns_query_a(int argc, char** argv) printf("Query A: %s.local, Timeout: %d\n", hostname, timeout); - struct ip4_addr addr; + struct esp_ip4_addr addr; addr.addr = 0; esp_err_t err = mdns_query_a(hostname, timeout, &addr); @@ -138,7 +138,7 @@ static int cmd_mdns_query_aaaa(int argc, char** argv) printf("Query AAAA: %s.local, Timeout: %d\n", hostname, timeout); - struct ip6_addr addr; + struct esp_ip6_addr addr; memset(addr.addr, 0, 16); esp_err_t err = mdns_query_aaaa(hostname, timeout, &addr); diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index ac69b093d..5f900cf4d 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -6,6 +6,7 @@ #include #include "mdns_networking.h" #include "esp_log.h" +#include "esp_netif_net_stack.h" extern mdns_server_t * _mdns_server; @@ -60,21 +61,18 @@ static void _udp_pcb_main_deinit(void) /** * @brief Low level UDP Multicast membership control */ -static esp_err_t _udp_join_group(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, bool join) +static esp_err_t _udp_join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protocol, bool join) { struct netif * netif = NULL; - void * nif = NULL; + esp_netif_t *tcpip_if = _mdns_get_esp_netif(if_inx); - if (!tcpip_adapter_is_netif_up(tcpip_if)) { + if (!esp_netif_is_netif_up(tcpip_if)) { // Network interface went down before event propagated, skipping IGMP config return ESP_ERR_INVALID_STATE; } - esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif); - if (err) { - return ESP_ERR_INVALID_ARG; - } - netif = (struct netif *)nif; + netif = esp_netif_get_netif_impl(tcpip_if); + assert(netif); if (ip_protocol == MDNS_IP_PROTOCOL_V4) { ip_addr_t multicast_addr; @@ -126,7 +124,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip continue; } - packet->tcpip_if = TCPIP_ADAPTER_IF_MAX; + packet->tcpip_if = MDNS_IF_MAX; packet->pb = this_pb; packet->src_port = rport; memcpy(&packet->src, raddr, sizeof(ip_addr_t)); @@ -145,12 +143,10 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces) struct netif * netif = NULL; - void * nif = NULL; struct udp_pcb * pcb = NULL; - for (i=0; iinterfaces[i].pcbs[packet->ip_protocol].pcb; - tcpip_adapter_get_netif (i, &nif); - netif = (struct netif *)nif; + netif = esp_netif_get_netif_impl(_mdns_get_esp_netif(i)); if (pcb && netif && netif == ip_current_input_netif ()) { if (packet->src.type == IPADDR_TYPE_V4) { if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) { @@ -179,7 +175,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip */ static bool _udp_pcb_is_in_use(void){ int i, p; - for (i=0; iinterfaces[i].pcbs[p].pcb){ return true; @@ -192,7 +188,7 @@ static bool _udp_pcb_is_in_use(void){ /** * @brief Stop PCB Main code */ -static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _udp_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { if (!_mdns_server) { return; @@ -217,7 +213,7 @@ static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_p /** * @brief Start PCB Main code */ -static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static esp_err_t _udp_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) { return ESP_ERR_INVALID_STATE; @@ -240,7 +236,7 @@ static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t i typedef struct { struct tcpip_api_call_data call; - tcpip_adapter_if_t tcpip_if; + mdns_if_t tcpip_if; mdns_ip_protocol_t ip_protocol; struct pbuf *pbt; const ip_addr_t *ip; @@ -274,7 +270,7 @@ static err_t _mdns_pcb_deinit_api(struct tcpip_api_call_data *api_call_msg) * - _mdns prefixed * - commented in mdns_networking.h header */ -esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_api_call_t msg = { .tcpip_if = tcpip_if, @@ -284,7 +280,7 @@ esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_prot return msg.err; } -esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_api_call_t msg = { .tcpip_if = tcpip_if, @@ -299,19 +295,19 @@ static err_t _mdns_udp_pcb_write_api(struct tcpip_api_call_data *api_call_msg) void * nif = NULL; mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; mdns_pcb_t * _pcb = &_mdns_server->interfaces[msg->tcpip_if].pcbs[msg->ip_protocol]; - esp_err_t err = tcpip_adapter_get_netif(msg->tcpip_if, &nif); - if (err) { + nif = esp_netif_get_netif_impl(_mdns_get_esp_netif(msg->tcpip_if)); + if (!nif) { pbuf_free(msg->pbt); - msg->err = err; - return err; + msg->err = ERR_IF; + return ERR_IF; } - err = udp_sendto_if (_pcb->pcb, msg->pbt, msg->ip, msg->port, (struct netif *)nif); + esp_err_t err = udp_sendto_if (_pcb->pcb, msg->pbt, msg->ip, msg->port, (struct netif *)nif); pbuf_free(msg->pbt); msg->err = err; return err; } -size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len) +size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len) { struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); if (pbt == NULL) { @@ -323,7 +319,7 @@ size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_pr .tcpip_if = tcpip_if, .ip_protocol = ip_protocol, .pbt = pbt, - .ip = ip, + .ip = (ip_addr_t *)ip, .port = port }; tcpip_api_call(_mdns_udp_pcb_write_api, &msg.call); diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h index 6b32ec7f1..12316f9ed 100644 --- a/components/mdns/private_include/mdns_networking.h +++ b/components/mdns/private_include/mdns_networking.h @@ -34,12 +34,12 @@ esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet); /** * @brief Start PCB */ -esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); /** * @brief Stop PCB */ -esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); /** * @brief send packet over UDP @@ -50,6 +50,6 @@ esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_pr * * @return length of sent packet or 0 on error */ -size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len); +size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len); #endif /* ESP_MDNS_NETWORKING_H_ */ diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 3c495dd82..900c28ced 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -214,10 +214,10 @@ typedef struct mdns_parsed_record_s { } mdns_parsed_record_t; typedef struct { - tcpip_adapter_if_t tcpip_if; + mdns_if_t tcpip_if; mdns_ip_protocol_t ip_protocol; //struct udp_pcb *pcb; - ip_addr_t src; + esp_ip_addr_t src; uint16_t src_port; uint8_t multicast; uint8_t authoritative; @@ -229,11 +229,11 @@ typedef struct { } mdns_parsed_packet_t; typedef struct { - tcpip_adapter_if_t tcpip_if; + mdns_if_t tcpip_if; mdns_ip_protocol_t ip_protocol; struct pbuf *pb; - ip_addr_t src; - ip_addr_t dest; + esp_ip_addr_t src; + esp_ip_addr_t dest; uint16_t src_port; uint8_t multicast; } mdns_rx_packet_t; @@ -283,9 +283,9 @@ typedef struct mdns_out_answer_s { typedef struct mdns_tx_packet_s { struct mdns_tx_packet_s * next; uint32_t send_at; - tcpip_adapter_if_t tcpip_if; + mdns_if_t tcpip_if; mdns_ip_protocol_t ip_protocol; - ip_addr_t dst; + esp_ip_addr_t dst; uint16_t port; uint16_t flags; uint8_t distributed; @@ -333,7 +333,7 @@ typedef struct mdns_search_once_s { typedef struct mdns_server_s { struct { mdns_pcb_t pcbs[MDNS_IP_PROTOCOL_MAX]; - } interfaces[TCPIP_ADAPTER_IF_MAX]; + } interfaces[MDNS_IF_MAX]; const char * hostname; const char * instance; mdns_srv_item_t * services; @@ -352,7 +352,7 @@ typedef struct { struct { esp_event_base_t event_base; int32_t event_id; - tcpip_adapter_if_t interface; + esp_netif_t* interface; } sys_event; struct { mdns_srv_item_t * service; @@ -393,4 +393,16 @@ typedef struct { } data; } mdns_action_t; +/* + * @brief Convert mnds if to esp-netif handle + * + * @param tcpip_if mdns supported interface as internal enum + * + * @return + * - ptr to esp-netif on success + * - NULL if no available netif for current interface index + */ +esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if); + + #endif /* MDNS_PRIVATE_H_ */ diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 76cb3b1b6..c15f37d18 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -9,18 +9,15 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" #include "esp_system.h" -#include "esp_wifi.h" #include "esp_event.h" #include "esp_log.h" #include "nvs_flash.h" -#include "tcpip_adapter.h" +#include "esp_netif.h" #include "protocol_examples_common.h" #include "mdns.h" #include "driver/gpio.h" -#include -#include +#include "netdb.h" #define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE @@ -88,7 +85,7 @@ static void mdns_print_results(mdns_result_t * results){ } a = r->addr; while(a){ - if(a->addr.type == IPADDR_TYPE_V6){ + if(a->addr.type == ESP_IPADDR_TYPE_V6){ printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); } else { printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); @@ -123,7 +120,7 @@ static void query_mdns_host(const char * host_name) { ESP_LOGI(TAG, "Query A: %s.local", host_name); - struct ip4_addr addr; + struct esp_ip4_addr addr; addr.addr = 0; esp_err_t err = mdns_query_a(host_name, 2000, &addr); From d1c62628b8416104289b2d5aa1a737dfacf665be Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 4 Sep 2019 13:58:29 +0200 Subject: [PATCH 107/289] esp_netif and examples: using wifi driver handle, update examples and tests to pass the CI * Original commit: espressif/esp-idf@3a19bf055d62d7cea4c7a62c8cc5f3b6a7e25b7c --- .../common_components/protocol_examples_common/connect.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index b261e0b4f..f9b974fba 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -12,6 +12,7 @@ #include "sdkconfig.h" #include "esp_event.h" #include "esp_wifi.h" +#include "esp_wifi_default.h" #if CONFIG_EXAMPLE_CONNECT_ETHERNET #include "esp_eth.h" #endif @@ -136,7 +137,7 @@ static void start(void) assert(netif); - esp_wifi_set_default_wifi_sta_handlers(netif); + esp_wifi_set_default_wifi_driver_and_handlers(ESP_IF_WIFI_STA, netif); s_example_esp_netif = netif; @@ -176,7 +177,7 @@ static void stop(void) } ESP_ERROR_CHECK(err); ESP_ERROR_CHECK(esp_wifi_deinit()); - + ESP_ERROR_CHECK(esp_wifi_clear_default_wifi_driver_and_handlers(s_example_esp_netif)); esp_netif_destroy(s_example_esp_netif); s_example_esp_netif = NULL; } From 573855031d28d76aedf1bee7945193e6245f19c1 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Sun, 15 Sep 2019 19:49:45 +0200 Subject: [PATCH 108/289] esp_netif: extract wifi_netif module as an abstraction to wifi universal interface defined by if handle and callback * Original commit: espressif/esp-idf@20add7da60d2e7c1a2f372258bdd286a9b30865e --- examples/common_components/protocol_examples_common/connect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index f9b974fba..b161e9a6e 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -137,7 +137,8 @@ static void start(void) assert(netif); - esp_wifi_set_default_wifi_driver_and_handlers(ESP_IF_WIFI_STA, netif); + esp_netif_attach_wifi_station(netif); + esp_wifi_set_default_wifi_sta_handlers(); s_example_esp_netif = netif; From 1f35e9a7285d291bca156362ff7d849e959d2e19 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 23 Oct 2019 16:47:16 +0200 Subject: [PATCH 109/289] tcpip_adapter: updated tcpip_adapter compatablity layer to include all public API and keep 100% backward compatibility update build of tcpip adapter when ethernet disabled * Original commit: espressif/esp-idf@7f5cda1b825586903f85dc4ad7736b35712e46d7 --- components/mdns/mdns.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index cb5f86ea0..f6131f2bf 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3110,8 +3110,10 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, s_esp_netifs[MDNS_IF_STA] = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_START) { s_esp_netifs[MDNS_IF_AP] = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); +#if CONFIG_ETH_ENABLED } else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_START) { s_esp_netifs[MDNS_IF_ETH] = esp_netif_get_handle_from_ifkey("ETH_DEF"); +#endif } esp_netif_dhcp_status_t dcst; From fb1de80fd729ad11613cc5e79a1a972a8fe9cf76 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Sat, 2 Nov 2019 21:32:52 +0100 Subject: [PATCH 110/289] mdns: add configuration values for task priority, affinity and internal service timeouts closes https://github.com/espressif/esp-idf/issues/4217 * Original commit: espressif/esp-idf@c6f38f04f8eec1aae937cc87c111609772681cb3 --- components/mdns/Kconfig | 48 +++++++++++++++++++ components/mdns/mdns.c | 19 +++++--- .../mdns/private_include/mdns_private.h | 11 ++++- 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig index 5c97d65f4..ab5cd8012 100644 --- a/components/mdns/Kconfig +++ b/components/mdns/Kconfig @@ -10,4 +10,52 @@ menu "mDNS" the maximum amount of services here. The valid value is from 1 to 64. + config MDNS_TASK_PRIORITY + int "mDNS task priority" + range 1 255 + default 1 + help + Allows setting mDNS task priority. Please do not set the task priority + higher than priorities of system tasks. Compile time warning/error + would be emitted if the chosen task priority were too high. + + choice MDNS_TASK_AFFINITY + prompt "mDNS task affinity" + default MDNS_TASK_AFFINITY_CPU0 + help + Allows setting mDNS tasks affinity, i.e. whether the task is pinned to + CPU0, pinned to CPU1, or allowed to run on any CPU. + + config MDNS_TASK_AFFINITY_NO_AFFINITY + bool "No affinity" + config MDNS_TASK_AFFINITY_CPU0 + bool "CPU0" + config MDNS_TASK_AFFINITY_CPU1 + bool "CPU1" + depends on !FREERTOS_UNICORE + + endchoice + + config MDNS_TASK_AFFINITY + hex + default FREERTOS_NO_AFFINITY if MDNS_TASK_AFFINITY_NO_AFFINITY + default 0x0 if MDNS_TASK_AFFINITY_CPU0 + default 0x1 if MDNS_TASK_AFFINITY_CPU1 + + config MDNS_SERVICE_ADD_TIMEOUT_MS + int "mDNS adding service timeout (ms)" + range 10 30000 + default 2000 + help + Configures timeout for adding a new mDNS service. Adding a service + fails if could not be completed within this time. + + config MDNS_TIMER_PERIOD_MS + int "mDNS timer period (ms)" + range 10 10000 + default 100 + help + Configures period of mDNS timer, which periodically transmits packets + and schedules mDNS searches. + endmenu diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index f6131f2bf..5fd82bf9c 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -17,6 +17,7 @@ #include "mdns_networking.h" #include "esp_log.h" #include +#include #ifdef MDNS_ENABLE_DEBUG void mdns_debug_packet(const uint8_t * data, size_t len); @@ -4141,7 +4142,8 @@ static esp_err_t _mdns_service_task_start(void) return ESP_FAIL; } if (!_mdns_service_task_handle) { - xTaskCreatePinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, 1, (TaskHandle_t * const)(&_mdns_service_task_handle), 0); + xTaskCreatePinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, MDNS_TASK_PRIORITY, + (TaskHandle_t * const)(&_mdns_service_task_handle), MDNS_TASK_AFFINITY); if (!_mdns_service_task_handle) { _mdns_stop_timer(); MDNS_SERVICE_UNLOCK(); @@ -4446,12 +4448,15 @@ esp_err_t mdns_service_add(const char * instance, const char * service, const ch return ESP_ERR_NO_MEM; } - uint8_t i = 0; - while (_mdns_get_service_item(service, proto) == NULL && i++ < 200) { - vTaskDelay(1); - } - if (i >= 200) { - return ESP_FAIL; + size_t start = xTaskGetTickCount(); + size_t timeout_ticks = pdMS_TO_TICKS(MDNS_SERVICE_ADD_TIMEOUT_MS); + while (_mdns_get_service_item(service, proto) == NULL) + { + uint32_t expired = xTaskGetTickCount() - start; + if (expired >= timeout_ticks) { + return ESP_FAIL; // Timeout + } + vTaskDelay(MIN(10 / portTICK_RATE_MS, timeout_ticks - expired)); } return ESP_OK; diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 900c28ced..8f26a5031 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -56,6 +56,15 @@ #define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on #define MDNS_SERVICE_STACK_DEPTH 4096 // Stack size for the service thread +#define MDNS_TASK_PRIORITY CONFIG_MDNS_TASK_PRIORITY +#if (MDNS_TASK_PRIORITY > ESP_TASK_PRIO_MAX) +#error "mDNS task priority is higher than ESP_TASK_PRIO_MAX" +#elif (MDNS_TASK_PRIORITY > ESP_TASKD_EVENT_PRIO) +#warning "mDNS task priority is higher than ESP_TASKD_EVENT_PRIO, mDNS library might not work correctly" +#endif +#define MDNS_TASK_AFFINITY CONFIG_MDNS_TASK_AFFINITY +#define MDNS_SERVICE_ADD_TIMEOUT_MS CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS + #define MDNS_PACKET_QUEUE_LEN 16 // Maximum packets that can be queued for parsing #define MDNS_ACTION_QUEUE_LEN 16 // Maximum actions pending to the server #define MDNS_TXT_MAX_LEN 1024 // Maximum string length of text data in TXT record @@ -82,7 +91,7 @@ #define MDNS_SRV_PORT_OFFSET 4 #define MDNS_SRV_FQDN_OFFSET 6 -#define MDNS_TIMER_PERIOD_US 100000 +#define MDNS_TIMER_PERIOD_US (CONFIG_MDNS_TIMER_PERIOD_MS*1000) #define MDNS_SERVICE_LOCK() xSemaphoreTake(_mdns_service_semaphore, portMAX_DELAY) #define MDNS_SERVICE_UNLOCK() xSemaphoreGive(_mdns_service_semaphore) From 662a4ce050f8329e442e4a3aa73d654afcf52aae Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 14 Nov 2019 18:02:26 +0100 Subject: [PATCH 111/289] mdns: add missing include of esp_task.h * Original commit: espressif/esp-idf@5884b80908d680874e27fa0c8b2df85b69d03dd3 --- components/mdns/private_include/mdns_private.h | 1 + 1 file changed, 1 insertion(+) diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 8f26a5031..b79808875 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -15,6 +15,7 @@ #define MDNS_PRIVATE_H_ #include "esp_event_base.h" +#include "esp_task.h" //#define MDNS_ENABLE_DEBUG From 1734e59057cdf6672c30afdafa498208518426f1 Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 21 Mar 2019 15:38:48 +0800 Subject: [PATCH 112/289] zh_CN translation of mdns service * Original commit: espressif/esp-idf@9691a755f683b857023da53b28ae242f57376366 --- docs/en/api-reference/protocols/mdns.rst | 1 + docs/zh_CN/api-reference/protocols/mdns.rst | 190 +++++++++++++++++++- 2 files changed, 190 insertions(+), 1 deletion(-) diff --git a/docs/en/api-reference/protocols/mdns.rst b/docs/en/api-reference/protocols/mdns.rst index 5a31fb613..bcea6686e 100644 --- a/docs/en/api-reference/protocols/mdns.rst +++ b/docs/en/api-reference/protocols/mdns.rst @@ -1,5 +1,6 @@ mDNS Service ============ +:link_to_translation:`zh_CN:[中文]` Overview -------- diff --git a/docs/zh_CN/api-reference/protocols/mdns.rst b/docs/zh_CN/api-reference/protocols/mdns.rst index 3f82c5d80..3973ef3ad 100644 --- a/docs/zh_CN/api-reference/protocols/mdns.rst +++ b/docs/zh_CN/api-reference/protocols/mdns.rst @@ -1 +1,189 @@ -.. include:: ../../../en/api-reference/protocols/mdns.rst \ No newline at end of file +mDNS 服务 +========= +:link_to_translation:`en:[English]` + +概述 +---- + +mDNS 是一种组播 UDP 服务,用来提供本地网络服务和主机发现。 + +绝大多数的操作系统默认都会安装 mDNS 服务,或者提供单独的安装包。``Mac OS`` 默认会安装名为 ``Bonjour`` 的服务(该服务基于 mDNS),此外 Apple 还发布了适用于 Windows 系统的安装程序,可以在 `官方支持 `_ 找到。在 ``Linux`` 上,mDNS 服务由 `avahi `_ 提供,通常也会被默认安装。 + +mDNS 属性 +^^^^^^^^^ + + * ``hostname``:设备会去响应的主机名,如果没有设置,会根据设备的网络接口名定义 ``hostname`` 。例如,``my-esp32`` 会被解析为 ``my-esp32.local``。 + * ``default_instance``:默认实例名(即易记的设备名),例如 ``Jhon's ESP32 Thing``。如果没有设置,将会使用 ``hostname``。 + +以下为 STA 接口启动 mDNS 服务并设置 ``hostname`` 和 ``default_instance`` 的示例方法: + +.. highlight:: c + +:: + + void start_mdns_service() + { + // 初始化 mDNS 服务 + esp_err_t err = mdns_init(); + if (err) { + printf("MDNS Init failed: %d\n", err); + return; + } + + // 设置 hostname + mdns_hostname_set("my-esp32"); + // 设置默认实例 + mdns_instance_name_set("Jhon's ESP32 Thing"); + } + +mDNS 服务 +^^^^^^^^^ + +mDNS 可以广播设备能够提供的网络服务的相关信息,每个服务会由以下属性构成。 + + * ``instance_name``:实例名(即易记的服务名),例如 ``Jhon's ESP32 Web Server``。如果没有定义,会使用 ``default_instance``。 + * ``service_type``:(必需)服务类型,以下划线为前缀,`这里 `_ 列出了常见的类型。 + * ``proto``:(必需)服务运行所依赖的协议,以下划线为前缀,例如 ``_tcp`` 或者 ``_udp``。 + * ``port``:(必需)服务运行所用的端口号。 + * ``txt``:形如 ``{var, val}`` 的字符串数组,用于定义服务的属性。 + +添加一些服务和不同属性的示例方法:: + + void add_mdns_services() + { + // 添加服务 + mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0); + mdns_service_add(NULL, "_arduino", "_tcp", 3232, NULL, 0); + mdns_service_add(NULL, "_myservice", "_udp", 1234, NULL, 0); + + // 注意:必须先添加服务,然后才能设置其属性 + // web 服务器使用自定义的实例名 + mdns_service_instance_name_set("_http", "_tcp", "Jhon's ESP32 Web Server"); + + mdns_txt_item_t serviceTxtData[3] = { + {"board","esp32"}, + {"u","user"}, + {"p","password"} + }; + // 设置服务的文本数据(会释放并替换当前数据) + mdns_service_txt_set("_http", "_tcp", serviceTxtData, 3); + + // 修改服务端口号 + mdns_service_port_set("_myservice", "_udp", 4321); + } + +mDNS 查询 +^^^^^^^^^ + +mDNS 提供查询服务和解析主机 IP/IPv6 地址的方法。 + +服务查询的结果会作为 ``mdns_result_t`` 类型对象的链表返回。 + +解析主机 IP 地址的示例方法:: + + void resolve_mdns_host(const char * host_name) + { + printf("Query A: %s.local", host_name); + + struct ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(host_name, 2000, &addr); + if(err){ + if(err == ESP_ERR_NOT_FOUND){ + printf("Host was not found!"); + return; + } + printf("Query Failed"); + return; + } + + printf(IPSTR, IP2STR(&addr)); + } + +解析本地服务的示例方法:: + + static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; + static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; + + void mdns_print_results(mdns_result_t * results){ + mdns_result_t * r = results; + mdns_ip_addr_t * a = NULL; + int i = 1, t; + while(r){ + printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]); + if(r->instance_name){ + printf(" PTR : %s\n", r->instance_name); + } + if(r->hostname){ + printf(" SRV : %s.local:%u\n", r->hostname, r->port); + } + if(r->txt_count){ + printf(" TXT : [%u] ", r->txt_count); + for(t=0; ttxt_count; t++){ + printf("%s=%s; ", r->txt[t].key, r->txt[t].value); + } + printf("\n"); + } + a = r->addr; + while(a){ + if(a->addr.type == IPADDR_TYPE_V6){ + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + r = r->next; + } + + } + + void find_mdns_service(const char * service_name, const char * proto) + { + ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); + + mdns_result_t * results = NULL; + esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); + if(err){ + ESP_LOGE(TAG, "Query Failed"); + return; + } + if(!results){ + ESP_LOGW(TAG, "No results found!"); + return; + } + + mdns_print_results(results); + mdns_query_results_free(results); + } + +使用上述方法的示例:: + + void my_app_some_method(){ + // 搜索 esp32-mdns.local + resolve_mdns_host("esp32-mdns"); + + // 搜索 HTTP 服务器 + find_mdns_service("_http", "_tcp"); + // 或者搜索文件服务器 + find_mdns_service("_smb", "_tcp"); // Windows 系统的共享服务 + find_mdns_service("_afpovertcp", "_tcp"); // Apple AFP 文件共享服务 + find_mdns_service("_nfs", "_tcp"); // NFS 服务器 + find_mdns_service("_ftp", "_tcp"); // FTP 服务器 + // 或者网络打印机 + find_mdns_service("_printer", "_tcp"); + find_mdns_service("_ipp", "_tcp"); + } + +应用示例 +-------- + +有关 mDNS 服务器和查询器的应用示例请参考 :example:`protocols/mdns`。 + +API 参考 +-------- + +.. include:: /_build/inc/mdns.inc + + From cd3cc0be3b0ab90d340de6e97a6212105514b270 Mon Sep 17 00:00:00 2001 From: suda-morris <362953310@qq.com> Date: Thu, 14 Nov 2019 12:03:14 +0800 Subject: [PATCH 113/289] ethernet: add gpio number into config structure * Original commit: espressif/esp-idf@05d71319de803589de99cc78850671b68917a8a2 --- .../Kconfig.projbuild | 54 +++++++++++++++---- .../protocol_examples_common/connect.c | 24 +++++---- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index 0e6997983..f8ceb1e40 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -33,7 +33,7 @@ menu "Example Connection Configuration" choice EXAMPLE_USE_ETHERNET prompt "Ethernet Type" default EXAMPLE_USE_INTERNAL_ETHERNET if IDF_TARGET_ESP32 - default EXAMPLE_USE_SPI_ETHERNET if !IDF_TARGET_ESP32 + default EXAMPLE_USE_DM9051 if !IDF_TARGET_ESP32 help Select which kind of Ethernet will be used in the example. @@ -44,9 +44,10 @@ menu "Example Connection Configuration" help Select internal Ethernet MAC controller. - config EXAMPLE_USE_SPI_ETHERNET - bool "SPI Ethernet Module" + config EXAMPLE_USE_DM9051 + bool "DM9051 Module" select ETH_USE_SPI_ETHERNET + select ETH_SPI_ETHERNET_DM9051 help Select external SPI-Ethernet module. @@ -93,51 +94,84 @@ menu "Example Connection Configuration" DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver. Goto http://www.ti.com/product/DP83848J for more information about it. endchoice + + config EXAMPLE_ETH_MDC_GPIO + int "SMI MDC GPIO number" + default 23 + help + Set the GPIO number used by SMI MDC. + + config EXAMPLE_ETH_MDIO_GPIO + int "SMI MDIO GPIO number" + default 18 + help + Set the GPIO number used by SMI MDIO. endif - if EXAMPLE_USE_SPI_ETHERNET - config EXAMPLE_ETH_SPI_HOST + if EXAMPLE_USE_DM9051 + config EXAMPLE_DM9051_SPI_HOST int "SPI Host Number" range 0 2 default 1 help Set the SPI host used to communicate with DM9051. - config EXAMPLE_ETH_SCLK_GPIO + config EXAMPLE_DM9051_SCLK_GPIO int "SPI SCLK GPIO number" range 0 33 default 19 help Set the GPIO number used by SPI SCLK. - config EXAMPLE_ETH_MOSI_GPIO + config EXAMPLE_DM9051_MOSI_GPIO int "SPI MOSI GPIO number" range 0 33 default 23 help Set the GPIO number used by SPI MOSI. - config EXAMPLE_ETH_MISO_GPIO + config EXAMPLE_DM9051_MISO_GPIO int "SPI MISO GPIO number" range 0 33 default 25 help Set the GPIO number used by SPI MISO. - config EXAMPLE_ETH_CS_GPIO + config EXAMPLE_DM9051_CS_GPIO int "SPI CS GPIO number" range 0 33 default 22 help Set the GPIO number used by SPI CS. - config EXAMPLE_ETH_SPI_CLOCK_MHZ + config EXAMPLE_DM9051_SPI_CLOCK_MHZ int "SPI clock speed (MHz)" range 20 80 default 20 help Set the clock speed (MHz) of SPI interface. + + config EXAMPLE_DM9051_INT_GPIO + int "Interrupt GPIO number" + default 4 + help + Set the GPIO number used by DM9051 interrupt. endif + + config EXAMPLE_ETH_PHY_RST_GPIO + int "PHY Reset GPIO number" + default 5 + help + Set the GPIO number used to reset PHY chip. + Set to -1 to disable PHY chip hardware reset. + + config EXAMPLE_ETH_PHY_ADDR + int "PHY Address" + range 0 31 if EXAMPLE_USE_INTERNAL_ETHERNET + range 1 1 if !EXAMPLE_USE_INTERNAL_ETHERNET + default 1 + help + Set PHY address according your board schematic. endif config EXAMPLE_CONNECT_IPV6 diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index b161e9a6e..f71b323b2 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -18,6 +18,7 @@ #endif #include "esp_log.h" #include "esp_netif.h" +#include "driver/gpio.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" @@ -227,7 +228,11 @@ static void start(void) #endif eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); + phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR; + phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO; #if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET + mac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; + mac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; s_mac = esp_eth_mac_new_esp32(&mac_config); #if CONFIG_EXAMPLE_ETH_PHY_IP101 s_phy = esp_eth_phy_new_ip101(&phy_config); @@ -238,28 +243,29 @@ static void start(void) #elif CONFIG_EXAMPLE_ETH_PHY_DP83848 s_phy = esp_eth_phy_new_dp83848(&phy_config); #endif -#elif CONFIG_EXAMPLE_USE_SPI_ETHERNET +#elif CONFIG_EXAMPLE_USE_DM9051 gpio_install_isr_service(0); spi_device_handle_t spi_handle = NULL; spi_bus_config_t buscfg = { - .miso_io_num = CONFIG_EXAMPLE_ETH_MISO_GPIO, - .mosi_io_num = CONFIG_EXAMPLE_ETH_MOSI_GPIO, - .sclk_io_num = CONFIG_EXAMPLE_ETH_SCLK_GPIO, + .miso_io_num = CONFIG_EXAMPLE_DM9051_MISO_GPIO, + .mosi_io_num = CONFIG_EXAMPLE_DM9051_MOSI_GPIO, + .sclk_io_num = CONFIG_EXAMPLE_DM9051_SCLK_GPIO, .quadwp_io_num = -1, .quadhd_io_num = -1, }; - ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1)); + ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_DM9051_SPI_HOST, &buscfg, 1)); spi_device_interface_config_t devcfg = { .command_bits = 1, .address_bits = 7, .mode = 0, - .clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000, - .spics_io_num = CONFIG_EXAMPLE_ETH_CS_GPIO, + .clock_speed_hz = CONFIG_EXAMPLE_DM9051_SPI_CLOCK_MHZ * 1000 * 1000, + .spics_io_num = CONFIG_EXAMPLE_DM9051_CS_GPIO, .queue_size = 20 }; - ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle)); + ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_DM9051_SPI_HOST, &devcfg, &spi_handle)); /* dm9051 ethernet driver is based on spi driver */ eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle); + dm9051_config.int_gpio_num = CONFIG_EXAMPLE_DM9051_INT_GPIO; s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); s_phy = esp_eth_phy_new_dm9051(&phy_config); #elif CONFIG_EXAMPLE_USE_OPENETH @@ -297,4 +303,4 @@ static void stop(void) esp_netif_t *get_example_netif(void) { return s_example_esp_netif; -} \ No newline at end of file +} From d20666f3a048c974df928bbeeec6fa212a04e12c Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 22 Nov 2019 09:42:09 +0100 Subject: [PATCH 114/289] mdns: fixed forgotten merge conflicts in debug code * Original commit: espressif/esp-idf@d9433ef69223a32d05abdca543fb530f2e6679e4 --- components/mdns/mdns.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 5fd82bf9c..ac6388916 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -5015,13 +5015,8 @@ void mdns_debug_packet(const uint8_t * data, size_t len) } _mdns_dbg_printf("\n"); } else if (type == MDNS_TYPE_AAAA) { -<<<<<<< HEAD - ip6_addr_t ip6; - memcpy(&ip6, data_ptr, MDNS_ANSWER_AAAA_SIZE); -======= esp_ip6_addr_t ip6; memcpy(&ip6, data_ptr, sizeof(esp_ip6_addr_t)); ->>>>>>> mdns: update mdns to use esp-netif for mdns supported services such as STA, AP, ETH _mdns_dbg_printf(IPV6STR "\n", IPV62STR(ip6)); } else if (type == MDNS_TYPE_A) { esp_ip4_addr_t ip; From 80ce63d73e7b623f4bf12fa5ab0e5dafd24851d1 Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 26 Nov 2019 17:48:38 +0800 Subject: [PATCH 115/289] ethernet: move netif glue && add ref counter 1. move netif glue into single file 2. add reference counter for Ethernet driver * Original commit: espressif/esp-idf@c3ee156df0df19207b374cd257109a2d5179c1a2 --- .../protocol_examples_common/connect.c | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index f71b323b2..f33aa7051 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -134,7 +134,7 @@ static void start(void) esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_WIFI_STA(); - esp_netif_t* netif = esp_netif_new(&netif_config); + esp_netif_t *netif = esp_netif_new(&netif_config); assert(netif); @@ -212,15 +212,12 @@ static esp_eth_phy_t *s_phy = NULL; static void start(void) { esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_ETH(); - - esp_netif_t* netif = esp_netif_new(&netif_config); - + esp_netif_t *netif = esp_netif_new(&netif_config); assert(netif); - - ESP_ERROR_CHECK(esp_eth_set_default_handlers(netif)); - s_example_esp_netif = netif; - + // Set default handlers to process TCP/IP stuffs + ESP_ERROR_CHECK(esp_eth_set_default_handlers(netif)); + // Register user defined event handers ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL)); #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif)); @@ -274,11 +271,12 @@ static void start(void) s_phy = esp_eth_phy_new_dp83848(&phy_config); #endif + // Install Ethernet driver esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy); - ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle)); - - esp_netif_attach(netif, s_eth_handle); + // combine driver with netif + esp_netif_attach(netif, esp_eth_new_netif_glue(s_eth_handle)); + esp_eth_start(s_eth_handle); s_connection_name = "Ethernet"; } From c7ff8ba0c967811d25edb8c7dde112dc74cb4e0f Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 3 Dec 2019 15:37:34 +0800 Subject: [PATCH 116/289] ethernet: warning when double start/stop * Original commit: espressif/esp-idf@ac11545e0a6456ad0db2fd01586b0556726d8377 --- examples/common_components/protocol_examples_common/connect.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index f33aa7051..b3765d878 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -287,6 +287,7 @@ static void stop(void) ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6)); ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event)); #endif + ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle)); ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle)); ESP_ERROR_CHECK(s_phy->del(s_phy)); ESP_ERROR_CHECK(s_mac->del(s_mac)); From 7a3aa26df854d825350601d0e52a2d5bbf041eb5 Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Wed, 27 Nov 2019 11:58:07 +0800 Subject: [PATCH 117/289] test: update example and unit tests with new import roles: tiny_test_fw is a python package now. import it using normal way. * Original commit: espressif/esp-idf@c906e2afee9455bf55b7b163815dce69de766879 --- examples/protocols/mdns/mdns_example_test.py | 27 +++++--------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index e86b84e42..af897bb79 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -1,6 +1,5 @@ import re import os -import sys import socket import time import struct @@ -8,22 +7,8 @@ import dpkt import dpkt.dns from threading import Thread, Event - -# this is a test case write with tiny-test-fw. -# to run test cases outside tiny-test-fw, -# we need to set environment variable `TEST_FW_PATH`, -# then get and insert `TEST_FW_PATH` to sys path before import FW module - -try: - import IDF - from IDF.IDFDUT import ESP32DUT -except ImportError: - test_fw_path = os.getenv("TEST_FW_PATH") - if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - import IDF - -import DUT +from tiny_test_fw import DUT +import ttfw_idf # g_run_server = True # g_done = False @@ -103,7 +88,7 @@ def mdns_server(esp_host): continue -@IDF.idf_example_test(env_tag="Example_WIFI") +@ttfw_idf.idf_example_test(env_tag="Example_WIFI") def test_examples_protocol_mdns(env, extra_data): global stop_mdns_server """ @@ -113,12 +98,12 @@ def test_examples_protocol_mdns(env, extra_data): 3. check the mdns name is accessible 4. check DUT output if mdns advertized host is resolved """ - dut1 = env.get_dut("mdns-test", "examples/protocols/mdns", dut_class=ESP32DUT) + dut1 = env.get_dut("mdns-test", "examples/protocols/mdns", dut_class=ttfw_idf.ESP32DUT) # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "mdns-test.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("mdns-test_bin_size", "{}KB".format(bin_size // 1024)) - IDF.check_performance("mdns-test_bin_size", bin_size // 1024) + ttfw_idf.log_performance("mdns-test_bin_size", "{}KB".format(bin_size // 1024)) + ttfw_idf.check_performance("mdns-test_bin_size", bin_size // 1024) # 1. start mdns application dut1.start_app() # 2. get the dut host name (and IP address) From 8f0dc6d57805b38d0b2c26a5601e62565a9c4b1e Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 28 Nov 2019 11:04:37 +0100 Subject: [PATCH 118/289] mdns: respond to discovery with the proper pseudo name _services._dns-sd._udp Closes https://github.com/espressif/esp-idf/issues/4369 Closes IDFGH-2219 * Original commit: espressif/esp-idf@de17a1487f8ba6f432b06199f2261132ec6e735f --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index ac6388916..83e9be71a 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1287,7 +1287,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; } From 817c4fd2e8a0fd9c42a159c4d61779dc93e2f172 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 9 Dec 2019 11:29:19 +0100 Subject: [PATCH 119/289] mdns: fixed crash on event during deinit mdns library deinitialization destroys internal structures including action queue. if an event (e.g. network update) received after some essential stucture is destoyed, an unexpected behavour might be introduced (e.g. crash of adding the event notification to the action queue which was already destroyed Closes WIFI-1485 * Original commit: espressif/esp-idf@eaa2f12d6761710d2633b4934fe09f6f45e20f4f --- components/mdns/mdns.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 83e9be71a..f04d4d192 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4301,6 +4301,14 @@ void mdns_free(void) if (!_mdns_server) { return; } + + // Unregister handlers before destoying the mdns internals to avoid receiving asyc events while deinit + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler); + esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler); +#if CONFIG_ETH_ENABLED + esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler); +#endif + mdns_service_remove_all(); _mdns_service_task_stop(); for (i=0; ilock); - esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler); - esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler); -#if CONFIG_ETH_ENABLED - esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler); -#endif free(_mdns_server); _mdns_server = NULL; } From 6713ffedcc03c18b2936db65b9c26335363b6d00 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 13 Dec 2019 19:30:20 +0100 Subject: [PATCH 120/289] mdns: fix preset of esp_netif ptr for local interfaces mdns module store local copy of esp_netif for common interfaces, but it was correctly initialized only when interface started. If the event were missed (e.g. mdns_init after interface start) the local copy wouldn't be initialized. Fixed by restoring the local copy. Closes WIFI-1538 * Original commit: espressif/esp-idf@09e36f9f3354092b2a528baaaaccab28ff4774d6 --- components/mdns/mdns.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index f04d4d192..0577ca542 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -56,6 +56,18 @@ static esp_netif_t * s_esp_netifs[MDNS_IF_MAX] = {}; esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) { if (tcpip_if < MDNS_IF_MAX) { + if (s_esp_netifs[tcpip_if] == NULL) { + // if local netif copy is NULL, try to search for the default interface key + if (tcpip_if == MDNS_IF_STA) { + s_esp_netifs[MDNS_IF_STA] = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); + } else if (tcpip_if == MDNS_IF_AP) { + s_esp_netifs[MDNS_IF_AP] = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); +#if CONFIG_ETH_ENABLED + } else if (tcpip_if == MDNS_IF_ETH) { + s_esp_netifs[MDNS_IF_ETH] = esp_netif_get_handle_from_ifkey("ETH_DEF"); +#endif + } + } return s_esp_netifs[tcpip_if]; } return NULL; @@ -3106,17 +3118,6 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, return; } - // Initialize handles to esp-netif if appropriate mdns supported interface started - if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { - s_esp_netifs[MDNS_IF_STA] = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); - } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_START) { - s_esp_netifs[MDNS_IF_AP] = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); -#if CONFIG_ETH_ENABLED - } else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_START) { - s_esp_netifs[MDNS_IF_ETH] = esp_netif_get_handle_from_ifkey("ETH_DEF"); -#endif - } - esp_netif_dhcp_status_t dcst; if (event_base == WIFI_EVENT) { switch(event_id) { @@ -4231,6 +4232,8 @@ esp_err_t mdns_init(void) return ESP_ERR_NO_MEM; } memset((uint8_t*)_mdns_server, 0, sizeof(mdns_server_t)); + // zero-out local copy of netifs to initiate a fresh search by interface key whenever a netif ptr is needed + memset(s_esp_netifs, 0, sizeof(s_esp_netifs)); _mdns_server->lock = xSemaphoreCreateMutex(); if (!_mdns_server->lock) { From b5e5a64e7fc21d6b694327600ed4c4520e9185bf Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 19 Dec 2019 10:31:02 +0100 Subject: [PATCH 121/289] mdns: fixed typos in the variable names and the comments * Original commit: espressif/esp-idf@ecca39e19f663e32e16aef2a09df15443de347e9 --- components/mdns/include/mdns.h | 4 +- components/mdns/mdns.c | 86 +++++++++---------- .../mdns/private_include/mdns_private.h | 4 +- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 5e93d2fc2..6cee1e313 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -81,7 +81,7 @@ typedef struct mdns_result_s { mdns_txt_item_t * txt; /*!< txt record */ size_t txt_count; /*!< number of txt items */ // A and AAAA - mdns_ip_addr_t * addr; /*!< linked list of IP addreses found */ + mdns_ip_addr_t * addr; /*!< linked list of IP addresses found */ } mdns_result_t; /** @@ -141,7 +141,7 @@ esp_err_t mdns_instance_name_set(const char * instance_name); * - ESP_OK success * - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_NO_MEM memory error - * - ESP_FAIL failed to add serivce + * - ESP_FAIL failed to add service */ 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); diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 0577ca542..9bee17076 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -51,7 +51,7 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, static esp_netif_t * s_esp_netifs[MDNS_IF_MAX] = {}; /* - * @brief Convert mnds if to esp-netif handle + * @brief Convert mdns if to esp-netif handle */ esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) { @@ -74,7 +74,7 @@ esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) } /* - * @brief Convert esp-netif handle to mnds if + * @brief Convert esp-netif handle to mdns if */ static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *interface) { @@ -352,25 +352,25 @@ static inline uint8_t _mdns_append_type(uint8_t * packet, uint16_t * index, uint if ((*index + 10) >= MDNS_MAX_PACKET_SIZE) { return 0; } - uint16_t clas = MDNS_CLASS_IN; + uint16_t mdns_class = MDNS_CLASS_IN; if (flush) { - clas = MDNS_CLASS_IN_FLUSH_CACHE; + mdns_class = MDNS_CLASS_IN_FLUSH_CACHE; } if (type == MDNS_ANSWER_PTR) { _mdns_append_u16(packet, index, MDNS_TYPE_PTR); - _mdns_append_u16(packet, index, clas); + _mdns_append_u16(packet, index, mdns_class); } else if (type == MDNS_ANSWER_TXT) { _mdns_append_u16(packet, index, MDNS_TYPE_TXT); - _mdns_append_u16(packet, index, clas); + _mdns_append_u16(packet, index, mdns_class); } else if (type == MDNS_ANSWER_SRV) { _mdns_append_u16(packet, index, MDNS_TYPE_SRV); - _mdns_append_u16(packet, index, clas); + _mdns_append_u16(packet, index, mdns_class); } else if (type == MDNS_ANSWER_A) { _mdns_append_u16(packet, index, MDNS_TYPE_A); - _mdns_append_u16(packet, index, clas); + _mdns_append_u16(packet, index, mdns_class); } else if (type == MDNS_ANSWER_AAAA) { _mdns_append_u16(packet, index, MDNS_TYPE_AAAA); - _mdns_append_u16(packet, index, clas); + _mdns_append_u16(packet, index, mdns_class); } else { return 0; } @@ -1165,9 +1165,9 @@ static void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t /** * @brief Remove and free answer from answer list (destination) */ -static void _mdns_dealloc_answer(mdns_out_answer_t ** destnation, uint16_t type, mdns_srv_item_t * service) +static void _mdns_dealloc_answer(mdns_out_answer_t ** destination, uint16_t type, mdns_srv_item_t * service) { - mdns_out_answer_t * d = *destnation; + mdns_out_answer_t * d = *destination; if (!d) { return; } @@ -1176,7 +1176,7 @@ static void _mdns_dealloc_answer(mdns_out_answer_t ** destnation, uint16_t type, service = &s; } if (d->type == type && d->service == service->service) { - *destnation = d->next; + *destination = d->next; free(d); return; } @@ -1194,9 +1194,9 @@ static void _mdns_dealloc_answer(mdns_out_answer_t ** destnation, uint16_t type, /** * @brief Allocate new answer and add it to answer list (destination) */ -static bool _mdns_alloc_answer(mdns_out_answer_t ** destnation, uint16_t type, mdns_service_t * service, bool flush, bool bye) +static bool _mdns_alloc_answer(mdns_out_answer_t ** destination, uint16_t type, mdns_service_t * service, bool flush, bool bye) { - mdns_out_answer_t * d = *destnation; + mdns_out_answer_t * d = *destination; while (d) { if (d->type == type && d->service == service) { return true; @@ -1215,7 +1215,7 @@ static bool _mdns_alloc_answer(mdns_out_answer_t ** destnation, uint16_t type, m a->bye = bye; a->flush = flush; a->next = NULL; - queueToEnd(mdns_out_answer_t, *destnation, a); + queueToEnd(mdns_out_answer_t, *destination, a); return true; } @@ -2678,12 +2678,12 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); - uint16_t clas = _mdns_read_u16(content, MDNS_CLASS_OFFSET); - bool unicast = !!(clas & 0x8000); - clas &= 0x7FFF; + uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + bool unicast = !!(mdns_class & 0x8000); + mdns_class &= 0x7FFF; content = content + 4; - if (clas != 0x0001 || name->invalid) {//bad class or invalid name for this question entry + if (mdns_class != 0x0001 || name->invalid) {//bad class or invalid name for this question entry continue; } @@ -2752,11 +2752,11 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); - uint16_t clas = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); uint32_t ttl = _mdns_read_u32(content, MDNS_TTL_OFFSET); uint16_t data_len = _mdns_read_u16(content, MDNS_LEN_OFFSET); const uint8_t * data_ptr = content + MDNS_DATA_OFFSET; - clas &= 0x7FFF; + mdns_class &= 0x7FFF; content = data_ptr + data_len; if (content > (data + len)) { @@ -2766,7 +2766,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) bool discovery = false; bool ours = false; mdns_srv_item_t * service = NULL; - mdns_parsed_recort_type_t record_type = MDNS_ANSWER; + mdns_parsed_record_type_t record_type = MDNS_ANSWER; if (recordIndex >= (header.answers + header.servers)) { record_type = MDNS_EXTRA; @@ -2860,9 +2860,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } //detect collision (-1=won, 0=none, 1=lost) int col = 0; - if (clas > 1) { + if (mdns_class > 1) { col = 1; - } else if (!clas) { + } else if (!mdns_class) { col = -1; } else if (service) { // only detect srv collision if service existed col = _mdns_check_srv_collision(service->service, priority, weight, port, name->host, name->domain); @@ -2945,9 +2945,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } //detect collision (-1=won, 0=none, 1=lost) int col = 0; - if (clas > 1) { + if (mdns_class > 1) { col = 1; - } else if (!clas) { + } else if (!mdns_class) { col = -1; } else if (service) { // only detect txt collision if service existed col = _mdns_check_txt_collision(service->service, data_ptr, data_len); @@ -2977,9 +2977,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } //detect collision (-1=won, 0=none, 1=lost) int col = 0; - if (clas > 1) { + if (mdns_class > 1) { col = 1; - } else if (!clas) { + } else if (!mdns_class) { col = -1; } else { col = _mdns_check_aaaa_collision(&(ip6.u_addr.ip6), packet->tcpip_if); @@ -3023,9 +3023,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } //detect collision (-1=won, 0=none, 1=lost) int col = 0; - if (clas > 1) { + if (mdns_class > 1) { col = 1; - } else if (!clas) { + } else if (!mdns_class) { col = -1; } else { col = _mdns_check_a_collision(&(ip.u_addr.ip4), packet->tcpip_if); @@ -3576,7 +3576,7 @@ static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * s, mdns_ } /** - * @brief Create search packet for partidular interface + * @brief Create search packet for particular interface */ static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { @@ -4305,7 +4305,7 @@ void mdns_free(void) return; } - // Unregister handlers before destoying the mdns internals to avoid receiving asyc events while deinit + // Unregister handlers before destroying the mdns internals to avoid receiving async events while deinit esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler); esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler); #if CONFIG_ETH_ENABLED @@ -4877,9 +4877,9 @@ void mdns_debug_packet(const uint8_t * data, size_t len) } uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); - uint16_t clas = _mdns_read_u16(content, MDNS_CLASS_OFFSET); - bool unicast = !!(clas & 0x8000); - clas &= 0x7FFF; + uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + bool unicast = !!(mdns_class & 0x8000); + mdns_class &= 0x7FFF; content = content + 4; _mdns_dbg_printf(" Q: "); @@ -4904,10 +4904,10 @@ void mdns_debug_packet(const uint8_t * data, size_t len) _mdns_dbg_printf("%s.%s%s.%s.%s. %04X ", name->host, name->sub?"_sub.":"", name->service, name->proto, name->domain, type); } - if (clas == 0x0001) { + if (mdns_class == 0x0001) { _mdns_dbg_printf("IN"); } else { - _mdns_dbg_printf("%04X", clas); + _mdns_dbg_printf("%04X", mdns_class); } _mdns_dbg_printf("\n"); } @@ -4925,12 +4925,12 @@ void mdns_debug_packet(const uint8_t * data, size_t len) } uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); - uint16_t clas = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); uint32_t ttl = _mdns_read_u32(content, MDNS_TTL_OFFSET); uint16_t data_len = _mdns_read_u16(content, MDNS_LEN_OFFSET); const uint8_t * data_ptr = content + MDNS_DATA_OFFSET; - bool flush = !!(clas & 0x8000); - clas &= 0x7FFF; + bool flush = !!(mdns_class & 0x8000); + mdns_class &= 0x7FFF; content = data_ptr + data_len; if (content > (data + len)) { @@ -4938,7 +4938,7 @@ void mdns_debug_packet(const uint8_t * data, size_t len) break; } - mdns_parsed_recort_type_t record_type = MDNS_ANSWER; + mdns_parsed_record_type_t record_type = MDNS_ANSWER; if (recordIndex >= (header.answers + header.servers)) { record_type = MDNS_EXTRA; @@ -4975,10 +4975,10 @@ void mdns_debug_packet(const uint8_t * data, size_t len) _mdns_dbg_printf(": %s.%s.%s.%s. %04X ", name->host, name->service, name->proto, name->domain, type); } - if (clas == 0x0001) { + if (mdns_class == 0x0001) { _mdns_dbg_printf("IN "); } else { - _mdns_dbg_printf("%04X ", clas); + _mdns_dbg_printf("%04X ", mdns_class); } if (flush) { _mdns_dbg_printf("FLUSH "); diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index b79808875..f572cc233 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -141,7 +141,7 @@ typedef enum { typedef enum { MDNS_ANSWER, MDNS_NS, MDNS_EXTRA -} mdns_parsed_recort_type_t; +} mdns_parsed_record_type_t; typedef enum { ACTION_SYSTEM_EVENT, @@ -210,7 +210,7 @@ typedef struct mdns_parsed_question_s { typedef struct mdns_parsed_record_s { struct mdns_parsed_record_s * next; - mdns_parsed_recort_type_t record_type; + mdns_parsed_record_type_t record_type; uint16_t type; uint16_t clas; uint8_t flush; From 74aee42f80f80da9bf5473be7774ae081ac4d578 Mon Sep 17 00:00:00 2001 From: morris Date: Mon, 13 Jan 2020 21:34:23 +0800 Subject: [PATCH 122/289] ethernet: work with cache disabled add ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE flag, make ethenret driver possible to work when cache disabled Closes https://github.com/espressif/esp-idf/issues/4406 * Original commit: espressif/esp-idf@5ad0bdd8db3438daf8f14eddca6954be29df7a8e --- .../common_components/protocol_examples_common/connect.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index b3765d878..87b218047 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -208,6 +208,7 @@ static void on_eth_event(void *esp_netif, esp_event_base_t event_base, static esp_eth_handle_t s_eth_handle = NULL; static esp_eth_mac_t *s_mac = NULL; static esp_eth_phy_t *s_phy = NULL; +static void *s_eth_glue = NULL; static void start(void) { @@ -275,7 +276,8 @@ static void start(void) esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy); ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle)); // combine driver with netif - esp_netif_attach(netif, esp_eth_new_netif_glue(s_eth_handle)); + s_eth_glue = esp_eth_new_netif_glue(s_eth_handle); + esp_netif_attach(netif, s_eth_glue); esp_eth_start(s_eth_handle); s_connection_name = "Ethernet"; } @@ -288,11 +290,12 @@ static void stop(void) ESP_ERROR_CHECK(esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event)); #endif ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle)); + ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue)); + ESP_ERROR_CHECK(esp_eth_clear_default_handlers(s_example_esp_netif)); ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle)); ESP_ERROR_CHECK(s_phy->del(s_phy)); ESP_ERROR_CHECK(s_mac->del(s_mac)); - esp_eth_clear_default_handlers(s_example_esp_netif); esp_netif_destroy(s_example_esp_netif); s_example_esp_netif = NULL; } From 4eb3e8984196d845d50b7cd912ee6e034e875bd0 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Thu, 6 Feb 2020 14:00:18 +0800 Subject: [PATCH 123/289] esp32: add implementation of esp_timer based on TG0 LAC timer Closes: IDF-979 * Original commit: espressif/esp-idf@739eb05bb97736b70507e7ebcfee58e670672d23 --- components/mdns/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 15b0d40f8..4274d2a46 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -3,5 +3,6 @@ idf_component_register(SRCS "mdns.c" "mdns_networking.c" INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "private_include" - REQUIRES lwip mbedtls console esp_netif) + REQUIRES lwip mbedtls console esp_netif + PRIV_REQUIRES esp_timer) From d9fa457b4f668db21be7ae8ab6446bae11394509 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 13 Nov 2019 11:46:16 +0800 Subject: [PATCH 124/289] docs: add new top-level docs builder that builds docs for a single chip * Original commit: espressif/esp-idf@e6211c7864505f3a66687b402faeb06fa7377f25 --- docs/en/api-reference/protocols/mdns.rst | 2 +- docs/zh_CN/api-reference/protocols/mdns.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/api-reference/protocols/mdns.rst b/docs/en/api-reference/protocols/mdns.rst index bcea6686e..960169b0f 100644 --- a/docs/en/api-reference/protocols/mdns.rst +++ b/docs/en/api-reference/protocols/mdns.rst @@ -184,6 +184,6 @@ mDNS server/scanner example: :example:`protocols/mdns`. API Reference ------------- -.. include:: /_build/inc/mdns.inc +.. include-build-file:: inc/mdns.inc diff --git a/docs/zh_CN/api-reference/protocols/mdns.rst b/docs/zh_CN/api-reference/protocols/mdns.rst index 3973ef3ad..29e935213 100644 --- a/docs/zh_CN/api-reference/protocols/mdns.rst +++ b/docs/zh_CN/api-reference/protocols/mdns.rst @@ -184,6 +184,6 @@ mDNS 提供查询服务和解析主机 IP/IPv6 地址的方法。 API 参考 -------- -.. include:: /_build/inc/mdns.inc +.. include-build-file:: inc/mdns.inc From 881ca095f0b040d3c11a8867ac6352113b0cead9 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Mon, 9 Dec 2019 11:01:09 +0800 Subject: [PATCH 125/289] doc: Update English pages with generic target name * Original commit: espressif/esp-idf@9352899d695fbc4a995f0b38d3eba83f406ba7ac --- docs/en/api-reference/protocols/mdns.rst | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/en/api-reference/protocols/mdns.rst b/docs/en/api-reference/protocols/mdns.rst index 960169b0f..1370b3015 100644 --- a/docs/en/api-reference/protocols/mdns.rst +++ b/docs/en/api-reference/protocols/mdns.rst @@ -12,8 +12,8 @@ mDNS is installed by default on most operating systems or is available as separa mDNS Properties ^^^^^^^^^^^^^^^ - * ``hostname``: the hostname that the device will respond to. If not set, the ``hostname`` will be read from the interface. Example: ``my-esp32`` will resolve to ``my-esp32.local`` - * ``default_instance``: friendly name for your device, like ``Jhon's ESP32 Thing``. If not set, ``hostname`` will be used. + * ``hostname``: the hostname that the device will respond to. If not set, the ``hostname`` will be read from the interface. Example: ``my-{IDF_TARGET_PATH_NAME}`` will resolve to ``my-{IDF_TARGET_PATH_NAME}.local`` + * ``default_instance``: friendly name for your device, like ``Jhon's {IDF_TARGET_NAME} Thing``. If not set, ``hostname`` will be used. Example method to start mDNS for the STA interface and set ``hostname`` and ``default_instance``: @@ -29,11 +29,11 @@ Example method to start mDNS for the STA interface and set ``hostname`` and ``de printf("MDNS Init failed: %d\n", err); return; } - + //set hostname - mdns_hostname_set("my-esp32"); + mdns_hostname_set("my-{IDF_TARGET_PATH_NAME}"); //set default instance - mdns_instance_name_set("Jhon's ESP32 Thing"); + mdns_instance_name_set("Jhon's {IDF_TARGET_NAME} Thing"); } mDNS Services @@ -41,9 +41,9 @@ mDNS Services mDNS can advertise information about network services that your device offers. Each service is defined by a few properties. - * ``instance_name``: friendly name for your service, like ``Jhon's ESP32 Web Server``. If not defined, ``default_instance`` will be used. + * ``instance_name``: friendly name for your service, like ``Jhon's E{IDF_TARGET_NAME} Web Server``. If not defined, ``default_instance`` will be used. * ``service_type``: (required) service type, prepended with underscore. Some common types can be found `here `_. - * ``proto``: (required) protocol that the service runs on, prepended with underscore. Example: ``_tcp`` or ``_udp`` + * ``proto``: (required) protocol that the service runs on, prepended with underscore. Example: ``_tcp`` or ``_udp`` * ``port``: (required) network port that the service runs on * ``txt``: ``{var, val}`` array of strings, used to define properties for your service @@ -55,19 +55,19 @@ Example method to add a few services and different properties:: mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0); mdns_service_add(NULL, "_arduino", "_tcp", 3232, NULL, 0); mdns_service_add(NULL, "_myservice", "_udp", 1234, NULL, 0); - + //NOTE: services must be added before their properties can be set //use custom instance for the web server - mdns_service_instance_name_set("_http", "_tcp", "Jhon's ESP32 Web Server"); + mdns_service_instance_name_set("_http", "_tcp", "Jhon's {IDF_TARGET_NAME} Web Server"); mdns_txt_item_t serviceTxtData[3] = { - {"board","esp32"}, + {"board","{{IDF_TARGET_PATH_NAME}}"}, {"u","user"}, {"p","password"} }; //set txt data for service (will free and replace current data) mdns_service_txt_set("_http", "_tcp", serviceTxtData, 3); - + //change service port mdns_service_port_set("_myservice", "_udp", 4321); } @@ -161,9 +161,9 @@ Example method to resolve local services:: Example of using the methods above:: void my_app_some_method(){ - //search for esp32-mdns.local - resolve_mdns_host("esp32-mdns"); - + //search for {IDF_TARGET_PATH_NAME}-mdns.local + resolve_mdns_host("{IDF_TARGET_PATH_NAME}-mdns"); + //search for HTTP servers find_mdns_service("_http", "_tcp"); //or file servers From 7bf23a7fe90d12a9d9c83e16de7d7db6cb07830a Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Tue, 10 Dec 2019 14:55:35 +0800 Subject: [PATCH 126/289] doc: Changed Chinese doc to use dynamic chip name * Original commit: espressif/esp-idf@cfeb9e68cb6fce1fcce075483e34d10a67f2aa0c --- docs/zh_CN/api-reference/protocols/mdns.rst | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/zh_CN/api-reference/protocols/mdns.rst b/docs/zh_CN/api-reference/protocols/mdns.rst index 29e935213..29bdbf345 100644 --- a/docs/zh_CN/api-reference/protocols/mdns.rst +++ b/docs/zh_CN/api-reference/protocols/mdns.rst @@ -12,8 +12,8 @@ mDNS 是一种组播 UDP 服务,用来提供本地网络服务和主机发现 mDNS 属性 ^^^^^^^^^ - * ``hostname``:设备会去响应的主机名,如果没有设置,会根据设备的网络接口名定义 ``hostname`` 。例如,``my-esp32`` 会被解析为 ``my-esp32.local``。 - * ``default_instance``:默认实例名(即易记的设备名),例如 ``Jhon's ESP32 Thing``。如果没有设置,将会使用 ``hostname``。 + * ``hostname``:设备会去响应的主机名,如果没有设置,会根据设备的网络接口名定义 ``hostname`` 。例如,``my-{IDF_TARGET_PATH_NAME}`` 会被解析为 ``my-{IDF_TARGET_PATH_NAME}.local``。 + * ``default_instance``:默认实例名(即易记的设备名),例如 ``Jhon's {IDF_TARGET_NAME} Thing``。如果没有设置,将会使用 ``hostname``。 以下为 STA 接口启动 mDNS 服务并设置 ``hostname`` 和 ``default_instance`` 的示例方法: @@ -29,11 +29,11 @@ mDNS 属性 printf("MDNS Init failed: %d\n", err); return; } - + // 设置 hostname - mdns_hostname_set("my-esp32"); + mdns_hostname_set("my-{IDF_TARGET_PATH_NAME}"); // 设置默认实例 - mdns_instance_name_set("Jhon's ESP32 Thing"); + mdns_instance_name_set("Jhon's {IDF_TARGET_NAME} Thing"); } mDNS 服务 @@ -41,7 +41,7 @@ mDNS 服务 mDNS 可以广播设备能够提供的网络服务的相关信息,每个服务会由以下属性构成。 - * ``instance_name``:实例名(即易记的服务名),例如 ``Jhon's ESP32 Web Server``。如果没有定义,会使用 ``default_instance``。 + * ``instance_name``:实例名(即易记的服务名),例如 ``Jhon's {IDF_TARGET_NAME} Web Server``。如果没有定义,会使用 ``default_instance``。 * ``service_type``:(必需)服务类型,以下划线为前缀,`这里 `_ 列出了常见的类型。 * ``proto``:(必需)服务运行所依赖的协议,以下划线为前缀,例如 ``_tcp`` 或者 ``_udp``。 * ``port``:(必需)服务运行所用的端口号。 @@ -55,19 +55,19 @@ mDNS 可以广播设备能够提供的网络服务的相关信息,每个服务 mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0); mdns_service_add(NULL, "_arduino", "_tcp", 3232, NULL, 0); mdns_service_add(NULL, "_myservice", "_udp", 1234, NULL, 0); - + // 注意:必须先添加服务,然后才能设置其属性 // web 服务器使用自定义的实例名 - mdns_service_instance_name_set("_http", "_tcp", "Jhon's ESP32 Web Server"); + mdns_service_instance_name_set("_http", "_tcp", "Jhon's {IDF_TARGET_NAME} Web Server"); mdns_txt_item_t serviceTxtData[3] = { - {"board","esp32"}, + {"board","{IDF_TARGET_PATH_NAME}"}, {"u","user"}, {"p","password"} }; // 设置服务的文本数据(会释放并替换当前数据) mdns_service_txt_set("_http", "_tcp", serviceTxtData, 3); - + // 修改服务端口号 mdns_service_port_set("_myservice", "_udp", 4321); } @@ -161,9 +161,9 @@ mDNS 提供查询服务和解析主机 IP/IPv6 地址的方法。 使用上述方法的示例:: void my_app_some_method(){ - // 搜索 esp32-mdns.local - resolve_mdns_host("esp32-mdns"); - + // 搜索 {IDF_TARGET_PATH_NAME}-mdns.local + resolve_mdns_host("{IDF_TARGET_PATH_NAME}-mdns"); + // 搜索 HTTP 服务器 find_mdns_service("_http", "_tcp"); // 或者搜索文件服务器 From 2b7d43e1f82d5ae327c21166c50d404b547db9ec Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 3 Mar 2020 13:55:33 +0100 Subject: [PATCH 127/289] mdns: limit the GOT_IP6_EVENT to only known network interfaces * Original commit: espressif/esp-idf@ab8cab1c553ee5312ef47a7dea002f2585605006 --- components/mdns/mdns.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 9bee17076..711de2a45 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3176,8 +3176,10 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, case IP_EVENT_GOT_IP6: { mdns_if_t mdns_if = _mdns_get_if_from_esp_netif(interface); - _mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); - _mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4, NULL, 0, true); + if (mdns_if != MDNS_IF_MAX) { + _mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); + _mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4, NULL, 0, true); + } } break; From 07399011f70ed39b2703bc01c3ddbe4407380852 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 3 Mar 2020 13:57:32 +0100 Subject: [PATCH 128/289] examples: common connect code to ignore GOT_IP6_EVENT if comes from unrelated netif * Original commit: espressif/esp-idf@48fe3a13f5e8de3114242f640cc2aa23a87521c2 --- .../common_components/protocol_examples_common/connect.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 87b218047..9713edda2 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -65,8 +65,12 @@ static void on_got_ip(void *arg, esp_event_base_t event_base, static void on_got_ipv6(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { - ESP_LOGI(TAG, "Got IPv6 event!"); ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data; + if (event->esp_netif != s_example_esp_netif) { + ESP_LOGD(TAG, "Got IPv6 from another netif: ignored"); + return; + } + ESP_LOGI(TAG, "Got IPv6 event!"); memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); } From 2a23f355c72be72fb3aee1f72c24607a100f8b01 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 5 Mar 2020 07:38:21 +0100 Subject: [PATCH 129/289] examples: enable IPv6 in example common connect for esp32s2 Closes IDF-1115 * Original commit: espressif/esp-idf@0927ac648f04550f7e883ab96ad210d467104c74 --- .../protocol_examples_common/Kconfig.projbuild | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index f8ceb1e40..6965c46a0 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -176,8 +176,6 @@ menu "Example Connection Configuration" config EXAMPLE_CONNECT_IPV6 bool "Obtain IPv6 link-local address" - depends on IDF_TARGET_ESP32 - # ToDo: remove once IPV6 is supported on esp32s2 default y help By default, examples will wait until IPv4 and IPv6 addresses are obtained. From ef9a758662d779c4b6fd4c7011fac43f628ca806 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Fri, 28 Feb 2020 16:12:11 +0100 Subject: [PATCH 130/289] Add multi-target support for performance tests * Original commit: espressif/esp-idf@15884eccf293dde1916dbc663d6a53758ff5dab0 --- examples/protocols/mdns/mdns_example_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index af897bb79..c6c356f9e 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -103,7 +103,7 @@ def test_examples_protocol_mdns(env, extra_data): binary_file = os.path.join(dut1.app.binary_path, "mdns-test.bin") bin_size = os.path.getsize(binary_file) ttfw_idf.log_performance("mdns-test_bin_size", "{}KB".format(bin_size // 1024)) - ttfw_idf.check_performance("mdns-test_bin_size", bin_size // 1024) + ttfw_idf.check_performance("mdns-test_bin_size", bin_size // 1024, dut1.TARGET) # 1. start mdns application dut1.start_app() # 2. get the dut host name (and IP address) From 9d9aac1569210db17438a8f9f2463ef32f5a8dc2 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 6 Feb 2020 16:48:36 +0100 Subject: [PATCH 131/289] esp-netif: support for ipv6 addr types and indices * Original commit: espressif/esp-idf@56725fa6782743a5e774223a99aa9d3e4fa6ab02 --- examples/common_components/protocol_examples_common/connect.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 9713edda2..de7e98208 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -73,6 +73,8 @@ static void on_got_ipv6(void *arg, esp_event_base_t event_base, ESP_LOGI(TAG, "Got IPv6 event!"); memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); + ESP_LOGI(TAG, "IPv6 address: " IPV6STR ", index: %d, type: %d", IPV62STR(s_ipv6_addr), event->ip_index, esp_ip6_get_addr_type(&s_ipv6_addr)); + } #endif // CONFIG_EXAMPLE_CONNECT_IPV6 From e24cc7d1ae31c8fdee4cf80fe654908d786ec604 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 7 Feb 2020 09:19:55 +0100 Subject: [PATCH 132/289] common_connect: add support for getting multiple IPv6 addresses * Original commit: espressif/esp-idf@63aa0d6e9ce2406fba008b72a3fbc1954c83abf1 --- .../Kconfig.projbuild | 39 ++++++++++++++++++- .../protocol_examples_common/connect.c | 32 ++++++++++++--- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index 6965c46a0..f47b8a6af 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -175,9 +175,44 @@ menu "Example Connection Configuration" endif config EXAMPLE_CONNECT_IPV6 - bool "Obtain IPv6 link-local address" + bool "Obtain IPv6 address" default y help - By default, examples will wait until IPv4 and IPv6 addresses are obtained. + By default, examples will wait until IPv4 and IPv6 local link addresses are obtained. Disable this option if the network does not support IPv6. + Choose the preferred IPv6 address type if the connection code should wait until other than + the local link address gets assigned. + + if EXAMPLE_CONNECT_IPV6 + choice EXAMPLE_CONNECT_PREFERRED_IPV6 + prompt "Preferred IPv6 Type" + default EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK + help + Select which kind of IPv6 address the connect logic waits for. + + config EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK + bool "Local Link Address" + help + Blocks until Local link address assigned. + + config EXAMPLE_CONNECT_IPV6_PREF_GLOBAL + bool "Global Address" + help + Blocks until Global address assigned. + + config EXAMPLE_CONNECT_IPV6_PREF_SITE_LOCAL + bool "Site Local Address" + help + Blocks until Site link address assigned. + + config EXAMPLE_CONNECT_IPV6_PREF_UNIQUE_LOCAL + bool "Unique Local Link Address" + help + Blocks until Unique local address assigned. + + endchoice + + endif + + endmenu diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index de7e98208..e845837cb 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -30,6 +30,17 @@ #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 #define CONNECTED_BITS (GOT_IPV4_BIT | GOT_IPV6_BIT) + +#if defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK) +#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_LINK_LOCAL +#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_GLOBAL) +#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_GLOBAL +#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_SITE_LOCAL) +#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_SITE_LOCAL +#elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_UNIQUE_LOCAL) +#define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_UNIQUE_LOCAL +#endif // if-elif CONFIG_EXAMPLE_CONNECT_IPV6_PREF_... + #else #define CONNECTED_BITS (GOT_IPV4_BIT) #endif @@ -41,6 +52,16 @@ static esp_netif_t *s_example_esp_netif = NULL; #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 static esp_ip6_addr_t s_ipv6_addr; + +/* types of ipv6 addresses to be displayed on ipv6 events */ +static const char *s_ipv6_addr_types[] = { + "ESP_IP6_ADDR_IS_UNKNOWN", + "ESP_IP6_ADDR_IS_GLOBAL", + "ESP_IP6_ADDR_IS_LINK_LOCAL", + "ESP_IP6_ADDR_IS_SITE_LOCAL", + "ESP_IP6_ADDR_IS_UNIQUE_LOCAL", + "ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6" + }; #endif static const char *TAG = "example_connect"; @@ -70,11 +91,12 @@ static void on_got_ipv6(void *arg, esp_event_base_t event_base, ESP_LOGD(TAG, "Got IPv6 from another netif: ignored"); return; } - ESP_LOGI(TAG, "Got IPv6 event!"); - memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); - xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); - ESP_LOGI(TAG, "IPv6 address: " IPV6STR ", index: %d, type: %d", IPV62STR(s_ipv6_addr), event->ip_index, esp_ip6_get_addr_type(&s_ipv6_addr)); - + esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip); + ESP_LOGI(TAG, "Got IPv6 address: " IPV6STR ", type: %s", IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]); + if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) { + memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); + xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); + } } #endif // CONFIG_EXAMPLE_CONNECT_IPV6 From 123ae8db624d252e5d10dc6b0b727e6182f90638 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 19 Mar 2020 11:45:02 +0100 Subject: [PATCH 133/289] examples: add socket stdin utils to common connect component * Original commit: espressif/esp-idf@a5a750ba4898f35672e060204d3a37c35b2e6e08 --- .../protocol_examples_common/CMakeLists.txt | 2 +- .../addr_from_stdin.c | 65 +++++++++++++++++++ .../include/addr_from_stdin.h | 44 +++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 examples/common_components/protocol_examples_common/addr_from_stdin.c create mode 100644 examples/common_components/protocol_examples_common/include/addr_from_stdin.h diff --git a/examples/common_components/protocol_examples_common/CMakeLists.txt b/examples/common_components/protocol_examples_common/CMakeLists.txt index 7c4ebe34d..5c19957ba 100644 --- a/examples/common_components/protocol_examples_common/CMakeLists.txt +++ b/examples/common_components/protocol_examples_common/CMakeLists.txt @@ -1,4 +1,4 @@ -idf_component_register(SRCS "connect.c" "stdin_out.c" +idf_component_register(SRCS "connect.c" "stdin_out.c" "addr_from_stdin.c" INCLUDE_DIRS "include" PRIV_REQUIRES esp_netif ) diff --git a/examples/common_components/protocol_examples_common/addr_from_stdin.c b/examples/common_components/protocol_examples_common/addr_from_stdin.c new file mode 100644 index 000000000..460fe9a2e --- /dev/null +++ b/examples/common_components/protocol_examples_common/addr_from_stdin.c @@ -0,0 +1,65 @@ +#include +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "protocol_examples_common.h" + +#include "lwip/sockets.h" +#include +#include + +#define HOST_IP_SIZE 128 + +esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *addr_family, struct sockaddr_in6 *dest_addr) +{ + char host_ip[HOST_IP_SIZE]; + int len; + static bool already_init = false; + + // this function could be called multiple times -> make sure UART init runs only once + if (!already_init) { + example_configure_stdin_stdout(); + already_init = true; + } + + // ignore empty or LF only string (could receive from DUT class) + do { + fgets(host_ip, HOST_IP_SIZE, stdin); + len = strlen(host_ip); + } while (len<=1 && host_ip[0] == '\n'); + host_ip[len - 1] = '\0'; + + struct addrinfo hints, *addr_list, *cur; + memset( &hints, 0, sizeof( hints ) ); + + // run getaddrinfo() to decide on the IP protocol + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = sock_type; + hints.ai_protocol = IPPROTO_TCP; + if( getaddrinfo( host_ip, NULL, &hints, &addr_list ) != 0 ) { + return ESP_FAIL; + } + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) { + memcpy(dest_addr, cur->ai_addr, sizeof(*dest_addr)); + if (cur->ai_family == AF_INET) { + *ip_protocol = IPPROTO_IP; + *addr_family = AF_INET; + // add port number and return on first IPv4 match + ((struct sockaddr_in*)dest_addr)->sin_port = htons(port); + freeaddrinfo( addr_list ); + return ESP_OK; + + } else if (cur->ai_family == AF_INET6) { + *ip_protocol = IPPROTO_IPV6; + *addr_family = AF_INET6; + // add port and interface number and return on first IPv6 match + dest_addr->sin6_port = htons(port); + dest_addr->sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE); + freeaddrinfo( addr_list ); + return ESP_OK; + } + } + // no match found + freeaddrinfo( addr_list ); + return ESP_FAIL; +} \ No newline at end of file diff --git a/examples/common_components/protocol_examples_common/include/addr_from_stdin.h b/examples/common_components/protocol_examples_common/include/addr_from_stdin.h new file mode 100644 index 000000000..ab5043aed --- /dev/null +++ b/examples/common_components/protocol_examples_common/include/addr_from_stdin.h @@ -0,0 +1,44 @@ +/* Common utilities for socket address input interface: + The API get_addr_from_stdin() is mainly used by socket client examples which read IP address from stdin (if configured). + This option is typically used in the CI, but could be enabled in the project configuration. + In that case this component is used to receive a string that is evaluated and processed to output + socket structures to open a connectio + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwip/sys.h" +#include +#include + +/** + * @brief Read and evaluate IP address from stdin + * + * This API reads stdin and parses the input address using getaddrinfo() + * to fill in struct sockaddr_in6 (for both IPv4 and IPv6) used to open + * a socket. IP protocol is guessed from the IP address string. + * + * @param[in] port port number of expected connection + * @param[in] sock_type expected protocol: SOCK_STREAM or SOCK_DGRAM + * @param[out] ip_protocol resultant IP protocol: IPPROTO_IP or IPPROTO_IP6 + * @param[out] addr_family resultant address family: AF_INET or AF_INET6 + * @param[out] dest_addr sockaddr_in6 structure (for both IPv4 and IPv6) + * @return ESP_OK on success, ESP_FAIL otherwise + */ +esp_err_t get_addr_from_stdin(int port, int sock_type, + int *ip_protocol, + int *addr_family, + struct sockaddr_in6 *dest_addr); + +#ifdef __cplusplus +} +#endif \ No newline at end of file From ac70c9aba8799513ac392310cb27edc6ec59f30e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 26 Apr 2020 12:07:28 +0800 Subject: [PATCH 134/289] mdns: Remove mbedtls dependency mdns does not use mbedtls, so remove mbedtls dependency. Signed-off-by: Axel Lin * Original commit: espressif/esp-idf@f4a4549a344e7ff2444a188adbebbc136b47a7bb --- components/mdns/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index 4274d2a46..cd85cc88f 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -3,6 +3,6 @@ idf_component_register(SRCS "mdns.c" "mdns_networking.c" INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "private_include" - REQUIRES lwip mbedtls console esp_netif + REQUIRES lwip console esp_netif PRIV_REQUIRES esp_timer) From 331984474573a6f5d18d0095ac1e93e1a34930f2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 30 Apr 2020 14:17:50 +0800 Subject: [PATCH 135/289] mdns: Allow config mDNS task stack size Signed-off-by: Axel Lin Merges https://github.com/espressif/esp-idf/pull/5216 * Original commit: espressif/esp-idf@cf7e48c779edd84c3f99d5e8ed81027932302382 --- components/mdns/Kconfig | 6 ++++++ components/mdns/private_include/mdns_private.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig index ab5cd8012..72800aaa2 100644 --- a/components/mdns/Kconfig +++ b/components/mdns/Kconfig @@ -19,6 +19,12 @@ menu "mDNS" higher than priorities of system tasks. Compile time warning/error would be emitted if the chosen task priority were too high. + config MDNS_TASK_STACK_SIZE + int "mDNS task stack size" + default 4096 + help + Allows setting mDNS task stacksize. + choice MDNS_TASK_AFFINITY prompt "mDNS task affinity" default MDNS_TASK_AFFINITY_CPU0 diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index f572cc233..535c25f6b 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -56,7 +56,7 @@ #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 +#define MDNS_SERVICE_STACK_DEPTH CONFIG_MDNS_TASK_STACK_SIZE #define MDNS_TASK_PRIORITY CONFIG_MDNS_TASK_PRIORITY #if (MDNS_TASK_PRIORITY > ESP_TASK_PRIO_MAX) #error "mDNS task priority is higher than ESP_TASK_PRIO_MAX" From 54f5c6f29c17fd07b26bb35f0eb96a39a1fc3ce7 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 23 Apr 2020 16:23:46 +0200 Subject: [PATCH 136/289] examples: common connect component to use both interfaces at once * Original commit: espressif/esp-idf@06711c7c367cc89b3525e01c5dfe490edfe64c5a --- .../Kconfig.projbuild | 26 +-- .../protocol_examples_common/connect.c | 192 +++++++++++++----- .../include/protocol_examples_common.h | 14 ++ 3 files changed, 170 insertions(+), 62 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index f47b8a6af..eccf77889 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -1,18 +1,11 @@ menu "Example Connection Configuration" - choice EXAMPLE_CONNECT_INTERFACE - prompt "Connect using" - default EXAMPLE_CONNECT_WIFI + + config EXAMPLE_CONNECT_WIFI + bool "connect using WiFi interface" + default y help - Protocol examples can use Wi-Fi or Ethernet to connect to the network. - Choose which interface to use. - - config EXAMPLE_CONNECT_WIFI - bool "Wi-Fi" - - config EXAMPLE_CONNECT_ETHERNET - bool "Ethernet" - - endchoice + Protocol examples can use Wi-Fi and/or Ethernet to connect to the network. + Choose this option to connect with WiFi if EXAMPLE_CONNECT_WIFI config EXAMPLE_WIFI_SSID @@ -29,6 +22,13 @@ menu "Example Connection Configuration" Can be left blank if the network has no security set. endif + config EXAMPLE_CONNECT_ETHERNET + bool "connect using Ethernet interface" + default n + help + Protocol examples can use Wi-Fi and/or Ethernet to connect to the network. + Choose this option to connect with Ethernet + if EXAMPLE_CONNECT_ETHERNET choice EXAMPLE_USE_ETHERNET prompt "Ethernet Type" diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index e845837cb..653a43ea0 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -25,11 +25,9 @@ #include "lwip/err.h" #include "lwip/sys.h" -#define GOT_IPV4_BIT BIT(0) -#define GOT_IPV6_BIT BIT(1) - #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 -#define CONNECTED_BITS (GOT_IPV4_BIT | GOT_IPV6_BIT) +#define MAX_IP6_ADDRS_PER_NETIF (5) +#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces*2) #if defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK) #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_LINK_LOCAL @@ -42,12 +40,12 @@ #endif // if-elif CONFIG_EXAMPLE_CONNECT_IPV6_PREF_... #else -#define CONNECTED_BITS (GOT_IPV4_BIT) +#define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces) #endif -static EventGroupHandle_t s_connect_event_group; +static int s_active_interfaces = 0; +static xSemaphoreHandle s_semph_get_ip_addrs; static esp_ip4_addr_t s_ip_addr; -static const char *s_connection_name; static esp_netif_t *s_example_esp_netif = NULL; #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 @@ -66,19 +64,72 @@ static const char *s_ipv6_addr_types[] = { static const char *TAG = "example_connect"; -/* set up connection, Wi-Fi or Ethernet */ -static void start(void); +#if CONFIG_EXAMPLE_CONNECT_WIFI +static esp_netif_t* wifi_start(void); +static void wifi_stop(void); +#endif +#if CONFIG_EXAMPLE_CONNECT_ETHERNET +static esp_netif_t* eth_start(void); +static void eth_stop(void); +#endif + +/** + * @brief Checks the netif description if it contains specified prefix. + * All netifs created withing common connect component are prefixed with the module TAG, + * so it returns true if the specified netif is owned by this module + */ +static bool is_our_netif(const char *prefix, esp_netif_t *netif) +{ + return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix)-1) == 0; +} + +/* set up connection, Wi-Fi and/or Ethernet */ +static void start(void) +{ + +#if CONFIG_EXAMPLE_CONNECT_WIFI + s_example_esp_netif = wifi_start(); + s_active_interfaces++; +#endif + +#if CONFIG_EXAMPLE_CONNECT_ETHERNET + s_example_esp_netif = eth_start(); + s_active_interfaces++; +#endif + +#if CONFIG_EXAMPLE_CONNECT_WIFI && CONFIG_EXAMPLE_CONNECT_ETHERNET + /* if both intefaces at once, clear out to indicate that multiple netifs are active */ + s_example_esp_netif = NULL; +#endif + + s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0); +} /* tear down connection, release resources */ -static void stop(void); +static void stop(void) +{ +#if CONFIG_EXAMPLE_CONNECT_WIFI + wifi_stop(); + s_active_interfaces--; +#endif + +#if CONFIG_EXAMPLE_CONNECT_ETHERNET + eth_stop(); + s_active_interfaces--; +#endif +} static void on_got_ip(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { - ESP_LOGI(TAG, "Got IP event!"); ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; + if (!is_our_netif(TAG, event->esp_netif)) { + ESP_LOGW(TAG, "Got IPv4 from another interface \"%s\": ignored", esp_netif_get_desc(event->esp_netif)); + return; + } + ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip)); memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr)); - xEventGroupSetBits(s_connect_event_group, GOT_IPV4_BIT); + xSemaphoreGive(s_semph_get_ip_addrs); } #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 @@ -87,15 +138,16 @@ static void on_got_ipv6(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data; - if (event->esp_netif != s_example_esp_netif) { - ESP_LOGD(TAG, "Got IPv6 from another netif: ignored"); + if (!is_our_netif(TAG, event->esp_netif)) { + ESP_LOGW(TAG, "Got IPv6 from another netif: ignored"); return; } esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip); - ESP_LOGI(TAG, "Got IPv6 address: " IPV6STR ", type: %s", IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]); + ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif), + IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]); if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) { memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); - xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); + xSemaphoreGive(s_semph_get_ip_addrs); } } @@ -103,32 +155,47 @@ static void on_got_ipv6(void *arg, esp_event_base_t event_base, esp_err_t example_connect(void) { - if (s_connect_event_group != NULL) { + if (s_semph_get_ip_addrs != NULL) { return ESP_ERR_INVALID_STATE; } - s_connect_event_group = xEventGroupCreate(); start(); ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop)); - ESP_LOGI(TAG, "Waiting for IP"); - xEventGroupWaitBits(s_connect_event_group, CONNECTED_BITS, true, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to %s", s_connection_name); - ESP_LOGI(TAG, "IPv4 address: " IPSTR, IP2STR(&s_ip_addr)); + ESP_LOGI(TAG, "Waiting for IP(s)"); + for (int i=0; idel(s_phy)); ESP_ERROR_CHECK(s_mac->del(s_mac)); - esp_netif_destroy(s_example_esp_netif); + esp_netif_destroy(eth_netif); s_example_esp_netif = NULL; } @@ -334,3 +413,18 @@ esp_netif_t *get_example_netif(void) { return s_example_esp_netif; } + +esp_netif_t *get_example_netif_from_desc(const char *desc) +{ + esp_netif_t *netif = NULL; + char *expected_desc; + asprintf(&expected_desc, "%s: %s", TAG, desc); + while ((netif = esp_netif_next(netif)) != NULL) { + if (strcmp(esp_netif_get_desc(netif), expected_desc) == 0) { + free(expected_desc); + return netif; + } + } + free(expected_desc); + return netif; +} diff --git a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h index 98f67e348..859264df0 100644 --- a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h +++ b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h @@ -57,8 +57,22 @@ esp_err_t example_configure_stdin_stdout(void); /** * @brief Returns esp-netif pointer created by example_connect() * + * @note If multiple interfaces active at once, this API return NULL + * In that case the get_example_netif_from_desc() should be used + * to get esp-netif pointer based on interface description */ esp_netif_t *get_example_netif(void); + +/** + * @brief Returns esp-netif pointer created by example_connect() described by + * the supplied desc field + * + * @param desc Textual interface of created network interface, for example "sta" + * indicate default WiFi station, "eth" default Ethernet interface. + * + */ +esp_netif_t *get_example_netif_from_desc(const char *desc); + #ifdef __cplusplus } #endif From 2258d5bcefde2291f62bcb36686b644cbacd7720 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 15 May 2020 10:41:14 +0200 Subject: [PATCH 137/289] mdns-example: fail gracefully if mdns response not received within timeout If mdns answer hasn't been received within timeout, Value error would be raised, but the mdns-server-thread would still run, blocking CI jobs. Fixed by moving the raise statement within try-finally block * Original commit: espressif/esp-idf@3758177bf8c8a7f3c3a2789ad396a97fce16b196 --- examples/protocols/mdns/mdns_example_test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index c6c356f9e..acd29ae72 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -117,11 +117,11 @@ def test_examples_protocol_mdns(env, extra_data): stop_mdns_server.set() thread1.join() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') - # 3. check the mdns name is accessible - if not esp_answered.wait(timeout=30): - raise ValueError('Test has failed: did not receive mdns answer within timeout') - # 4. check DUT output if mdns advertized host is resolved try: + # 3. check the mdns name is accessible + if not esp_answered.wait(timeout=30): + raise ValueError('Test has failed: did not receive mdns answer within timeout') + # 4. check DUT output if mdns advertized host is resolved dut1.expect(re.compile(r"mdns-test: Query A: tinytester.local resolved to: 127.0.0.1"), timeout=30) dut1.expect(re.compile(r"mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) dut1.expect(re.compile(r"mdns-test: getaddrinfo: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) From 12fb6d8e15108588d216ee8b187c8d1bb3c1615d Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Mon, 18 May 2020 16:51:57 +0530 Subject: [PATCH 138/289] protocol_examples_common: keep buffering enabled on stdout - Newlib uses significantly more stack space when printing to an unbuffered stream - For examples tests, disabling buffering on stdout is not really required This issue was found during one of the OTA example test failure, root cause being stack overflow in `esp_event` task. * Original commit: espressif/esp-idf@7925ba245d1aada6a8c0d75b00dc7f1d0fb42be2 --- examples/common_components/protocol_examples_common/stdin_out.c | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/common_components/protocol_examples_common/stdin_out.c b/examples/common_components/protocol_examples_common/stdin_out.c index 10cc2167f..8f95b8ac7 100644 --- a/examples/common_components/protocol_examples_common/stdin_out.c +++ b/examples/common_components/protocol_examples_common/stdin_out.c @@ -17,7 +17,6 @@ esp_err_t example_configure_stdin_stdout(void) { // Initialize VFS & UART so we can use std::cout/cin setvbuf(stdin, NULL, _IONBF, 0); - setvbuf(stdout, NULL, _IONBF, 0); /* Install UART driver for interrupt-driven reads and writes */ ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM, 256, 0, 0, NULL, 0) ); From f1f6c5de058aa4be751dcc6e3c0022f2d9f489a7 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 22 May 2020 10:41:55 +0200 Subject: [PATCH 139/289] examples: common connect: fix build error if ipv6 disabled Declaration of local variable esp_ip6_addr_t ip6[]; was active even if IPV6 disabled in sdkconfig. Introduced in 62e39adff8db0605875fe7103c8919fbfe229f20 * Original commit: espressif/esp-idf@5c6bca69a5f12b3039c6fcf76d8e480cd541bc65 --- examples/common_components/protocol_examples_common/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 653a43ea0..ed502210c 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -167,7 +167,6 @@ esp_err_t example_connect(void) // iterate over active interfaces, and print out IPs of "our" netifs esp_netif_t *netif = NULL; esp_netif_ip_info_t ip; - esp_ip6_addr_t ip6[MAX_IP6_ADDRS_PER_NETIF]; for (int i=0; i Date: Fri, 19 Jun 2020 12:00:58 +0800 Subject: [PATCH 140/289] esp_rom: extract common GPIO apis into esp_rom_gpio.h * Original commit: espressif/esp-idf@a4d0033c034260f016d4657d797063e0ed326d24 --- examples/protocols/mdns/main/mdns_example_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index c15f37d18..7d713c712 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -139,7 +139,7 @@ static void query_mdns_host(const char * host_name) static void initialise_button(void) { gpio_config_t io_conf = {0}; - io_conf.intr_type = GPIO_PIN_INTR_DISABLE; + io_conf.intr_type = GPIO_INTR_DISABLE; io_conf.pin_bit_mask = BIT64(EXAMPLE_BUTTON_GPIO); io_conf.mode = GPIO_MODE_INPUT; io_conf.pull_up_en = 1; From ad67a23097b09be63ac5afda44e3946479af96be Mon Sep 17 00:00:00 2001 From: houwenxiang Date: Tue, 9 Jun 2020 17:00:47 +0800 Subject: [PATCH 141/289] vfs: support vfs uart set line endings with specified uart number * Original commit: espressif/esp-idf@8e00522cd7a03d8f97036d0069b7d7556ddf49f0 --- .../common_components/protocol_examples_common/stdin_out.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/common_components/protocol_examples_common/stdin_out.c b/examples/common_components/protocol_examples_common/stdin_out.c index 8f95b8ac7..b57e0e715 100644 --- a/examples/common_components/protocol_examples_common/stdin_out.c +++ b/examples/common_components/protocol_examples_common/stdin_out.c @@ -22,8 +22,8 @@ esp_err_t example_configure_stdin_stdout(void) 256, 0, 0, NULL, 0) ); /* Tell VFS to use UART driver */ esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); - esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR); /* Move the caret to the beginning of the next line on '\n' */ - esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); + esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF); return ESP_OK; } From 07f57523c86ddfd604b5d55a81f474d58ec29961 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 5 Jun 2020 14:29:32 +0200 Subject: [PATCH 142/289] examples: common connect to also support no connection flow if no inteface chosen This is useful for testing if there's no need for external network and connection * Original commit: espressif/esp-idf@085d2b8d25bee96df6f3f5410cd31d80a8f11675 --- .../protocol_examples_common/Kconfig.projbuild | 1 + .../protocol_examples_common/connect.c | 13 ++++++++++++- .../include/protocol_examples_common.h | 5 +++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index eccf77889..5875ccdfa 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -177,6 +177,7 @@ menu "Example Connection Configuration" config EXAMPLE_CONNECT_IPV6 bool "Obtain IPv6 address" default y + depends on EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET help By default, examples will wait until IPv4 and IPv6 local link addresses are obtained. Disable this option if the network does not support IPv6. diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index ed502210c..dfba995e8 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -43,9 +43,10 @@ #define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces) #endif +#define EXAMPLE_DO_CONNECT CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET + static int s_active_interfaces = 0; static xSemaphoreHandle s_semph_get_ip_addrs; -static esp_ip4_addr_t s_ip_addr; static esp_netif_t *s_example_esp_netif = NULL; #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 @@ -102,7 +103,11 @@ static void start(void) s_example_esp_netif = NULL; #endif +#if EXAMPLE_DO_CONNECT + /* create semaphore if at least one interface is active */ s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0); +#endif + } /* tear down connection, release resources */ @@ -119,6 +124,9 @@ static void stop(void) #endif } +#if EXAMPLE_DO_CONNECT +static esp_ip4_addr_t s_ip_addr; + static void on_got_ip(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { @@ -131,6 +139,7 @@ static void on_got_ip(void *arg, esp_event_base_t event_base, memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr)); xSemaphoreGive(s_semph_get_ip_addrs); } +#endif #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 @@ -155,9 +164,11 @@ static void on_got_ipv6(void *arg, esp_event_base_t event_base, esp_err_t example_connect(void) { +#if EXAMPLE_DO_CONNECT if (s_semph_get_ip_addrs != NULL) { return ESP_ERR_INVALID_STATE; } +#endif start(); ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop)); ESP_LOGI(TAG, "Waiting for IP(s)"); diff --git a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h index 859264df0..8c0a0a30e 100644 --- a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h +++ b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h @@ -24,6 +24,11 @@ extern "C" { #define EXAMPLE_INTERFACE get_example_netif() #endif +#if !defined (CONFIG_EXAMPLE_CONNECT_ETHERNET) && !defined (CONFIG_EXAMPLE_CONNECT_WIFI) +// This is useful for some tests which do not need a network connection +#define EXAMPLE_INTERFACE NULL +#endif + /** * @brief Configure Wi-Fi or Ethernet, connect, wait for IP * From 78f71ecdf686dfae1f23c046526bf2d9ed234865 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 27 Jul 2020 07:14:34 +0200 Subject: [PATCH 143/289] mdns: Fix include query ID in reponses Closes https://github.com/espressif/esp-idf/issues/5574 * Original commit: espressif/esp-idf@f62e321d87c1d520cccca951715c27730e06607a --- components/mdns/mdns.c | 3 +++ components/mdns/private_include/mdns_private.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 711de2a45..750456c7e 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -980,6 +980,7 @@ static void _mdns_dispatch_tx_packet(mdns_tx_packet_t * p) uint8_t count; _mdns_set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, p->flags); + _mdns_set_u16(packet, MDNS_HEAD_ID_OFFSET, p->id); count = 0; q = p->questions; @@ -1259,6 +1260,7 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed } packet->flags = MDNS_FLAGS_AUTHORITATIVE; packet->distributed = parsed_packet->distributed; + packet->id = parsed_packet->id; mdns_parsed_question_t * q = parsed_packet->questions; while (q) { @@ -2662,6 +2664,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) parsed_packet->multicast = packet->multicast; parsed_packet->authoritative = header.flags.value == MDNS_FLAGS_AUTHORITATIVE; parsed_packet->distributed = header.flags.value == MDNS_FLAGS_DISTRIBUTED; + parsed_packet->id = header.id; ip_addr_copy(parsed_packet->src, packet->src); parsed_packet->src_port = packet->src_port; diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 535c25f6b..f14619f06 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -236,6 +236,7 @@ typedef struct { uint8_t distributed; mdns_parsed_question_t * questions; mdns_parsed_record_t * records; + uint16_t id; } mdns_parsed_packet_t; typedef struct { @@ -304,6 +305,7 @@ typedef struct mdns_tx_packet_s { mdns_out_answer_t * servers; mdns_out_answer_t * additional; bool queued; + uint16_t id; } mdns_tx_packet_t; typedef struct { From 6021a886575c0c943d21bdd284c8dce0a75c3b78 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 28 Jul 2020 09:06:12 +0200 Subject: [PATCH 144/289] mdns: Support queries in responses in mDNS non-strict mode By default adds original queries to responses in order to be resolved by some resolvers, such as lwIP mdns library. This functionality however is discouraged by the RFC6762, so it could be disabled in menuconfig if MDNS_STRICT_MODE configured Closes https://github.com/espressif/esp-idf/issues/5521 * Original commit: espressif/esp-idf@bcfa36db8ffff997f1f95eaf6b011ffc4d46a10f --- components/mdns/mdns.c | 11 +++++++++++ components/mdns/private_include/mdns_private.h | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 750456c7e..debc02651 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1313,6 +1313,17 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed _mdns_free_tx_packet(packet); return; } +#ifdef MDNS_REPEAT_QUERY_IN_RESPONSE + mdns_out_question_t * out_question = malloc(sizeof(mdns_out_question_t)); + if (out_question == NULL) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return; + } + memcpy(out_question, q, sizeof(mdns_out_question_t)); + out_question->next = NULL; + queueToEnd(mdns_out_question_t, packet->questions, out_question); +#endif // MDNS_REPEAT_QUERY_IN_RESPONSE } else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, send_flush, false)) { _mdns_free_tx_packet(packet); return; diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index f14619f06..3fa57e597 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -23,6 +23,22 @@ #define _mdns_dbg_printf(...) printf(__VA_ARGS__) #endif +/** mDNS strict mode: Set this to 1 for the mDNS library to strictly follow the RFC6762: + * Strict features: + * - to do not set original questions in response packets per RFC6762, sec 6 + * + * The actual configuration is 0, i.e. non-strict mode, since some implementations, + * such as lwIP mdns resolver (used by standard POSIX API like getaddrinfo, gethostbyname) + * could not correctly resolve advertised names. + */ +#define MDNS_STRICT_MODE 0 + +#if !MDNS_STRICT_MODE +/* mDNS responders sometimes repeat queries in responses + * but according to RFC6762, sec 6: Responses MUST NOT contain + * any item in question field */ +#define MDNS_REPEAT_QUERY_IN_RESPONSE 1 +#endif /** The maximum number of services */ #define MDNS_MAX_SERVICES CONFIG_MDNS_MAX_SERVICES From ed77d65a82a55ad06fee6581b206c47c4320713f Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 29 Jul 2020 10:18:34 +0200 Subject: [PATCH 145/289] examples: Common connect component: Unregister shutdown handler on disconnection To be able to connect smoothly after disconnecting, we have to unregister all handlers including shutdown handler on disconnection * Original commit: espressif/esp-idf@52a7721bf7c4b61b4a729cb7df72038552449418 --- examples/common_components/protocol_examples_common/connect.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index dfba995e8..6ef826f42 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -207,6 +207,7 @@ esp_err_t example_disconnect(void) vSemaphoreDelete(s_semph_get_ip_addrs); s_semph_get_ip_addrs = NULL; stop(); + ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&stop)); return ESP_OK; } From 110f1f652d3f571a3afa4682b539f51fa11bb153 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 30 Jul 2020 16:12:37 +0200 Subject: [PATCH 146/289] mdns test: Add test to resolve esp32 hostname with DiG * Original commit: espressif/esp-idf@81e89476fed3e751e9ea32c4a9aee8c48acda1ac --- examples/protocols/mdns/mdns_example_test.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index acd29ae72..2acf45885 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -6,12 +6,11 @@ import struct import dpkt import dpkt.dns from threading import Thread, Event +import subprocess from tiny_test_fw import DUT import ttfw_idf -# g_run_server = True -# g_done = False stop_mdns_server = Event() esp_answered = Event() @@ -112,7 +111,8 @@ def test_examples_protocol_mdns(env, extra_data): thread1 = Thread(target=mdns_server, args=(specific_host,)) thread1.start() try: - dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) + ip_address = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30)[0] + print("Connected to AP with IP: {}".format(ip_address)) except DUT.ExpectTimeout: stop_mdns_server.set() thread1.join() @@ -125,6 +125,13 @@ def test_examples_protocol_mdns(env, extra_data): dut1.expect(re.compile(r"mdns-test: Query A: tinytester.local resolved to: 127.0.0.1"), timeout=30) dut1.expect(re.compile(r"mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) dut1.expect(re.compile(r"mdns-test: getaddrinfo: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) + # 5. check the DUT answers to `dig` command + dig_output = subprocess.check_output(['dig', '+short', '-p', '5353', '@224.0.0.251', + '{}.local'.format(specific_host)]) + print('Resolving {} using "dig" succeeded with:\n{}'.format(specific_host, dig_output)) + if not ip_address.encode('utf-8') in dig_output: + raise ValueError("Test has failed: Incorrectly resolved DUT hostname using dig" + "Output should've contained DUT's IP address:{}".format(ip_address)) finally: stop_mdns_server.set() thread1.join() From 9772e49b26a75061e55dd09d95915d1580f0c7f5 Mon Sep 17 00:00:00 2001 From: Jakob Hasse Date: Wed, 5 Aug 2020 10:16:32 +0800 Subject: [PATCH 147/289] cmock: added cmock as component * changing dependencies from unity->cmock * added component.mk and Makefile.projbuild * ignore test dir in gen_esp_err_to_name.py * added some brief introduction of CMock in IDF * Original commit: espressif/esp-idf@20c068ef3b49999387896b90f8011b02f718485f --- components/mdns/test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/test/CMakeLists.txt b/components/mdns/test/CMakeLists.txt index 516ee0097..a24aa2433 100644 --- a/components/mdns/test/CMakeLists.txt +++ b/components/mdns/test/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRC_DIRS "." - PRIV_REQUIRES unity test_utils mdns) \ No newline at end of file + PRIV_REQUIRES cmock test_utils mdns) \ No newline at end of file From e0bc60a58602b484fd07e49b67edaac5c6670da9 Mon Sep 17 00:00:00 2001 From: "suren.gabrielyan" Date: Thu, 23 Jul 2020 17:16:15 +0400 Subject: [PATCH 148/289] mdns, dns, dhcp, dhcps: update fuzzer test to work in CI Closes: IDF-1861 and IDF-1990 * Original commit: espressif/esp-idf@a43c06a592bcf9404297b22268c33bb7a246632c --- .../mdns/test_afl_fuzz_host/CMakeLists.txt | 8 + components/mdns/test_afl_fuzz_host/Makefile | 43 +- .../mdns/test_afl_fuzz_host/esp32_compat.h | 82 +--- .../mdns/test_afl_fuzz_host/esp32_mock.c | 1 - .../mdns/test_afl_fuzz_host/esp32_mock.h | 28 +- components/mdns/test_afl_fuzz_host/esp_attr.h | 3 + .../esp_netif_loopback_mock.c | 35 ++ .../esp_netif_objects_mock.c | 71 +++ .../mdns/test_afl_fuzz_host/mdns_mock.h | 5 + .../mdns/test_afl_fuzz_host/sdkconfig.h | 425 ++++++++++++++++++ 10 files changed, 597 insertions(+), 104 deletions(-) create mode 100644 components/mdns/test_afl_fuzz_host/CMakeLists.txt create mode 100644 components/mdns/test_afl_fuzz_host/esp_attr.h create mode 100644 components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c create mode 100644 components/mdns/test_afl_fuzz_host/esp_netif_objects_mock.c create mode 100644 components/mdns/test_afl_fuzz_host/mdns_mock.h create mode 100644 components/mdns/test_afl_fuzz_host/sdkconfig.h diff --git a/components/mdns/test_afl_fuzz_host/CMakeLists.txt b/components/mdns/test_afl_fuzz_host/CMakeLists.txt new file mode 100644 index 000000000..453dbc3dd --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(fuzz_test_update) + diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 6d19d3bf0..e8ad15232 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -1,9 +1,42 @@ TEST_NAME=test FUZZ=afl-fuzz COMPONENTS_DIR=../.. -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 +COMPILER_ICLUDE_DIR=$(shell echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf) + +CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversion -Wno-macro-redefined -Wno-int-to-void-pointer-cast -DHOOK_MALLOC_FAILED -DESP_EVENT_H_ -D__ESP_LOG_H__ -DMDNS_TEST_MODE \ + -I. -I.. -I../include -I../private_include -I ./build/config -include esp32_compat.h \ + -I$(COMPONENTS_DIR) \ + -I$(COMPONENTS_DIR)/driver/include \ + -I$(COMPONENTS_DIR)/esp_common/include \ + -I$(COMPONENTS_DIR)/esp_event/include \ + -I$(COMPONENTS_DIR)/esp_eth/include \ + -I$(COMPONENTS_DIR)/esp_netif/include \ + -I$(COMPONENTS_DIR)/esp_netif/private_include \ + -I$(COMPONENTS_DIR)/esp_netif/lwip \ + -I$(COMPONENTS_DIR)/esp_rom/include \ + -I$(COMPONENTS_DIR)/esp_system/include \ + -I$(COMPONENTS_DIR)/esp_timer/include \ + -I$(COMPONENTS_DIR)/esp_wifi/include \ + -I$(COMPONENTS_DIR)/freertos/xtensa/include \ + -I$(COMPONENTS_DIR)/freertos \ + -I$(COMPONENTS_DIR)/freertos/include \ + -I$(COMPONENTS_DIR)/hal/include \ + -I$(COMPONENTS_DIR)/hal/esp32/include \ + -I$(COMPONENTS_DIR)/heap/include \ + -I$(COMPONENTS_DIR)/log/include \ + -I$(COMPONENTS_DIR)/lwip/lwip/src/include \ + -I$(COMPONENTS_DIR)/lwip/port/esp32/include \ + -I$(COMPONENTS_DIR)/lwip/lwip/src/include/lwip/apps \ + -I$(COMPONENTS_DIR)/soc/include \ + -I$(COMPONENTS_DIR)/soc/soc/include \ + -I$(COMPONENTS_DIR)/soc/soc/esp32/include \ + -I$(COMPONENTS_DIR)/soc/src/esp32/include \ + -I$(COMPONENTS_DIR)/tcpip_adapter/include \ + -I$(COMPONENTS_DIR)/xtensa/include \ + -I$(COMPONENTS_DIR)/xtensa/esp32/include \ + -I$(COMPILER_ICLUDE_DIR)/include + + MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h ifeq ($(INSTR),off) CC=gcc @@ -14,7 +47,7 @@ else endif CPP=$(CC) LD=$(CC) -OBJECTS=mdns.o esp32_mock.o test.o +OBJECTS=esp32_mock.o esp_netif_loopback_mock.o mdns.o test.o esp_netif_objects_mock.o OS := $(shell uname) ifeq ($(OS),Darwin) @@ -32,7 +65,7 @@ all: $(TEST_NAME) mdns.o: ../mdns.c @echo "[CC] $<" - @$(CC) $(CFLAGS) $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@ + @$(CC) $(CFLAGS) --include mdns_mock.h $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@ $(TEST_NAME): $(OBJECTS) @echo "[LD] $@" diff --git a/components/mdns/test_afl_fuzz_host/esp32_compat.h b/components/mdns/test_afl_fuzz_host/esp32_compat.h index 62c77a768..e8a998e29 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_compat.h +++ b/components/mdns/test_afl_fuzz_host/esp32_compat.h @@ -33,10 +33,6 @@ #include #include -#define CONFIG_MDNS_MAX_SERVICES 25 - -#define ERR_OK 0 -#define ESP_OK 0 #define ESP_FAIL -1 #define ESP_ERR_NO_MEM 0x101 @@ -57,16 +53,24 @@ #define portMAX_DELAY 0xFFFFFFFF #define portTICK_PERIOD_MS 1 #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_SYSTEM_H__ +#define INC_TASK_H #define xSemaphoreTake(s,d) #define xTaskDelete(a) #define vTaskDelete(a) free(a) #define xSemaphoreGive(s) +#define xQueueCreateMutex(s) #define _mdns_pcb_init(a,b) true -#define _mdns_pcb_deinit(a,b) true +#define _mdns_pcb_deinit(a,b) true #define xSemaphoreCreateMutex() malloc(1) #define xSemaphoreCreateBinary() malloc(1) #define vSemaphoreDelete(s) free(s) +#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U #define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1) #define vTaskDelay(m) usleep((m)*0) #define pbuf_free(p) free(p) @@ -84,9 +88,6 @@ #define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) #define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) -#define IPADDR_TYPE_V4 0U -#define IPADDR_TYPE_V6 6U -#define IPADDR_TYPE_ANY 46U #define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) #define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \ IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0) @@ -102,60 +103,14 @@ typedef void * SemaphoreHandle_t; typedef void * xQueueHandle; typedef void * QueueHandle_t; typedef void * TaskHandle_t; -typedef void * esp_timer_handle_t; typedef uint32_t TickType_t; typedef uint32_t portTickType; -typedef enum { - WIFI_MODE_NULL = 0, /**< null mode */ - WIFI_MODE_STA, /**< WiFi station mode */ - WIFI_MODE_AP, /**< WiFi soft-AP mode */ - WIFI_MODE_APSTA, /**< WiFi station + soft-AP mode */ - 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 */ @@ -178,14 +133,6 @@ struct ip6_addr { }; typedef struct ip6_addr ip6_addr_t; -typedef struct _ip_addr { - union { - ip6_addr_t ip6; - ip4_addr_t ip4; - } u_addr; - uint8_t type; -} ip_addr_t; - typedef struct { ip4_addr_t ip; ip4_addr_t netmask; @@ -203,19 +150,8 @@ typedef struct { ip6_addr_t ip; } tcpip_adapter_ip6_info_t; -typedef struct { - 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) -{ - *mode = WIFI_MODE_APSTA; - return ESP_OK; -} - struct pbuf { struct pbuf *next; void *payload; diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.c b/components/mdns/test_afl_fuzz_host/esp32_mock.c index 0fa2c0a68..89efa55fb 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.c +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.c @@ -10,7 +10,6 @@ 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, diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h index 4a441a4ae..631694709 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.h @@ -1,33 +1,11 @@ #ifndef ESP32_MOCK_H_ #define ESP32_MOCK_H_ +#include "esp_timer.h" typedef void (*esp_timer_cb_t)(void* arg); -typedef enum -{ - ESP_TIMER_TASK, //!< Callback is called from timer task -} esp_timer_dispatch_t; - -typedef struct -{ - esp_timer_cb_t callback; //!< Function to call when timer expires - void* arg; //!< Argument to pass to the callback - esp_timer_dispatch_t dispatch_method; //!< Call the callback from task or from ISR - const char* name; //!< Timer name, used in esp_timer_dump function -} esp_timer_create_args_t; - -esp_err_t esp_timer_delete(esp_timer_handle_t timer); - -esp_err_t esp_timer_stop(esp_timer_handle_t timer); - -esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period); - -esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, - esp_timer_handle_t* out_handle); - - // Queue mock - QueueHandle_t xQueueCreate( uint32_t uxQueueLength, +QueueHandle_t xQueueCreate( uint32_t uxQueueLength, uint32_t uxItemSize ); void vQueueDelete( QueueHandle_t xQueue ); @@ -46,4 +24,4 @@ esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id #define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len -#endif /* ESP32_MOCK_H_ */ \ No newline at end of file +#endif /* ESP32_MOCK_H_ */ diff --git a/components/mdns/test_afl_fuzz_host/esp_attr.h b/components/mdns/test_afl_fuzz_host/esp_attr.h new file mode 100644 index 000000000..abbb3b3e0 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/esp_attr.h @@ -0,0 +1,3 @@ +#pragma once +#define IRAM_ATTR +#define FLAG_ATTR(TYPE) diff --git a/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c b/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c new file mode 100644 index 000000000..2d52c15a0 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c @@ -0,0 +1,35 @@ +// Copyright 2020 Espressif Systems (Shanghai) CO LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_netif_lwip_internal.h" + +esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) +{ + return ESP_ERR_NOT_SUPPORTED; +} + +esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) +{ + return ESP_ERR_NOT_SUPPORTED; +} + +const char *esp_netif_get_ifkey(esp_netif_t *esp_netif) +{ + return esp_netif->if_key; +} + +esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6) +{ + return ESP_ERR_NOT_SUPPORTED; +} diff --git a/components/mdns/test_afl_fuzz_host/esp_netif_objects_mock.c b/components/mdns/test_afl_fuzz_host/esp_netif_objects_mock.c new file mode 100644 index 000000000..9d0213082 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/esp_netif_objects_mock.c @@ -0,0 +1,71 @@ +// Copyright 2020 Espressif Systems (Shanghai) CO LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_netif.h" +#include "sys/queue.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "esp_netif_private.h" +#include + +// +// Purpose of this module is to provide list of esp-netif structures +// - this module has no dependency on a specific network stack (lwip) +// + +struct slist_netifs_s { + esp_netif_t *netif; + SLIST_ENTRY(slist_netifs_s) next; +}; + +SLIST_HEAD(slisthead, slist_netifs_s) s_head = { .slh_first = NULL, }; + +static size_t s_esp_netif_counter = 0; + +ESP_EVENT_DEFINE_BASE(IP_EVENT); + +// +// List manipulation functions +// +esp_err_t esp_netif_add_to_list(esp_netif_t *netif) +{ + return ESP_OK; +} + + +esp_err_t esp_netif_remove_from_list(esp_netif_t *netif) +{ + return ESP_ERR_NOT_FOUND; +} + +size_t esp_netif_get_nr_of_ifs(void) +{ + return s_esp_netif_counter; +} + +esp_netif_t* esp_netif_next(esp_netif_t* netif) +{ + return NULL; +} + +esp_netif_t* esp_netif_next_unsafe(esp_netif_t* netif) +{ + return NULL; +} + +esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key) +{ + return NULL; +} diff --git a/components/mdns/test_afl_fuzz_host/mdns_mock.h b/components/mdns/test_afl_fuzz_host/mdns_mock.h new file mode 100644 index 000000000..73ae1568a --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/mdns_mock.h @@ -0,0 +1,5 @@ +#pragma once +#define ERR_OK 0 +#define IPADDR_TYPE_V4 0U +#define IPADDR_TYPE_V6 6U +#define IPADDR_TYPE_ANY 46U diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h new file mode 100644 index 000000000..335b03994 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -0,0 +1,425 @@ +/* + * This config file commited in order to not run `idf.py reconfigure` each time when running fuzzer test. You can modify it manually or run `idf.py reconfigure` to generate new one if needed. + * Espressif IoT Development Framework (ESP-IDF) Configuration Header + */ +#pragma once +#define CONFIG_IDF_CMAKE 1 +#define CONFIG_IDF_TARGET "esp32" +#define CONFIG_IDF_TARGET_ESP32 1 +#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 +#define CONFIG_SDK_TOOLPREFIX "xtensa-esp32-elf-" +#define CONFIG_APP_BUILD_TYPE_APP_2NDBOOT 1 +#define CONFIG_APP_BUILD_GENERATE_BINARIES 1 +#define CONFIG_APP_BUILD_BOOTLOADER 1 +#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1 +#define CONFIG_APP_COMPILE_TIME_DATE 1 +#define CONFIG_APP_RETRIEVE_LEN_ELF_SHA 16 +#define CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL_INFO 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL 3 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 +#define CONFIG_BOOTLOADER_WDT_ENABLE 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#define CONFIG_BOOTLOADER_RESERVE_RTC_SIZE 0x0 +#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 +#define CONFIG_ESPTOOLPY_WITH_STUB 1 +#define CONFIG_ESPTOOLPY_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" +#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB" +#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B 1 +#define CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL 115200 +#define CONFIG_ESPTOOLPY_MONITOR_BAUD 115200 +#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_COMPILER_OPTIMIZATION_DEFAULT 1 +#define CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE 1 +#define CONFIG_COMPILER_STACK_CHECK_MODE_NONE 1 +#define CONFIG_APPTRACE_DEST_NONE 1 +#define CONFIG_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF 0 +#define CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_PINNED_TO_CORE 0 +#define CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF 1 +#define CONFIG_BT_RESERVE_DRAM 0x0 +#define CONFIG_COAP_MBEDTLS_PSK 1 +#define CONFIG_COAP_LOG_DEFAULT_LEVEL 0 +#define CONFIG_ADC_DISABLE_DAC 1 +#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 +#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 +#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 +#define CONFIG_EFUSE_MAX_BLK_LEN 192 +#define CONFIG_ESP_TLS_USING_MBEDTLS 1 +#define CONFIG_ESP32_REV_MIN_0 1 +#define CONFIG_ESP32_REV_MIN 0 +#define CONFIG_ESP32_DPORT_WORKAROUND 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_ESP32_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR 1 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES 4 +#define CONFIG_ESP32_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_ESP32_DEBUG_OCDAWARE 1 +#define CONFIG_ESP32_BROWNOUT_DET 1 +#define CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP32_BROWNOUT_DET_LVL 0 +#define CONFIG_ESP32_REDUCE_PHY_TX_POWER 1 +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 +#define CONFIG_ESP32_RTC_CLK_SRC_INT_RC 1 +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 +#define CONFIG_ESP32_XTAL_FREQ_40 1 +#define CONFIG_ESP32_XTAL_FREQ 40 +#define CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL 5 +#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 +#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 +#define CONFIG_ADC_CAL_LUT_ENABLE 1 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_ESP_IPC_USES_CALLERS_PRIORITY 1 +#define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048 +#define CONFIG_ESP_CONSOLE_UART_DEFAULT 1 +#define CONFIG_ESP_CONSOLE_UART_NUM 0 +#define CONFIG_ESP_CONSOLE_UART_TX_GPIO 1 +#define CONFIG_ESP_CONSOLE_UART_RX_GPIO 3 +#define CONFIG_ESP_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_ESP_INT_WDT 1 +#define CONFIG_ESP_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESP_INT_WDT_CHECK_CPU1 1 +#define CONFIG_ESP_TASK_WDT 1 +#define CONFIG_ESP_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT_OFFSET 2 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH 1 +#define CONFIG_ETH_ENABLED 1 +#define CONFIG_ETH_USE_ESP32_EMAC 1 +#define CONFIG_ETH_PHY_INTERFACE_RMII 1 +#define CONFIG_ETH_RMII_CLK_INPUT 1 +#define CONFIG_ETH_RMII_CLK_IN_GPIO 0 +#define CONFIG_ETH_DMA_BUFFER_SIZE 512 +#define CONFIG_ETH_DMA_RX_BUFFER_NUM 10 +#define CONFIG_ETH_DMA_TX_BUFFER_NUM 10 +#define CONFIG_ETH_USE_SPI_ETHERNET 1 +#define CONFIG_ESP_EVENT_POST_FROM_ISR 1 +#define CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 1 +#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 +#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 +#define CONFIG_HTTPD_MAX_URI_LEN 512 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 +#define CONFIG_HTTPD_PURGE_BUF_LEN 32 +#define CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_ESP_NETIF_TCPIP_LWIP 1 +#define CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER 1 +#define CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT 1 +#define CONFIG_ESP_TIMER_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_TIMER_IMPL_TG0_LAC 1 +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 +#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1 +#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752 +#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 +#define CONFIG_ESP32_WIFI_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_RX_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE 1 +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_FMB_COMM_MODE_RTU_EN 1 +#define CONFIG_FMB_COMM_MODE_ASCII_EN 1 +#define CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND 150 +#define CONFIG_FMB_MASTER_DELAY_MS_CONVERT 200 +#define CONFIG_FMB_QUEUE_LENGTH 20 +#define CONFIG_FMB_SERIAL_TASK_STACK_SIZE 2048 +#define CONFIG_FMB_SERIAL_BUF_SIZE 256 +#define CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB 8 +#define CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS 1000 +#define CONFIG_FMB_SERIAL_TASK_PRIO 10 +#define CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT 20 +#define CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE 20 +#define CONFIG_FMB_CONTROLLER_STACK_SIZE 4096 +#define CONFIG_FMB_EVENT_QUEUE_TIMEOUT 20 +#define CONFIG_FMB_TIMER_PORT_ENABLED 1 +#define CONFIG_FMB_TIMER_GROUP 0 +#define CONFIG_FMB_TIMER_INDEX 0 +#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_FREERTOS_TIMER_TASK_PRIORITY 1 +#define CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH 2048 +#define CONFIG_FREERTOS_TIMER_QUEUE_LENGTH 10 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 +#define CONFIG_FREERTOS_DEBUG_OCDAWARE 1 +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_HEAP_TRACING_OFF 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_LOG_COLORS 1 +#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1 +#define CONFIG_LWIP_LOCAL_HOSTNAME "espressif" +#define CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES 1 +#define CONFIG_LWIP_TIMERS_ONDEMAND 1 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_LWIP_IP_FRAG 1 +#define CONFIG_LWIP_ESP_GRATUITOUS_ARP 1 +#define CONFIG_LWIP_GARP_TMR_INTERVAL 60 +#define CONFIG_LWIP_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_LWIP_TCP_MAXRTX 12 +#define CONFIG_LWIP_TCP_SYNMAXRTX 6 +#define CONFIG_LWIP_TCP_MSS 1440 +#define CONFIG_LWIP_TCP_TMR_INTERVAL 250 +#define CONFIG_LWIP_TCP_MSL 60000 +#define CONFIG_LWIP_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_LWIP_TCP_WND_DEFAULT 5744 +#define CONFIG_LWIP_TCP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCP_QUEUE_OOSEQ 1 +#define CONFIG_LWIP_TCP_OVERSIZE_MSS 1 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_LWIP_UDP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCPIP_TASK_STACK_SIZE 3072 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY 0x7FFFFFFF +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 +#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000 +#define CONFIG_LWIP_ESP_LWIP_ASSERT 1 +#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 +#define CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN 1 +#define CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN 16384 +#define CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN 4096 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL 1 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_MBEDTLS_HARDWARE_MPI 1 +#define CONFIG_MBEDTLS_HARDWARE_SHA 1 +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_MBEDTLS_ECDSA_DETERMINISTIC 1 +#define CONFIG_MBEDTLS_SHA512_C 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_RC4_DISABLED 1 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_MDNS_MAX_SERVICES 25 +#define CONFIG_MDNS_TASK_PRIORITY 1 +#define CONFIG_MDNS_TASK_STACK_SIZE 4096 +#define CONFIG_MDNS_TASK_AFFINITY_CPU0 1 +#define CONFIG_MDNS_TASK_AFFINITY 0x0 +#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 100 +#define CONFIG_MDNS_TIMER_PERIOD_MS 100 +#define CONFIG_MQTT_PROTOCOL_311 1 +#define CONFIG_MQTT_TRANSPORT_SSL 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_OPENSSL_ASSERT_EXIT 1 +#define CONFIG_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_PTHREAD_STACK_MIN 768 +#define CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY 1 +#define CONFIG_PTHREAD_TASK_CORE_DEFAULT -1 +#define CONFIG_PTHREAD_TASK_NAME_DEFAULT "pthread" +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS 1 +#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 +#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 +#define CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_GD_CHIP 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_USB_DESC_CUSTOM_VID 0x1234 +#define CONFIG_USB_DESC_CUSTOM_PID 0x5678 +#define CONFIG_UNITY_ENABLE_FLOAT 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 +#define CONFIG_VFS_SUPPORT_IO 1 +#define CONFIG_VFS_SUPPORT_DIR 1 +#define CONFIG_VFS_SUPPORT_SELECT 1 +#define CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT 1 +#define CONFIG_VFS_SUPPORT_TERMIOS 1 +#define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1 +#define CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN 128 +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 +#define CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT 30 +#define CONFIG_WPA_MBEDTLS_CRYPTO 1 + +/* List of deprecated options */ +#define CONFIG_ADC2_DISABLE_DAC CONFIG_ADC_DISABLE_DAC +#define CONFIG_BROWNOUT_DET CONFIG_ESP32_BROWNOUT_DET +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 +#define CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE +#define CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT +#define CONFIG_CONSOLE_UART_RX_GPIO CONFIG_ESP_CONSOLE_UART_RX_GPIO +#define CONFIG_CONSOLE_UART_TX_GPIO CONFIG_ESP_CONSOLE_UART_TX_GPIO +#define CONFIG_ESP32S2_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE +#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY +#define CONFIG_ESP32_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT CONFIG_PTHREAD_TASK_NAME_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT CONFIG_PTHREAD_TASK_PRIO_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT +#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC CONFIG_ESP32_RTC_CLK_SRC_INT_RC +#define CONFIG_ESP_GRATUITOUS_ARP CONFIG_LWIP_ESP_GRATUITOUS_ARP +#define CONFIG_FLASHMODE_DIO CONFIG_ESPTOOLPY_FLASHMODE_DIO +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR +#define CONFIG_GARP_TMR_INTERVAL CONFIG_LWIP_GARP_TMR_INTERVAL +#define CONFIG_INT_WDT CONFIG_ESP_INT_WDT +#define CONFIG_INT_WDT_CHECK_CPU1 CONFIG_ESP_INT_WDT_CHECK_CPU1 +#define CONFIG_INT_WDT_TIMEOUT_MS CONFIG_ESP_INT_WDT_TIMEOUT_MS +#define CONFIG_IPC_TASK_STACK_SIZE CONFIG_ESP_IPC_TASK_STACK_SIZE +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO CONFIG_BOOTLOADER_LOG_LEVEL_INFO +#define CONFIG_MAIN_TASK_STACK_SIZE CONFIG_ESP_MAIN_TASK_STACK_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT +#define CONFIG_MB_CONTROLLER_STACK_SIZE CONFIG_FMB_CONTROLLER_STACK_SIZE +#define CONFIG_MB_EVENT_QUEUE_TIMEOUT CONFIG_FMB_EVENT_QUEUE_TIMEOUT +#define CONFIG_MB_MASTER_DELAY_MS_CONVERT CONFIG_FMB_MASTER_DELAY_MS_CONVERT +#define CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND +#define CONFIG_MB_QUEUE_LENGTH CONFIG_FMB_QUEUE_LENGTH +#define CONFIG_MB_SERIAL_BUF_SIZE CONFIG_FMB_SERIAL_BUF_SIZE +#define CONFIG_MB_SERIAL_TASK_PRIO CONFIG_FMB_SERIAL_TASK_PRIO +#define CONFIG_MB_SERIAL_TASK_STACK_SIZE CONFIG_FMB_SERIAL_TASK_STACK_SIZE +#define CONFIG_MB_TIMER_GROUP CONFIG_FMB_TIMER_GROUP +#define CONFIG_MB_TIMER_INDEX CONFIG_FMB_TIMER_INDEX +#define CONFIG_MB_TIMER_PORT_ENABLED CONFIG_FMB_TIMER_PORT_ENABLED +#define CONFIG_MONITOR_BAUD_115200B CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_POST_EVENTS_FROM_IRAM_ISR CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR +#define CONFIG_POST_EVENTS_FROM_ISR CONFIG_ESP_EVENT_POST_FROM_ISR +#define CONFIG_REDUCE_PHY_TX_POWER CONFIG_ESP32_REDUCE_PHY_TX_POWER +#define CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN +#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS +#define CONFIG_STACK_CHECK_NONE CONFIG_COMPILER_STACK_CHECK_MODE_NONE +#define CONFIG_SUPPORT_TERMIOS CONFIG_VFS_SUPPORT_TERMIOS +#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE +#define CONFIG_TASK_WDT CONFIG_ESP_TASK_WDT +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 +#define CONFIG_TASK_WDT_TIMEOUT_S CONFIG_ESP_TASK_WDT_TIMEOUT_S +#define CONFIG_TCPIP_RECVMBOX_SIZE CONFIG_LWIP_TCPIP_RECVMBOX_SIZE +#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY +#define CONFIG_TCPIP_TASK_STACK_SIZE CONFIG_LWIP_TCPIP_TASK_STACK_SIZE +#define CONFIG_TCP_MAXRTX CONFIG_LWIP_TCP_MAXRTX +#define CONFIG_TCP_MSL CONFIG_LWIP_TCP_MSL +#define CONFIG_TCP_MSS CONFIG_LWIP_TCP_MSS +#define CONFIG_TCP_OVERSIZE_MSS CONFIG_LWIP_TCP_OVERSIZE_MSS +#define CONFIG_TCP_QUEUE_OOSEQ CONFIG_LWIP_TCP_QUEUE_OOSEQ +#define CONFIG_TCP_RECVMBOX_SIZE CONFIG_LWIP_TCP_RECVMBOX_SIZE +#define CONFIG_TCP_SND_BUF_DEFAULT CONFIG_LWIP_TCP_SND_BUF_DEFAULT +#define CONFIG_TCP_SYNMAXRTX CONFIG_LWIP_TCP_SYNMAXRTX +#define CONFIG_TCP_WND_DEFAULT CONFIG_LWIP_TCP_WND_DEFAULT +#define CONFIG_TIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH +#define CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY +#define CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH +#define CONFIG_TIMER_TASK_STACK_SIZE CONFIG_ESP_TIMER_TASK_STACK_SIZE +#define CONFIG_TOOLPREFIX CONFIG_SDK_TOOLPREFIX +#define CONFIG_UDP_RECVMBOX_SIZE CONFIG_LWIP_UDP_RECVMBOX_SIZE From d5fe42bffbf670eacc0be2e7bd6fab246d582d69 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Tue, 29 Sep 2020 21:02:17 +0530 Subject: [PATCH 149/289] Coredump config option rename throughout IDF * Original commit: espressif/esp-idf@20af94ff53c5147a76342800d007a6c49be50a7b --- components/mdns/test_afl_fuzz_host/sdkconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index 335b03994..43d4a278a 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -151,7 +151,7 @@ #define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 #define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 #define CONFIG_ESP32_PHY_MAX_TX_POWER 20 -#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 +#define CONFIG_ESP_COREDUMP_ENABLE_TO_NONE 1 #define CONFIG_FATFS_CODEPAGE_437 1 #define CONFIG_FATFS_CODEPAGE 437 #define CONFIG_FATFS_LFN_NONE 1 From 7635c0479bd234f507fa4981ee392af909be1cd3 Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Fri, 25 Sep 2020 13:57:52 +0800 Subject: [PATCH 150/289] soc: descriptive part occupy whole component * Original commit: espressif/esp-idf@79887fdc6c3d9a2e509cc189bb43c998d3f0f4ee --- components/mdns/test_afl_fuzz_host/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index e8ad15232..d636e3758 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -28,8 +28,8 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi -I$(COMPONENTS_DIR)/lwip/port/esp32/include \ -I$(COMPONENTS_DIR)/lwip/lwip/src/include/lwip/apps \ -I$(COMPONENTS_DIR)/soc/include \ - -I$(COMPONENTS_DIR)/soc/soc/include \ - -I$(COMPONENTS_DIR)/soc/soc/esp32/include \ + -I$(COMPONENTS_DIR)/soc/include \ + -I$(COMPONENTS_DIR)/soc/esp32/include \ -I$(COMPONENTS_DIR)/soc/src/esp32/include \ -I$(COMPONENTS_DIR)/tcpip_adapter/include \ -I$(COMPONENTS_DIR)/xtensa/include \ From fc5388811534f07c679f9f2a2cb14594182a689c Mon Sep 17 00:00:00 2001 From: "suren.gabrielyan" Date: Mon, 7 Sep 2020 18:52:17 +0400 Subject: [PATCH 151/289] CI: Add a test to pre-check fuzzer tests compilation before weekly run * Original commit: espressif/esp-idf@637f5c0a6842c42ee6cf7f41d3c5ae0cb28a68af --- components/mdns/test_afl_fuzz_host/Makefile | 1 + components/mdns/test_afl_fuzz_host/esp_attr.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index d636e3758..f73d3fcbd 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -27,6 +27,7 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi -I$(COMPONENTS_DIR)/lwip/lwip/src/include \ -I$(COMPONENTS_DIR)/lwip/port/esp32/include \ -I$(COMPONENTS_DIR)/lwip/lwip/src/include/lwip/apps \ + -I$(COMPONENTS_DIR)/newlib/platform_include \ -I$(COMPONENTS_DIR)/soc/include \ -I$(COMPONENTS_DIR)/soc/include \ -I$(COMPONENTS_DIR)/soc/esp32/include \ diff --git a/components/mdns/test_afl_fuzz_host/esp_attr.h b/components/mdns/test_afl_fuzz_host/esp_attr.h index abbb3b3e0..149f25c00 100644 --- a/components/mdns/test_afl_fuzz_host/esp_attr.h +++ b/components/mdns/test_afl_fuzz_host/esp_attr.h @@ -1,3 +1,6 @@ #pragma once #define IRAM_ATTR #define FLAG_ATTR(TYPE) +#define QUEUE_H +#define __XTENSA_API_H__ +#define SSIZE_MAX INT_MAX From 825652f3e1cdec5fec0ab11fd3b6f93b6a7509ca Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 5 Nov 2020 14:21:08 +1100 Subject: [PATCH 152/289] test_compile_fuzzers: Fix include paths for host build Regression in 988be6946681b592e3e51bb652b91bce54d7ba34, need to add esp_hw_support component include dir here. * Original commit: espressif/esp-idf@98a0cc783f701b238bea232b53250a538d34920a --- components/mdns/test_afl_fuzz_host/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index f73d3fcbd..7f84a6f86 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -10,6 +10,7 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi -I$(COMPONENTS_DIR)/esp_common/include \ -I$(COMPONENTS_DIR)/esp_event/include \ -I$(COMPONENTS_DIR)/esp_eth/include \ + -I$(COMPONENTS_DIR)/esp_hw_support/include \ -I$(COMPONENTS_DIR)/esp_netif/include \ -I$(COMPONENTS_DIR)/esp_netif/private_include \ -I$(COMPONENTS_DIR)/esp_netif/lwip \ From ccd48bc9a957a60f8801591099fc6cc00a1e1010 Mon Sep 17 00:00:00 2001 From: nx518 <50616530+nx518@users.noreply.github.com> Date: Fri, 6 Nov 2020 09:59:40 +0100 Subject: [PATCH 153/289] lwip: Added description to Kconfig option on IPv6 SLAAC Closes https://github.com/espressif/esp-idf/issues/6076 Merges https://github.com/espressif/esp-idf/pull/6078 * Original commit: espressif/esp-idf@9207c6ca8e5a0883a8ce46e0f403a17066895b69 --- .../common_components/protocol_examples_common/Kconfig.projbuild | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index 5875ccdfa..ed7f51c59 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -183,6 +183,7 @@ menu "Example Connection Configuration" Disable this option if the network does not support IPv6. Choose the preferred IPv6 address type if the connection code should wait until other than the local link address gets assigned. + Consider enabling IPv6 stateless address autoconfiguration (SLAAC) in the LWIP component. if EXAMPLE_CONNECT_IPV6 choice EXAMPLE_CONNECT_PREFERRED_IPV6 From 2cb3a6e35ef14d6c97ef2d096698865dd4869740 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 10 Nov 2020 18:40:01 +1100 Subject: [PATCH 154/289] Whitespace: Automated whitespace fixes (large commit) Apply the pre-commit hook whitespace fixes to all files in the repo. (Line endings, blank lines at end of file, trailing whitespace) * Original commit: espressif/esp-idf@66fb5a29bbdc2482d67c52e6f66b303378c9b789 --- components/mdns/CMakeLists.txt | 1 - components/mdns/mdns_console.c | 1 - components/mdns/mdns_networking.c | 2 +- components/mdns/test/CMakeLists.txt | 2 +- components/mdns/test/component.mk | 2 +- components/mdns/test/test_mdns.c | 2 +- components/mdns/test_afl_fuzz_host/CMakeLists.txt | 1 - components/mdns/test_afl_fuzz_host/Makefile | 2 +- .../mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c | 4 ++-- components/mdns/test_afl_fuzz_host/input_packets.txt | 6 +++--- components/mdns/test_afl_fuzz_host/mdns_di.h | 4 ++-- components/mdns/test_afl_fuzz_host/test.c | 6 +++--- .../protocol_examples_common/addr_from_stdin.c | 2 +- .../protocol_examples_common/include/addr_from_stdin.h | 2 +- examples/protocols/mdns/Makefile | 1 - examples/protocols/mdns/main/CMakeLists.txt | 2 +- examples/protocols/mdns/main/mdns_example_main.c | 2 +- examples/protocols/mdns/sdkconfig.ci | 2 +- 18 files changed, 20 insertions(+), 24 deletions(-) diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index cd85cc88f..a8d2cedb3 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -5,4 +5,3 @@ idf_component_register(SRCS "mdns.c" PRIV_INCLUDE_DIRS "private_include" REQUIRES lwip console esp_netif PRIV_REQUIRES esp_timer) - diff --git a/components/mdns/mdns_console.c b/components/mdns/mdns_console.c index 2c36a6aee..3c36c05a5 100644 --- a/components/mdns/mdns_console.c +++ b/components/mdns/mdns_console.c @@ -1057,4 +1057,3 @@ void mdns_console_register(void) register_mdns_query_ip(); register_mdns_query_svc(); } - diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index 5f900cf4d..5b0f1e7b2 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -1,7 +1,7 @@ /* * MDNS Server Networking - * + * */ #include #include "mdns_networking.h" diff --git a/components/mdns/test/CMakeLists.txt b/components/mdns/test/CMakeLists.txt index a24aa2433..5994c440c 100644 --- a/components/mdns/test/CMakeLists.txt +++ b/components/mdns/test/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRC_DIRS "." - PRIV_REQUIRES cmock test_utils mdns) \ No newline at end of file + PRIV_REQUIRES cmock test_utils mdns) diff --git a/components/mdns/test/component.mk b/components/mdns/test/component.mk index 5be873488..8c6eb513e 100644 --- a/components/mdns/test/component.mk +++ b/components/mdns/test/component.mk @@ -1,4 +1,4 @@ # #Component Makefile # -COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive \ No newline at end of file +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/mdns/test/test_mdns.c b/components/mdns/test/test_mdns.c index 9e1e50dc4..9dc9fe090 100644 --- a/components/mdns/test/test_mdns.c +++ b/components/mdns/test/test_mdns.c @@ -96,4 +96,4 @@ TEST_CASE("mdns query api return expected err-code and do not leak memory", "[le mdns_free(); esp_event_loop_delete_default(); -} \ No newline at end of file +} diff --git a/components/mdns/test_afl_fuzz_host/CMakeLists.txt b/components/mdns/test_afl_fuzz_host/CMakeLists.txt index 453dbc3dd..d65845194 100644 --- a/components/mdns/test_afl_fuzz_host/CMakeLists.txt +++ b/components/mdns/test_afl_fuzz_host/CMakeLists.txt @@ -5,4 +5,3 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(fuzz_test_update) - diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 7f84a6f86..147bd1c05 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -36,7 +36,7 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi -I$(COMPONENTS_DIR)/tcpip_adapter/include \ -I$(COMPONENTS_DIR)/xtensa/include \ -I$(COMPONENTS_DIR)/xtensa/esp32/include \ - -I$(COMPILER_ICLUDE_DIR)/include + -I$(COMPILER_ICLUDE_DIR)/include MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h diff --git a/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c b/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c index 2d52c15a0..ba7bbccb3 100644 --- a/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c +++ b/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c @@ -30,6 +30,6 @@ const char *esp_netif_get_ifkey(esp_netif_t *esp_netif) } esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6) -{ +{ return ESP_ERR_NOT_SUPPORTED; -} +} diff --git a/components/mdns/test_afl_fuzz_host/input_packets.txt b/components/mdns/test_afl_fuzz_host/input_packets.txt index 6156ffa23..15c5df2ba 100644 --- a/components/mdns/test_afl_fuzz_host/input_packets.txt +++ b/components/mdns/test_afl_fuzz_host/input_packets.txt @@ -76,7 +76,7 @@ Packet Length: 262 Answers: 2 + 6 A: Hristo’s Mac mini._device-info._tcp.local. TXT IN 4500 [28] model=Macmini6,2; osxvers=16 A: _smb._tcp.local. PTR IN 4500 [22] Hristo’s Mac mini._smb._tcp.local. - A: Hristo’s Mac mini._smb._tcp.local. TXT IN FLUSH 4500 [1] + A: Hristo’s Mac mini._smb._tcp.local. TXT IN FLUSH 4500 [1] A: Hristo’s Mac mini._smb._tcp.local. SRV IN FLUSH 120 [18] 445 minifritz.local. A: minifritz.local. AAAA IN FLUSH 120 [16] fe80:0000:0000:0000:142e:54ff:b8c4:fd09 A: minifritz.local. A IN FLUSH 120 [4] 192.168.254.16 @@ -97,7 +97,7 @@ Packet Length: 269 Answers: 2 + 6 A: Hristo’s Mac mini._device-info._tcp.local. TXT IN 4500 [28] model=Macmini6,2; osxvers=16 A: _afpovertcp._tcp.local. PTR IN 4500 [22] Hristo’s Mac mini._afpovertcp._tcp.local. - A: Hristo’s Mac mini._afpovertcp._tcp.local. TXT IN FLUSH 4500 [1] + A: Hristo’s Mac mini._afpovertcp._tcp.local. TXT IN FLUSH 4500 [1] A: Hristo’s Mac mini._afpovertcp._tcp.local. SRV IN FLUSH 120 [18] 548 minifritz.local. A: minifritz.local. AAAA IN FLUSH 120 [16] fe80:0000:0000:0000:142e:54ff:b8c4:fd09 A: minifritz.local. A IN FLUSH 120 [4] 192.168.254.16 @@ -135,7 +135,7 @@ Packet Length: 279 Answers: 2 + 6 A: Sofiya Ivanova’s MacBook._device-info._tcp.local. TXT IN 4500 [17] model=Macmini2,1 A: _rfb._tcp.local. PTR IN 4500 [29] Sofiya Ivanova’s MacBook._rfb._tcp.local. - A: Sofiya Ivanova’s MacBook._rfb._tcp.local. TXT IN FLUSH 4500 [1] + A: Sofiya Ivanova’s MacBook._rfb._tcp.local. TXT IN FLUSH 4500 [1] A: Sofiya Ivanova’s MacBook._rfb._tcp.local. SRV IN FLUSH 120 [32] 5900 Sofiya-Ivanovas-MacBook.local. A: Sofiya-Ivanovas-MacBook.local. AAAA IN FLUSH 120 [16] fe80:0000:0000:0000:021c:b3ff:feb2:72a3 A: Sofiya-Ivanovas-MacBook.local. A IN FLUSH 120 [4] 192.168.254.20 diff --git a/components/mdns/test_afl_fuzz_host/mdns_di.h b/components/mdns/test_afl_fuzz_host/mdns_di.h index c3587c576..b4569dd59 100644 --- a/components/mdns/test_afl_fuzz_host/mdns_di.h +++ b/components/mdns/test_afl_fuzz_host/mdns_di.h @@ -1,6 +1,6 @@ /* * MDNS Dependecy injection -- preincluded to inject interface test functions into static variables - * + * */ #include "mdns.h" @@ -50,4 +50,4 @@ mdns_search_once_t * mdns_test_search_init(const char * name, const char * servi mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto) { return mdns_test_static_mdns_get_service_item(service, proto); -} \ No newline at end of file +} diff --git a/components/mdns/test_afl_fuzz_host/test.c b/components/mdns/test_afl_fuzz_host/test.c index a19b27125..0c123f6fa 100644 --- a/components/mdns/test_afl_fuzz_host/test.c +++ b/components/mdns/test_afl_fuzz_host/test.c @@ -124,7 +124,7 @@ int main(int argc, char** argv) }; const uint8_t mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x32}; - + uint8_t buf[1460]; char winstance[21+strlen(mdns_hostname)]; @@ -183,9 +183,9 @@ int main(int argc, char** argv) || mdns_test_service_add("_ptp", "_tcp", 885) || mdns_test_service_add("_sleep-proxy", "_udp", 885)) { - abort(); + abort(); } - + mdns_result_t * results = NULL; FILE *file; size_t nread; diff --git a/examples/common_components/protocol_examples_common/addr_from_stdin.c b/examples/common_components/protocol_examples_common/addr_from_stdin.c index 460fe9a2e..0320a27bf 100644 --- a/examples/common_components/protocol_examples_common/addr_from_stdin.c +++ b/examples/common_components/protocol_examples_common/addr_from_stdin.c @@ -62,4 +62,4 @@ esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *ad // no match found freeaddrinfo( addr_list ); return ESP_FAIL; -} \ No newline at end of file +} diff --git a/examples/common_components/protocol_examples_common/include/addr_from_stdin.h b/examples/common_components/protocol_examples_common/include/addr_from_stdin.h index ab5043aed..959a7ed09 100644 --- a/examples/common_components/protocol_examples_common/include/addr_from_stdin.h +++ b/examples/common_components/protocol_examples_common/include/addr_from_stdin.h @@ -41,4 +41,4 @@ esp_err_t get_addr_from_stdin(int port, int sock_type, #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/examples/protocols/mdns/Makefile b/examples/protocols/mdns/Makefile index 91a417c7c..5b69ef89c 100644 --- a/examples/protocols/mdns/Makefile +++ b/examples/protocols/mdns/Makefile @@ -8,4 +8,3 @@ PROJECT_NAME := mdns-test EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common include $(IDF_PATH)/make/project.mk - diff --git a/examples/protocols/mdns/main/CMakeLists.txt b/examples/protocols/mdns/main/CMakeLists.txt index 141d1e30d..eb0e6d9eb 100644 --- a/examples/protocols/mdns/main/CMakeLists.txt +++ b/examples/protocols/mdns/main/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRCS "mdns_example_main.c" - INCLUDE_DIRS ".") \ No newline at end of file + INCLUDE_DIRS ".") diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 7d713c712..8f655fdad 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -256,4 +256,4 @@ static void query_mdns_host_with_getaddrinfo(char * host) } } } -#endif \ No newline at end of file +#endif diff --git a/examples/protocols/mdns/sdkconfig.ci b/examples/protocols/mdns/sdkconfig.ci index 60158c45c..42c55b8c0 100644 --- a/examples/protocols/mdns/sdkconfig.ci +++ b/examples/protocols/mdns/sdkconfig.ci @@ -1,3 +1,3 @@ CONFIG_MDNS_RESOLVE_TEST_SERVICES=y CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y -CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y \ No newline at end of file +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y From fd47df3e309c63344b84d59d8657183b151a987f Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 6 Nov 2020 10:32:00 +0100 Subject: [PATCH 155/289] mdns: Fix wrong mdns source address if lwIP IPv6 zones disabled The struct definition of ip6_addr_t in lwip and esp_ip6_addr_t differs since zone could be possibly disabled in lwip. Using memcpy to copy the address will cause wrong source address. Copy the entries manually instead. Merges https://github.com/espressif/esp-idf/pull/6055 * Original commit: espressif/esp-idf@7ac97616c119e4d2f4cdd377dfc5abbf75ec5e30 --- components/mdns/mdns_networking.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index 5b0f1e7b2..48c18cb1b 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -127,7 +127,8 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip packet->tcpip_if = MDNS_IF_MAX; packet->pb = this_pb; packet->src_port = rport; - memcpy(&packet->src, raddr, sizeof(ip_addr_t)); + packet->src.type = raddr->type; + memcpy(&packet->src.u_addr, &raddr->u_addr, sizeof(raddr->u_addr)); packet->dest.type = packet->src.type; if (packet->src.type == IPADDR_TYPE_V4) { From 988d120902360f0ef5b4d555d0e1bb08ea6aee56 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 6 Nov 2020 15:03:21 +1100 Subject: [PATCH 156/289] freertos: Add RISC-V port Changes come from internal branch commit a6723fc * Original commit: espressif/esp-idf@87e13baaf12fe6deae715d95e912a310fea4ba88 --- components/mdns/test_afl_fuzz_host/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 147bd1c05..4d2afd614 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -18,7 +18,7 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi -I$(COMPONENTS_DIR)/esp_system/include \ -I$(COMPONENTS_DIR)/esp_timer/include \ -I$(COMPONENTS_DIR)/esp_wifi/include \ - -I$(COMPONENTS_DIR)/freertos/xtensa/include \ + -I$(COMPONENTS_DIR)/freertos/port/xtensa/include \ -I$(COMPONENTS_DIR)/freertos \ -I$(COMPONENTS_DIR)/freertos/include \ -I$(COMPONENTS_DIR)/hal/include \ From d5566971fb4f825160730fd8f6e6f1ddb6291f77 Mon Sep 17 00:00:00 2001 From: morris Date: Fri, 6 Nov 2020 16:06:20 +0800 Subject: [PATCH 157/289] eth: support W5500 in network examples * Original commit: espressif/esp-idf@aea901f014ac05c41664dd1e3ba9bbd2301a0aba --- .../Kconfig.projbuild | 42 ++++++----- .../protocol_examples_common/connect.c | 72 +++++++++++++------ 2 files changed, 74 insertions(+), 40 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index ed7f51c59..56a6f9c95 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -33,7 +33,7 @@ menu "Example Connection Configuration" choice EXAMPLE_USE_ETHERNET prompt "Ethernet Type" default EXAMPLE_USE_INTERNAL_ETHERNET if IDF_TARGET_ESP32 - default EXAMPLE_USE_DM9051 if !IDF_TARGET_ESP32 + default EXAMPLE_USE_W5500 help Select which kind of Ethernet will be used in the example. @@ -51,6 +51,13 @@ menu "Example Connection Configuration" help Select external SPI-Ethernet module. + config EXAMPLE_USE_W5500 + bool "W5500 Module" + select ETH_USE_SPI_ETHERNET + select ETH_SPI_ETHERNET_W5500 + help + Select external SPI-Ethernet module (W5500). + config EXAMPLE_USE_OPENETH bool "OpenCores Ethernet MAC (EXPERIMENTAL)" select ETH_USE_OPENETH @@ -108,55 +115,55 @@ menu "Example Connection Configuration" Set the GPIO number used by SMI MDIO. endif - if EXAMPLE_USE_DM9051 - config EXAMPLE_DM9051_SPI_HOST + if ETH_USE_SPI_ETHERNET + config EXAMPLE_ETH_SPI_HOST int "SPI Host Number" range 0 2 default 1 help - Set the SPI host used to communicate with DM9051. + Set the SPI host used to communicate with the SPI Ethernet Controller. - config EXAMPLE_DM9051_SCLK_GPIO + config EXAMPLE_ETH_SPI_SCLK_GPIO int "SPI SCLK GPIO number" range 0 33 - default 19 + default 20 help Set the GPIO number used by SPI SCLK. - config EXAMPLE_DM9051_MOSI_GPIO + config EXAMPLE_ETH_SPI_MOSI_GPIO int "SPI MOSI GPIO number" range 0 33 - default 23 + default 19 help Set the GPIO number used by SPI MOSI. - config EXAMPLE_DM9051_MISO_GPIO + config EXAMPLE_ETH_SPI_MISO_GPIO int "SPI MISO GPIO number" range 0 33 - default 25 + default 18 help Set the GPIO number used by SPI MISO. - config EXAMPLE_DM9051_CS_GPIO + config EXAMPLE_ETH_SPI_CS_GPIO int "SPI CS GPIO number" range 0 33 - default 22 + default 21 help Set the GPIO number used by SPI CS. - config EXAMPLE_DM9051_SPI_CLOCK_MHZ + config EXAMPLE_ETH_SPI_CLOCK_MHZ int "SPI clock speed (MHz)" range 20 80 - default 20 + default 36 help Set the clock speed (MHz) of SPI interface. - config EXAMPLE_DM9051_INT_GPIO + config EXAMPLE_ETH_SPI_INT_GPIO int "Interrupt GPIO number" default 4 help - Set the GPIO number used by DM9051 interrupt. - endif + Set the GPIO number used by the SPI Ethernet module interrupt line. + endif # ETH_USE_SPI_ETHERNET config EXAMPLE_ETH_PHY_RST_GPIO int "PHY Reset GPIO number" @@ -168,7 +175,6 @@ menu "Example Connection Configuration" config EXAMPLE_ETH_PHY_ADDR int "PHY Address" range 0 31 if EXAMPLE_USE_INTERNAL_ETHERNET - range 1 1 if !EXAMPLE_USE_INTERNAL_ETHERNET default 1 help Set PHY address according your board schematic. diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 6ef826f42..2449ab940 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -15,7 +15,10 @@ #include "esp_wifi_default.h" #if CONFIG_EXAMPLE_CONNECT_ETHERNET #include "esp_eth.h" -#endif +#if CONFIG_ETH_USE_SPI_ETHERNET +#include "driver/spi_master.h" +#endif // CONFIG_ETH_USE_SPI_ETHERNET +#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET #include "esp_log.h" #include "esp_netif.h" #include "driver/gpio.h" @@ -60,17 +63,17 @@ static const char *s_ipv6_addr_types[] = { "ESP_IP6_ADDR_IS_SITE_LOCAL", "ESP_IP6_ADDR_IS_UNIQUE_LOCAL", "ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6" - }; +}; #endif static const char *TAG = "example_connect"; #if CONFIG_EXAMPLE_CONNECT_WIFI -static esp_netif_t* wifi_start(void); +static esp_netif_t *wifi_start(void); static void wifi_stop(void); #endif #if CONFIG_EXAMPLE_CONNECT_ETHERNET -static esp_netif_t* eth_start(void); +static esp_netif_t *eth_start(void); static void eth_stop(void); #endif @@ -81,7 +84,7 @@ static void eth_stop(void); */ static bool is_our_netif(const char *prefix, esp_netif_t *netif) { - return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix)-1) == 0; + return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0; } /* set up connection, Wi-Fi and/or Ethernet */ @@ -153,7 +156,7 @@ static void on_got_ipv6(void *arg, esp_event_base_t event_base, } esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip); ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif), - IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]); + IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]); if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) { memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); xSemaphoreGive(s_semph_get_ip_addrs); @@ -172,13 +175,13 @@ esp_err_t example_connect(void) start(); ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop)); ESP_LOGI(TAG, "Waiting for IP(s)"); - for (int i=0; i Date: Fri, 6 Nov 2020 17:19:51 +0800 Subject: [PATCH 158/289] test: fix several test build error * Original commit: espressif/esp-idf@b7ecccd9010f1deaba83de54374231c3c7f5b472 --- components/mdns/test_afl_fuzz_host/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 4d2afd614..96bfc991e 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -67,7 +67,7 @@ all: $(TEST_NAME) mdns.o: ../mdns.c @echo "[CC] $<" - @$(CC) $(CFLAGS) --include mdns_mock.h $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@ + @$(CC) $(CFLAGS) -include mdns_mock.h $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@ $(TEST_NAME): $(OBJECTS) @echo "[LD] $@" From df6a208f456d7b7742e712a559ad2a748252296c Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Tue, 24 Nov 2020 16:40:15 +0800 Subject: [PATCH 159/289] test: remove fake binary size check in example test: the binary size check in example test was removed long time ago. Now we have updated ttfw_idf to raise exception when performance standard is not found. These fake performance check will be regarded as error. Remove them now. * Original commit: espressif/esp-idf@a908174c06fd493dfada08606eb9d8ff314f7939 --- examples/protocols/mdns/mdns_example_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index 2acf45885..e081f2af0 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -102,7 +102,6 @@ def test_examples_protocol_mdns(env, extra_data): binary_file = os.path.join(dut1.app.binary_path, "mdns-test.bin") bin_size = os.path.getsize(binary_file) ttfw_idf.log_performance("mdns-test_bin_size", "{}KB".format(bin_size // 1024)) - ttfw_idf.check_performance("mdns-test_bin_size", bin_size // 1024, dut1.TARGET) # 1. start mdns application dut1.start_app() # 2. get the dut host name (and IP address) From e2653e7fb0f1da207c37120ef65708c1593abda5 Mon Sep 17 00:00:00 2001 From: morris Date: Fri, 27 Nov 2020 11:44:42 +0800 Subject: [PATCH 160/289] eth: hide spi configuration when using internal emac * Original commit: espressif/esp-idf@8d0a0537ccc6e702cfa6c917f068efe8ab588fd4 --- .../protocol_examples_common/Kconfig.projbuild | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index 56a6f9c95..e3275ec3f 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -30,7 +30,10 @@ menu "Example Connection Configuration" Choose this option to connect with Ethernet if EXAMPLE_CONNECT_ETHERNET - choice EXAMPLE_USE_ETHERNET + config EXAMPLE_USE_SPI_ETHERNET + bool + + choice EXAMPLE_ETHERNET_TYPE prompt "Ethernet Type" default EXAMPLE_USE_INTERNAL_ETHERNET if IDF_TARGET_ESP32 default EXAMPLE_USE_W5500 @@ -46,6 +49,7 @@ menu "Example Connection Configuration" config EXAMPLE_USE_DM9051 bool "DM9051 Module" + select EXAMPLE_USE_SPI_ETHERNET select ETH_USE_SPI_ETHERNET select ETH_SPI_ETHERNET_DM9051 help @@ -53,6 +57,7 @@ menu "Example Connection Configuration" config EXAMPLE_USE_W5500 bool "W5500 Module" + select EXAMPLE_USE_SPI_ETHERNET select ETH_USE_SPI_ETHERNET select ETH_SPI_ETHERNET_W5500 help @@ -68,7 +73,7 @@ menu "Example Connection Configuration" not officially supported. Examples built with this option enabled will not run on a real ESP32 chip. - endchoice + endchoice # EXAMPLE_ETHERNET_TYPE if EXAMPLE_USE_INTERNAL_ETHERNET choice EXAMPLE_ETH_PHY_MODEL @@ -115,7 +120,7 @@ menu "Example Connection Configuration" Set the GPIO number used by SMI MDIO. endif - if ETH_USE_SPI_ETHERNET + if EXAMPLE_USE_SPI_ETHERNET config EXAMPLE_ETH_SPI_HOST int "SPI Host Number" range 0 2 @@ -163,7 +168,7 @@ menu "Example Connection Configuration" default 4 help Set the GPIO number used by the SPI Ethernet module interrupt line. - endif # ETH_USE_SPI_ETHERNET + endif # EXAMPLE_USE_SPI_ETHERNET config EXAMPLE_ETH_PHY_RST_GPIO int "PHY Reset GPIO number" @@ -178,7 +183,7 @@ menu "Example Connection Configuration" default 1 help Set PHY address according your board schematic. - endif + endif # EXAMPLE_CONNECT_ETHERNET config EXAMPLE_CONNECT_IPV6 bool "Obtain IPv6 address" From 0d7a30944ece8f023b8f1111b40eb52a19a2e95e Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 26 Nov 2020 19:56:13 +1100 Subject: [PATCH 161/289] esp32c3: Apply one-liner/small changes for ESP32-C3 * Original commit: espressif/esp-idf@5228d9f9ced16118d87326f94d9f9dfd411e0be9 --- components/mdns/private_include/mdns_networking.h | 1 - components/mdns/private_include/mdns_private.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h index 12316f9ed..5a8156af9 100644 --- a/components/mdns/private_include/mdns_networking.h +++ b/components/mdns/private_include/mdns_networking.h @@ -19,7 +19,6 @@ #include "lwip/priv/tcpip_priv.h" #include "esp_wifi.h" #include "esp_system.h" -#include "esp_timer.h" #include "esp_event.h" #if CONFIG_ETH_ENABLED #include "esp_eth.h" diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 3fa57e597..60dfeb4ee 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -16,6 +16,7 @@ #include "esp_event_base.h" #include "esp_task.h" +#include "esp_timer.h" //#define MDNS_ENABLE_DEBUG From becd5d0266415e998624b5afb7f03d9785f502ea Mon Sep 17 00:00:00 2001 From: "suren.gabrielyan" Date: Fri, 4 Dec 2020 18:19:19 +0400 Subject: [PATCH 162/289] mDNS: Fix of collision detection during txt length calculation Closes https://github.com/espressif/esp-idf/issues/6114 * Original commit: espressif/esp-idf@f33772c96037c795366e60082bdbbefe2a69165f --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index debc02651..72687e022 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2158,7 +2158,7 @@ static int _mdns_check_txt_collision(mdns_service_t * service, const uint8_t * d mdns_txt_linked_item_t * txt = service->txt; while (txt) { - data_len += 2 + strlen(service->txt->key) + strlen(service->txt->value); + data_len += 2 + strlen(txt->key) + strlen(txt->value); txt = txt->next; } From 89439e0a9b31908ab68b3a8ddb4d8283eb86ccc0 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 11 Dec 2020 14:00:26 +0100 Subject: [PATCH 163/289] mdns: Allow resolve its own non-strict answers the mDNS responder should not repeat questions when replying, however resolvers must ignore these questions field if they are present. esp-idf mDNS library does include questions in answering packets (thus not strictly following the RFC6762) so the resolver did not correctly resolved another instance host name. Closes https://github.com/espressif/esp-idf/issues/6190 * Original commit: espressif/esp-idf@0693e172de392086b9bfd8cf1474d8d133af3298 --- components/mdns/mdns.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 72687e022..5fa9ed177 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2753,7 +2753,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } } - if (header.questions && !parsed_packet->questions && !parsed_packet->discovery) { + if (header.questions && !parsed_packet->questions && !parsed_packet->discovery && !header.answers) { goto clear_rx_packet; } else if (header.answers || header.servers || header.additional) { uint16_t recordIndex = 0; @@ -2796,13 +2796,14 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) if (parsed_packet->discovery && _mdns_name_is_discovery(name, type)) { discovery = true; - } else if (!name->sub && _mdns_name_is_ours(name)) { - ours = true; - if (name->service && name->service[0] && name->proto && name->proto[0]) { - service = _mdns_get_service_item(name->service, name->proto); - } } else { - if (header.questions || !parsed_packet->authoritative || record_type == MDNS_NS) { + if (!name->sub && _mdns_name_is_ours(name)) { + ours = true; + if (name->service && name->service[0] && name->proto && name->proto[0]) { + service = _mdns_get_service_item(name->service, name->proto); + } + } + if (!parsed_packet->authoritative || record_type == MDNS_NS) { //skip this record continue; } From 2cf9fd889147838783c841af31d917acea9c7e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20=C4=8Cerm=C3=A1k?= Date: Wed, 13 Jan 2021 10:28:34 +0800 Subject: [PATCH 164/289] lwip: Moved default SNTP API to esp_sntp.h and make sntp.h in port folders of lwip component obsoleted * Original commit: espressif/esp-idf@76f6dd6214ca583b1a94c7c553ccac739a27f6d5 --- .../mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c b/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c index ba7bbccb3..57c04b216 100644 --- a/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c +++ b/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c @@ -11,8 +11,13 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#include "esp32_compat.h" -#include "esp_netif_lwip_internal.h" +// mock the types to decouple from lwip +typedef void * esp_netif_t; +typedef enum { DHCP_MOCK } esp_netif_dhcp_status_t; +typedef tcpip_adapter_ip_info_t esp_netif_ip_info_t; +typedef ip6_addr_t esp_ip6_addr_t; esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) { @@ -26,7 +31,7 @@ esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_stat const char *esp_netif_get_ifkey(esp_netif_t *esp_netif) { - return esp_netif->if_key; + return NULL; } esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6) From 1fe901f70f08aa2548646c8d408ddf3bf1e0871c Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 17 Nov 2020 12:48:35 +0800 Subject: [PATCH 165/289] global: fix sign-compare warnings * Original commit: espressif/esp-idf@753a9295259126217a9fe6ef1c5e9da21e9b4e28 --- components/mdns/mdns.c | 11 ++++------- components/mdns/mdns_console.c | 4 ++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 5fa9ed177..b5499744e 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1605,7 +1605,7 @@ static void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_proto mdns_srv_item_t * new_probe_services[len]; int new_probe_service_len = 0; bool found; - for (int j=0; j < len; ++j) { + for (size_t j=0; j < len; ++j) { found = false; for (int i=0; i < pcb->probe_services_len; ++i) { if (pcb->probe_services[i] == services[j]) { @@ -2508,11 +2508,10 @@ static int _mdns_txt_items_count_get(const uint8_t * data, size_t len) */ static int _mdns_txt_item_name_get_len(const uint8_t * data, size_t len) { - int i; if (*data == '=') { return -1; } - for (i = 0; i < len; i++) { + for (size_t i = 0; i < len; i++) { if (data[i] == '=') { return i; } @@ -3483,7 +3482,6 @@ static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char */ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { - int i; mdns_result_t * r = search->result; while (r) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol) { @@ -3515,7 +3513,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it return; free_txt: - for (i=0; ihostname)); free((char *)(r->instance_name)); - for (i=0; itxt_count; i++) { + for (size_t i=0; itxt_count; i++) { free((char *)(r->txt[i].key)); free((char *)(r->txt[i].value)); } diff --git a/components/mdns/mdns_console.c b/components/mdns/mdns_console.c index 3c36c05a5..730889f64 100644 --- a/components/mdns/mdns_console.c +++ b/components/mdns/mdns_console.c @@ -24,7 +24,7 @@ static void mdns_print_results(mdns_result_t * results) { mdns_result_t * r = results; mdns_ip_addr_t * a = NULL; - int i = 1, t; + int i = 1; while (r) { printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]); if (r->instance_name) { @@ -35,7 +35,7 @@ static void mdns_print_results(mdns_result_t * results) } if (r->txt_count) { printf(" TXT : [%u] ", r->txt_count); - for (t=0; ttxt_count; t++) { + for (size_t t=0; ttxt_count; t++) { printf("%s=%s; ", r->txt[t].key, r->txt[t].value); } printf("\n"); From 487287157d0fa5a0585cf105a325b23dbb32ca5f Mon Sep 17 00:00:00 2001 From: xiehang Date: Mon, 11 Jan 2021 14:35:29 +0800 Subject: [PATCH 166/289] example: We should not check the return value of esp_wifi_connect() in any case * Original commit: espressif/esp-idf@c260c223e979c2604806cb585064e4fcfe80fdba --- examples/common_components/protocol_examples_common/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 2449ab940..25fa8e07c 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -271,7 +271,7 @@ static esp_netif_t *wifi_start(void) ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); - ESP_ERROR_CHECK(esp_wifi_connect()); + esp_wifi_connect(); return netif; } From 2ffd22382d9a97649fdc7dc5cef0e86a61b2ff73 Mon Sep 17 00:00:00 2001 From: "suren.gabrielyan" Date: Thu, 14 Jan 2021 14:32:05 +0400 Subject: [PATCH 167/289] mDNS: Fix of text length calculation when detecting a collision * Original commit: espressif/esp-idf@be0ae1ebbbe9fae6ecf7de09e8d50cba063b61f4 --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index b5499744e..8bb30eed2 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2147,7 +2147,7 @@ static int _mdns_check_srv_collision(mdns_service_t * service, uint16_t priority */ static int _mdns_check_txt_collision(mdns_service_t * service, const uint8_t * data, size_t len) { - size_t data_len = 1; + size_t data_len = 0; if (len == 1 && service->txt) { return -1;//we win } else if (len > 1 && !service->txt) { From dec1d7dcf89b380d8718179c6abc07b297b9c71d Mon Sep 17 00:00:00 2001 From: xiehang Date: Tue, 19 Jan 2021 11:55:44 +0800 Subject: [PATCH 168/289] esp_wifi: Modify ESP_IF_WIFI_STA to WIFI_IF_STA * Original commit: espressif/esp-idf@b8a8fe3f5464366c9c52dd16c946585fde44ea35 --- examples/common_components/protocol_examples_common/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 25fa8e07c..d6d2c0f2c 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -269,7 +269,7 @@ static esp_netif_t *wifi_start(void) }; ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); esp_wifi_connect(); return netif; From 49a00c2455e47b4a42239d7152e9744fb00ba74c Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Tue, 26 Jan 2021 10:49:01 +0800 Subject: [PATCH 169/289] style: format python files with isort and double-quote-string-fixer * Original commit: espressif/esp-idf@0146f258d7c8bdbc59ba6d40e8798500a30eb4ce --- examples/protocols/mdns/mdns_example_test.py | 56 ++++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index e081f2af0..52651035b 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -1,15 +1,15 @@ -import re import os +import re import socket -import time import struct +import subprocess +import time +from threading import Event, Thread + import dpkt import dpkt.dns -from threading import Thread, Event -import subprocess - -from tiny_test_fw import DUT import ttfw_idf +from tiny_test_fw import DUT stop_mdns_server = Event() esp_answered = Event() @@ -18,7 +18,7 @@ esp_answered = Event() def get_dns_query_for_esp(esp_host): dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') dns.qd[0].name = esp_host + u'.local' - print("Created query for esp host: {} ".format(dns.__repr__())) + print('Created query for esp host: {} '.format(dns.__repr__())) return dns.pack() @@ -32,26 +32,26 @@ def get_dns_answer_to_mdns(tester_host): arr.name = tester_host arr.ip = socket.inet_aton('127.0.0.1') dns. an.append(arr) - print("Created answer to mdns query: {} ".format(dns.__repr__())) + print('Created answer to mdns query: {} '.format(dns.__repr__())) return dns.pack() def get_dns_answer_to_mdns_lwip(tester_host, id): - dns = dpkt.dns.DNS(b"\x5e\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x0a\x64\x61\x76\x69\x64" - b"\x2d\x63\x6f\x6d\x70\x05\x6c\x6f\x63\x61\x6c\x00\x00\x01\x00\x01\xc0\x0c" - b"\x00\x01\x00\x01\x00\x00\x00\x0a\x00\x04\xc0\xa8\x0a\x6c") + dns = dpkt.dns.DNS(b'\x5e\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x0a\x64\x61\x76\x69\x64' + b'\x2d\x63\x6f\x6d\x70\x05\x6c\x6f\x63\x61\x6c\x00\x00\x01\x00\x01\xc0\x0c' + b'\x00\x01\x00\x01\x00\x00\x00\x0a\x00\x04\xc0\xa8\x0a\x6c') dns.qd[0].name = tester_host dns.an[0].name = tester_host dns.an[0].ip = socket.inet_aton('127.0.0.1') dns.an[0].rdata = socket.inet_aton('127.0.0.1') dns.id = id - print("Created answer to mdns (lwip) query: {} ".format(dns.__repr__())) + print('Created answer to mdns (lwip) query: {} '.format(dns.__repr__())) return dns.pack() def mdns_server(esp_host): global esp_answered - UDP_IP = "0.0.0.0" + UDP_IP = '0.0.0.0' UDP_PORT = 5353 MCAST_GRP = '224.0.0.251' TESTER_NAME = u'tinytester.local' @@ -60,7 +60,7 @@ def mdns_server(esp_host): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) sock.bind((UDP_IP,UDP_PORT)) - mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) + mreq = struct.pack('4sl', socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) sock.settimeout(30) while not stop_mdns_server.is_set(): @@ -72,14 +72,14 @@ def mdns_server(esp_host): dns = dpkt.dns.DNS(data) if len(dns.qd) > 0 and dns.qd[0].type == dpkt.dns.DNS_A: if dns.qd[0].name == TESTER_NAME: - print("Received query: {} ".format(dns.__repr__())) + print('Received query: {} '.format(dns.__repr__())) sock.sendto(get_dns_answer_to_mdns(TESTER_NAME), (MCAST_GRP,UDP_PORT)) elif dns.qd[0].name == TESTER_NAME_LWIP: - print("Received query: {} ".format(dns.__repr__())) + print('Received query: {} '.format(dns.__repr__())) sock.sendto(get_dns_answer_to_mdns_lwip(TESTER_NAME_LWIP, dns.id), addr) if len(dns.an) > 0 and dns.an[0].type == dpkt.dns.DNS_A: if dns.an[0].name == esp_host + u'.local': - print("Received answer to esp32-mdns query: {}".format(dns.__repr__())) + print('Received answer to esp32-mdns query: {}'.format(dns.__repr__())) esp_answered.set() except socket.timeout: break @@ -87,7 +87,7 @@ def mdns_server(esp_host): continue -@ttfw_idf.idf_example_test(env_tag="Example_WIFI") +@ttfw_idf.idf_example_test(env_tag='Example_WIFI') def test_examples_protocol_mdns(env, extra_data): global stop_mdns_server """ @@ -97,21 +97,21 @@ def test_examples_protocol_mdns(env, extra_data): 3. check the mdns name is accessible 4. check DUT output if mdns advertized host is resolved """ - dut1 = env.get_dut("mdns-test", "examples/protocols/mdns", dut_class=ttfw_idf.ESP32DUT) + dut1 = env.get_dut('mdns-test', 'examples/protocols/mdns', dut_class=ttfw_idf.ESP32DUT) # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, "mdns-test.bin") + binary_file = os.path.join(dut1.app.binary_path, 'mdns-test.bin') bin_size = os.path.getsize(binary_file) - ttfw_idf.log_performance("mdns-test_bin_size", "{}KB".format(bin_size // 1024)) + ttfw_idf.log_performance('mdns-test_bin_size', '{}KB'.format(bin_size // 1024)) # 1. start mdns application dut1.start_app() # 2. get the dut host name (and IP address) - specific_host = dut1.expect(re.compile(r"mdns hostname set to: \[([^\]]+)\]"), timeout=30) + specific_host = dut1.expect(re.compile(r'mdns hostname set to: \[([^\]]+)\]'), timeout=30) specific_host = str(specific_host[0]) thread1 = Thread(target=mdns_server, args=(specific_host,)) thread1.start() try: - ip_address = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30)[0] - print("Connected to AP with IP: {}".format(ip_address)) + ip_address = dut1.expect(re.compile(r' sta ip: ([^,]+),'), timeout=30)[0] + print('Connected to AP with IP: {}'.format(ip_address)) except DUT.ExpectTimeout: stop_mdns_server.set() thread1.join() @@ -121,15 +121,15 @@ def test_examples_protocol_mdns(env, extra_data): if not esp_answered.wait(timeout=30): raise ValueError('Test has failed: did not receive mdns answer within timeout') # 4. check DUT output if mdns advertized host is resolved - dut1.expect(re.compile(r"mdns-test: Query A: tinytester.local resolved to: 127.0.0.1"), timeout=30) - dut1.expect(re.compile(r"mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) - dut1.expect(re.compile(r"mdns-test: getaddrinfo: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) + dut1.expect(re.compile(r'mdns-test: Query A: tinytester.local resolved to: 127.0.0.1'), timeout=30) + dut1.expect(re.compile(r'mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1'), timeout=30) + dut1.expect(re.compile(r'mdns-test: getaddrinfo: tinytester-lwip.local resolved to: 127.0.0.1'), timeout=30) # 5. check the DUT answers to `dig` command dig_output = subprocess.check_output(['dig', '+short', '-p', '5353', '@224.0.0.251', '{}.local'.format(specific_host)]) print('Resolving {} using "dig" succeeded with:\n{}'.format(specific_host, dig_output)) if not ip_address.encode('utf-8') in dig_output: - raise ValueError("Test has failed: Incorrectly resolved DUT hostname using dig" + raise ValueError('Test has failed: Incorrectly resolved DUT hostname using dig' "Output should've contained DUT's IP address:{}".format(ip_address)) finally: stop_mdns_server.set() From b114ed69dee85c5eaf73de5537a65e87455afb2b Mon Sep 17 00:00:00 2001 From: "suren.gabrielyan" Date: Fri, 12 Feb 2021 13:18:59 +0400 Subject: [PATCH 170/289] mdns: add bound check when setting interface as duplicate Closes IDF-2787 Partially addresses https://github.com/espressif/esp-idf/issues/6440 * Original commit: espressif/esp-idf@2b9d2c06f54924b680c41ae641978c8d81612f65 --- components/mdns/mdns.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 8bb30eed2..35cbe2293 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2202,6 +2202,9 @@ static void _mdns_dup_interface(mdns_if_t tcpip_if) { uint8_t i; mdns_if_t other_if = _mdns_get_other_if (tcpip_if); + if (other_if == MDNS_IF_MAX) { + return; // no other interface found + } for (i=0; iinterfaces[other_if].pcbs[i].pcb) { //stop this interface and mark as dup From 1623c0e729e8899da8733164d86398eac74e92e2 Mon Sep 17 00:00:00 2001 From: yuanjm Date: Mon, 18 Jan 2021 19:14:51 +0800 Subject: [PATCH 171/289] components: Use CONFIG_LWIP_IPV6 to strip IPv6 function in components * Original commit: espressif/esp-idf@da58235a0ee262ff552c5f1155d531b5c31e8de6 --- components/mdns/include/mdns.h | 2 ++ components/mdns/mdns.c | 37 ++++++++++++++++++++++++++----- components/mdns/mdns_console.c | 4 ++++ components/mdns/mdns_networking.c | 33 +++++++++++++++++++-------- 4 files changed, 62 insertions(+), 14 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 6cee1e313..aeda9a071 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -339,6 +339,7 @@ esp_err_t mdns_query_txt(const char * instance_name, const char * service_type, */ esp_err_t mdns_query_a(const char * host_name, uint32_t timeout, esp_ip4_addr_t * addr); +#if CONFIG_LWIP_IPV6 /** * @brief Query mDNS for A record * @@ -353,6 +354,7 @@ esp_err_t mdns_query_a(const char * host_name, uint32_t timeout, esp_ip4_addr_t * - ESP_ERR_INVALID_ARG parameter error */ esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, esp_ip6_addr_t * addr); +#endif /** * @brief System event handler diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 35cbe2293..fd3706f9f 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -761,6 +761,7 @@ static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, uint32 return record_length; } +#if CONFIG_LWIP_IPV6 /** * @brief appends AAAA record to a packet, incrementing the index * @@ -809,6 +810,7 @@ static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, uin record_length += part_length; return record_length; } +#endif /** * @brief Append question to packet @@ -874,6 +876,7 @@ static bool _mdns_if_is_dup(mdns_if_t tcpip_if) return false; } +#if CONFIG_LWIP_IPV6 /** * @brief Check if IPv6 address is NULL */ @@ -888,6 +891,7 @@ static bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) } return true; } +#endif /** * @brief Append answer to packet @@ -936,7 +940,9 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ return 2; } return 1; - } else if (answer->type == MDNS_TYPE_AAAA) { + } +#if CONFIG_LWIP_IPV6 + else if (answer->type == MDNS_TYPE_AAAA) { struct esp_ip6_addr if_ip6; if (!_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state != PCB_DUP) { return 0; @@ -962,6 +968,7 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ } return 1; } +#endif return 0; } @@ -1235,11 +1242,14 @@ static mdns_tx_packet_t * _mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip packet->ip_protocol = ip_protocol; packet->port = MDNS_SERVICE_PORT; if (ip_protocol == MDNS_IP_PROTOCOL_V4) { - IP_ADDR4(&packet->dst, 224, 0, 0, 251); - } else { + IP4_ADDR(&packet->dst.u_addr.ip4, 224, 0, 0, 251); + } +#if CONFIG_LWIP_IPV6 + else { esp_ip_addr_t addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); memcpy(&packet->dst, &addr, sizeof(esp_ip_addr_t)); } +#endif return packet; } @@ -2253,6 +2263,7 @@ static int _mdns_check_a_collision(esp_ip4_addr_t * ip, mdns_if_t tcpip_if) return 0;//same } +#if CONFIG_LWIP_IPV6 /** * @brief Detect IPv6 address collision */ @@ -2286,6 +2297,7 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t * ip, mdns_if_t tcpip_if) } return 0;//same } +#endif /** * @brief Check if parsed name is discovery @@ -2678,7 +2690,12 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) parsed_packet->authoritative = header.flags.value == MDNS_FLAGS_AUTHORITATIVE; parsed_packet->distributed = header.flags.value == MDNS_FLAGS_DISTRIBUTED; parsed_packet->id = header.id; +#if CONFIG_LWIP_IPV6 ip_addr_copy(parsed_packet->src, packet->src); +#else + ip4_addr_copy(parsed_packet->src.u_addr.ip4, packet->src.u_addr.ip4); +#endif + parsed_packet->src_port = packet->src_port; if (header.questions) { @@ -2977,7 +2994,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } } - } else if (type == MDNS_TYPE_AAAA) {//ipv6 + } +#if CONFIG_LWIP_IPV6 + else if (type == MDNS_TYPE_AAAA) {//ipv6 esp_ip_addr_t ip6; ip6.type = IPADDR_TYPE_V6; memcpy(ip6.u_addr.ip6.addr, data_ptr, MDNS_ANSWER_AAAA_SIZE); @@ -3023,7 +3042,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } } - } else if (type == MDNS_TYPE_A) { + } +#endif + else if (type == MDNS_TYPE_A) { esp_ip_addr_t ip; ip.type = IPADDR_TYPE_V4; memcpy(&(ip.u_addr.ip4.addr), data_ptr, 4); @@ -4276,13 +4297,17 @@ esp_err_t mdns_init(void) } #endif uint8_t i; +#if CONFIG_LWIP_IPV6 esp_ip6_addr_t tmp_addr6; +#endif esp_netif_ip_info_t if_ip_info; for (i=0; imcast_ttl = 1; _pcb_main->remote_port = MDNS_SERVICE_PORT; - ip_addr_copy(_pcb_main->remote_ip, ip_addr_any_type); + ip_addr_copy(_pcb_main->remote_ip, *(IP_ANY_TYPE)); udp_recv(_pcb_main, &_udp_recv, _mdns_server); return ESP_OK; } @@ -75,19 +75,21 @@ static esp_err_t _udp_join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protoco assert(netif); if (ip_protocol == MDNS_IP_PROTOCOL_V4) { - ip_addr_t multicast_addr; - IP_ADDR4(&multicast_addr, 224, 0, 0, 251); + ip4_addr_t multicast_addr; + IP4_ADDR(&multicast_addr, 224, 0, 0, 251); if(join){ - if (igmp_joingroup_netif(netif, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) { + if (igmp_joingroup_netif(netif, &multicast_addr)) { return ESP_ERR_INVALID_STATE; } } else { - if (igmp_leavegroup_netif(netif, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) { + if (igmp_leavegroup_netif(netif, &multicast_addr)) { return ESP_ERR_INVALID_STATE; } } - } else { + } +#if CONFIG_LWIP_IPV6 + else { ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); if(join){ @@ -100,6 +102,7 @@ static esp_err_t _udp_join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protoco } } } +#endif return ESP_OK; } @@ -127,20 +130,29 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip packet->tcpip_if = MDNS_IF_MAX; packet->pb = this_pb; packet->src_port = rport; +#if CONFIG_LWIP_IPV6 packet->src.type = raddr->type; memcpy(&packet->src.u_addr, &raddr->u_addr, sizeof(raddr->u_addr)); +#else + packet->src.type = IPADDR_TYPE_V4; + memcpy(&packet->src.u_addr.ip4, &raddr->addr, sizeof(ip_addr_t)); +#endif packet->dest.type = packet->src.type; if (packet->src.type == IPADDR_TYPE_V4) { packet->ip_protocol = MDNS_IP_PROTOCOL_V4; struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN); packet->dest.u_addr.ip4.addr = iphdr->dest.addr; - } else { + packet->multicast = ip4_addr_ismulticast(&(packet->dest.u_addr.ip4)); + } +#if CONFIG_LWIP_IPV6 + else { packet->ip_protocol = MDNS_IP_PROTOCOL_V6; struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN); memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16); + packet->multicast = ip6_addr_ismulticast(&(packet->dest.u_addr.ip6)); } - packet->multicast = ip_addr_ismulticast(&(packet->dest)); +#endif //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces) struct netif * netif = NULL; @@ -150,8 +162,11 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip netif = esp_netif_get_netif_impl(_mdns_get_esp_netif(i)); if (pcb && netif && netif == ip_current_input_netif ()) { if (packet->src.type == IPADDR_TYPE_V4) { +#if CONFIG_LWIP_IPV6 if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) { - //packet source is not in the same subnet +#else + if ((packet->src.u_addr.ip4.addr & netif->netmask.addr) != (netif->ip_addr.addr & netif->netmask.addr)) { +#endif //packet source is not in the same subnet pcb = NULL; break; } From eda5d72acf5a8e8f50b2b8e4593907c95feb0182 Mon Sep 17 00:00:00 2001 From: yuanjm Date: Mon, 18 Jan 2021 19:16:06 +0800 Subject: [PATCH 172/289] examples: Strip IPv6 function in example and use sockaddr_storage to replace sockaddr_in6 * Original commit: espressif/esp-idf@821eea45b33bcd99b1889ef55d5c25effac83ddc --- .../protocol_examples_common/Kconfig.projbuild | 1 + .../protocol_examples_common/addr_from_stdin.c | 11 +++++++---- .../include/addr_from_stdin.h | 6 +++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index e3275ec3f..5e2af8b8c 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -189,6 +189,7 @@ menu "Example Connection Configuration" bool "Obtain IPv6 address" default y depends on EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET + select LWIP_IPV6 help By default, examples will wait until IPv4 and IPv6 local link addresses are obtained. Disable this option if the network does not support IPv6. diff --git a/examples/common_components/protocol_examples_common/addr_from_stdin.c b/examples/common_components/protocol_examples_common/addr_from_stdin.c index 0320a27bf..c907ffd96 100644 --- a/examples/common_components/protocol_examples_common/addr_from_stdin.c +++ b/examples/common_components/protocol_examples_common/addr_from_stdin.c @@ -10,7 +10,7 @@ #define HOST_IP_SIZE 128 -esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *addr_family, struct sockaddr_in6 *dest_addr) +esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *addr_family, struct sockaddr_storage *dest_addr) { char host_ip[HOST_IP_SIZE]; int len; @@ -49,15 +49,18 @@ esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *ad freeaddrinfo( addr_list ); return ESP_OK; - } else if (cur->ai_family == AF_INET6) { + } +#if CONFIG_LWIP_IPV6 + else if (cur->ai_family == AF_INET6) { *ip_protocol = IPPROTO_IPV6; *addr_family = AF_INET6; // add port and interface number and return on first IPv6 match - dest_addr->sin6_port = htons(port); - dest_addr->sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE); + ((struct sockaddr_in6*)dest_addr)->sin6_port = htons(port); + ((struct sockaddr_in6*)dest_addr)->sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE); freeaddrinfo( addr_list ); return ESP_OK; } +#endif } // no match found freeaddrinfo( addr_list ); diff --git a/examples/common_components/protocol_examples_common/include/addr_from_stdin.h b/examples/common_components/protocol_examples_common/include/addr_from_stdin.h index 959a7ed09..9a059c149 100644 --- a/examples/common_components/protocol_examples_common/include/addr_from_stdin.h +++ b/examples/common_components/protocol_examples_common/include/addr_from_stdin.h @@ -24,20 +24,20 @@ extern "C" { * @brief Read and evaluate IP address from stdin * * This API reads stdin and parses the input address using getaddrinfo() - * to fill in struct sockaddr_in6 (for both IPv4 and IPv6) used to open + * to fill in struct sockaddr_storage (for both IPv4 and IPv6) used to open * a socket. IP protocol is guessed from the IP address string. * * @param[in] port port number of expected connection * @param[in] sock_type expected protocol: SOCK_STREAM or SOCK_DGRAM * @param[out] ip_protocol resultant IP protocol: IPPROTO_IP or IPPROTO_IP6 * @param[out] addr_family resultant address family: AF_INET or AF_INET6 - * @param[out] dest_addr sockaddr_in6 structure (for both IPv4 and IPv6) + * @param[out] dest_addr sockaddr_storage structure (for both IPv4 and IPv6) * @return ESP_OK on success, ESP_FAIL otherwise */ esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *addr_family, - struct sockaddr_in6 *dest_addr); + struct sockaddr_storage *dest_addr); #ifdef __cplusplus } From 22c7c0a1952a00165d0bb8099e49c186f8a22907 Mon Sep 17 00:00:00 2001 From: "suren.gabrielyan" Date: Fri, 26 Feb 2021 18:28:57 +0400 Subject: [PATCH 173/289] mDNS: Updated APIs description and shows the warning when hostname contains domain name during the query Closes https://github.com/espressif/esp-idf/issues/6590 * Original commit: espressif/esp-idf@9f8d2b944d2b3736a012e0dff1a8459b6941d295 --- components/mdns/include/mdns.h | 4 ++++ components/mdns/mdns.c | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index aeda9a071..22da2afab 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -343,6 +343,8 @@ esp_err_t mdns_query_a(const char * host_name, uint32_t timeout, esp_ip4_addr_t /** * @brief Query mDNS for A record * + * Please note that hostname must not contain domain name, as mDNS uses '.local' domain. + * * @param host_name host name to look for * @param timeout time in milliseconds to wait for answer. If 0, max_results needs to be defined * @param addr pointer to the resulting IP6 address @@ -361,6 +363,8 @@ esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, esp_ip6_addr * This method controls the service state on all active interfaces and applications are required * to call it from the system event handler for normal operation of mDNS service. * + * Please note that hostname must not contain domain name, as mDNS uses '.local' domain. + * * @param ctx The system event context * @param event The system event */ diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index fd3706f9f..401d93122 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4819,6 +4819,10 @@ esp_err_t mdns_query_a(const char * name, uint32_t timeout, esp_ip4_addr_t * add return ESP_ERR_INVALID_ARG; } + if (strstr(name, ".local")) { + ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); + } + err = mdns_query(name, NULL, NULL, MDNS_TYPE_A, timeout, 1, &result); if (err) { @@ -4853,6 +4857,10 @@ esp_err_t mdns_query_aaaa(const char * name, uint32_t timeout, esp_ip6_addr_t * return ESP_ERR_INVALID_ARG; } + if (strstr(name, ".local")) { + ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); + } + err = mdns_query(name, NULL, NULL, MDNS_TYPE_AAAA, timeout, 1, &result); if (err) { From 1e5eeb16ec111fe0c1577c5b894c685d26be37ca Mon Sep 17 00:00:00 2001 From: "suren.gabrielyan" Date: Fri, 5 Feb 2021 17:56:09 +0400 Subject: [PATCH 174/289] mdns: Removed freeRTOS dependancies from fuzzer tests * Original commit: espressif/esp-idf@55716945a9908e057743d69e1d59399df03e49bd --- components/mdns/test_afl_fuzz_host/esp32_compat.h | 3 +++ components/mdns/test_afl_fuzz_host/esp_attr.h | 3 +++ .../mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c | 8 ++------ .../mdns/test_afl_fuzz_host/esp_netif_objects_mock.c | 2 -- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/esp32_compat.h b/components/mdns/test_afl_fuzz_host/esp32_compat.h index e8a998e29..7f7383b9f 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_compat.h +++ b/components/mdns/test_afl_fuzz_host/esp32_compat.h @@ -52,6 +52,7 @@ #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) @@ -60,6 +61,8 @@ #define __ESP_SYSTEM_H__ #define INC_TASK_H +#define pdMS_TO_TICKS(a) a +#define portTICK_RATE_MS 10 #define xSemaphoreTake(s,d) #define xTaskDelete(a) #define vTaskDelete(a) free(a) diff --git a/components/mdns/test_afl_fuzz_host/esp_attr.h b/components/mdns/test_afl_fuzz_host/esp_attr.h index 149f25c00..49bb7515d 100644 --- a/components/mdns/test_afl_fuzz_host/esp_attr.h +++ b/components/mdns/test_afl_fuzz_host/esp_attr.h @@ -2,5 +2,8 @@ #define IRAM_ATTR #define FLAG_ATTR(TYPE) #define QUEUE_H +#define __ARCH_CC_H__ #define __XTENSA_API_H__ #define SSIZE_MAX INT_MAX +#define LWIP_HDR_IP6_ADDR_H +#define LWIP_HDR_IP4_ADDR_H diff --git a/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c b/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c index 57c04b216..72ada5f9d 100644 --- a/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c +++ b/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c @@ -11,13 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -#include "esp32_compat.h" -// mock the types to decouple from lwip -typedef void * esp_netif_t; -typedef enum { DHCP_MOCK } esp_netif_dhcp_status_t; -typedef tcpip_adapter_ip_info_t esp_netif_ip_info_t; -typedef ip6_addr_t esp_ip6_addr_t; +#include "esp32_compat.h" +#include "esp_netif_lwip_internal.h" esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) { diff --git a/components/mdns/test_afl_fuzz_host/esp_netif_objects_mock.c b/components/mdns/test_afl_fuzz_host/esp_netif_objects_mock.c index 9d0213082..124144992 100644 --- a/components/mdns/test_afl_fuzz_host/esp_netif_objects_mock.c +++ b/components/mdns/test_afl_fuzz_host/esp_netif_objects_mock.c @@ -15,8 +15,6 @@ #include "esp_netif.h" #include "sys/queue.h" #include "esp_log.h" -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" #include "esp_netif_private.h" #include From c30617d872f31aa37c1d98c01cbbc25d91ded4a1 Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Wed, 24 Feb 2021 16:44:27 +0800 Subject: [PATCH 175/289] freertos: common config header * Original commit: espressif/esp-idf@39cf818838b0259b3e00b3c198ad47b4add41939 --- components/mdns/test_afl_fuzz_host/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 96bfc991e..8d98d501e 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -18,9 +18,9 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi -I$(COMPONENTS_DIR)/esp_system/include \ -I$(COMPONENTS_DIR)/esp_timer/include \ -I$(COMPONENTS_DIR)/esp_wifi/include \ - -I$(COMPONENTS_DIR)/freertos/port/xtensa/include \ -I$(COMPONENTS_DIR)/freertos \ -I$(COMPONENTS_DIR)/freertos/include \ + -I$(COMPONENTS_DIR)/freertos/port/xtensa/include \ -I$(COMPONENTS_DIR)/hal/include \ -I$(COMPONENTS_DIR)/hal/esp32/include \ -I$(COMPONENTS_DIR)/heap/include \ From 7a8329cb5cab7fb5effb3758b46bba07bda98f55 Mon Sep 17 00:00:00 2001 From: ronghulin Date: Thu, 25 Feb 2021 19:47:53 +0800 Subject: [PATCH 176/289] Bugfix: Connect example to add scan mode config Closes https://github.com/espressif/esp-idf/issues/6595 * Original commit: espressif/esp-idf@3373eff989fb829a3d4743b475a42a3f1ecbc71d --- .../Kconfig.projbuild | 68 +++++++++++++++++++ .../protocol_examples_common/connect.c | 36 ++++++++++ 2 files changed, 104 insertions(+) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index 5e2af8b8c..afbdf08a2 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -20,6 +20,74 @@ menu "Example Connection Configuration" help WiFi password (WPA or WPA2) for the example to use. Can be left blank if the network has no security set. + + choice EXAMPLE_WIFI_SCAN_METHOD + prompt "WiFi Scan Method" + default EXAMPLE_WIFI_SCAN_METHOD_FAST + help + WiFi scan method: + + If "Fast" is selected, scan will end after find SSID match AP. + + If "All Channel" is selected, scan will end after scan all the channel. + + config EXAMPLE_WIFI_SCAN_METHOD_FAST + bool "Fast" + config EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL + bool "All Channel" + endchoice + + menu "WiFi Scan threshold" + config EXAMPLE_WIFI_SCAN_RSSI_THRESHOLD + int "WiFi minimum rssi" + range -127 0 + + default -127 + help + The minimum rssi to accept in the scan mode. + + choice EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD + prompt "WiFi Scan auth mode threshold" + default EXAMPLE_WIFI_AUTH_OPEN + help + The weakest authmode to accept in the scan mode. + + config EXAMPLE_WIFI_AUTH_OPEN + bool "OPEN" + config EXAMPLE_WIFI_AUTH_WEP + bool "WEP" + config EXAMPLE_WIFI_AUTH_WPA_PSK + bool "WPA PSK" + config EXAMPLE_WIFI_AUTH_WPA2_PSK + bool "WPA2 PSK" + config EXAMPLE_WIFI_AUTH_WPA_WPA2_PSK + bool "WPA WPA2 PSK" + config EXAMPLE_WIFI_AUTH_WPA2_ENTERPRISE + bool "WPA2 ENTERPRISE" + config EXAMPLE_WIFI_AUTH_WPA3_PSK + bool "WPA3 PSK" + config EXAMPLE_WIFI_AUTH_WPA2_WPA3_PSK + bool "WPA2 WPA3 PSK" + config EXAMPLE_WIFI_AUTH_WAPI_PSK + bool "WAPI PSK" + endchoice + endmenu + + choice EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD + prompt "WiFi Connect AP Sort Method" + default EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL + help + WiFi connect AP sort method: + + If "Signal" is selected, Sort matched APs in scan list by RSSI. + + If "Security" is selected, Sort matched APs in scan list by security mode. + + config EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL + bool "Signal" + config EXAMPLE_WIFI_CONNECT_AP_BY_SECURITY + bool "Security" + endchoice endif config EXAMPLE_CONNECT_ETHERNET diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index d6d2c0f2c..40bac5fec 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -48,6 +48,38 @@ #define EXAMPLE_DO_CONNECT CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET +#if CONFIG_EXAMPLE_WIFI_SCAN_METHOD_FAST +#define EXAMPLE_WIFI_SCAN_METHOD WIFI_FAST_SCAN +#elif CONFIG_EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL +#define EXAMPLE_WIFI_SCAN_METHOD WIFI_ALL_CHANNEL_SCAN +#endif + +#if CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SIGNAL +#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL +#elif CONFIG_EXAMPLE_WIFI_CONNECT_AP_BY_SECURITY +#define EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD WIFI_CONNECT_AP_BY_SECURITY +#endif + +#if CONFIG_EXAMPLE_WIFI_AUTH_OPEN +#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN +#elif CONFIG_EXAMPLE_WIFI_AUTH_WEP +#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP +#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_PSK +#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK +#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_PSK +#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK +#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA_WPA2_PSK +#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK +#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_ENTERPRISE +#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_ENTERPRISE +#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA3_PSK +#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK +#elif CONFIG_EXAMPLE_WIFI_AUTH_WPA2_WPA3_PSK +#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK +#elif CONFIG_EXAMPLE_WIFI_AUTH_WAPI_PSK +#define EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK +#endif + static int s_active_interfaces = 0; static xSemaphoreHandle s_semph_get_ip_addrs; static esp_netif_t *s_example_esp_netif = NULL; @@ -265,6 +297,10 @@ static esp_netif_t *wifi_start(void) .sta = { .ssid = CONFIG_EXAMPLE_WIFI_SSID, .password = CONFIG_EXAMPLE_WIFI_PASSWORD, + .scan_method = EXAMPLE_WIFI_SCAN_METHOD, + .sort_method = EXAMPLE_WIFI_CONNECT_AP_SORT_METHOD, + .threshold.rssi = CONFIG_EXAMPLE_WIFI_SCAN_RSSI_THRESHOLD, + .threshold.authmode = EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD, }, }; ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid); From adc34309dc6e2df3077670b384114bc499ecced3 Mon Sep 17 00:00:00 2001 From: "suren.gabrielyan" Date: Fri, 5 Mar 2021 21:12:51 +0400 Subject: [PATCH 177/289] mdns: Add MDNS_STRICT_MODE config option Strict mode was hardcoded in private header file, but it's useful for users to enable/disable it depending on the mdns library they are using. e.g. Avahi might not resolve the non-strict answers. * Original commit: espressif/esp-idf@0eee31546dd4e6df0d1c1cc2740da0675dffb4bf --- components/mdns/Kconfig | 11 +++++++++++ components/mdns/private_include/mdns_private.h | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig index 72800aaa2..38dec7628 100644 --- a/components/mdns/Kconfig +++ b/components/mdns/Kconfig @@ -56,6 +56,17 @@ menu "mDNS" Configures timeout for adding a new mDNS service. Adding a service fails if could not be completed within this time. + config MDNS_STRICT_MODE + bool "mDNS strict mode" + default "n" + help + Configures strict mode. Set this to 1 for the mDNS library to strictly follow the RFC6762: + Currently the only strict feature: Do not repeat original questions in response packets + (defined in RFC6762 sec. 6). + Default configuration is 0, i.e. non-strict mode, since some implementations, + such as lwIP mdns resolver (used by standard POSIX API like getaddrinfo, gethostbyname) + could not correctly resolve advertised names. + config MDNS_TIMER_PERIOD_MS int "mDNS timer period (ms)" range 10 10000 diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 60dfeb4ee..9ed0dcfbd 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -32,7 +32,11 @@ * such as lwIP mdns resolver (used by standard POSIX API like getaddrinfo, gethostbyname) * could not correctly resolve advertised names. */ +#ifndef CONFIG_MDNS_STRICT_MODE #define MDNS_STRICT_MODE 0 +#else +#define MDNS_STRICT_MODE 1 +#endif #if !MDNS_STRICT_MODE /* mDNS responders sometimes repeat queries in responses From cbcbe4ffd73724d17b304dc3852f334459258fc4 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 8 Mar 2021 19:40:53 +0100 Subject: [PATCH 178/289] mdns: Fix the resolver to correctly parse it's own non-strict answers The resolver was able to respond correctly, but would also resolve its own queries and cause issues with BCT 1.5.2, specifically * MULTIPLE QUESTIONS - DUPLICATE SUPPRESSION * MULTIPLE QUESTIONS - DISTRIBUTED DUPLICATE SUPPRESSION tests failed. * Original commit: espressif/esp-idf@b649603a0d70ec804567f57752c3eddaed56198f --- components/mdns/mdns.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 401d93122..ebf2c63c5 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2815,13 +2815,12 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) if (parsed_packet->discovery && _mdns_name_is_discovery(name, type)) { discovery = true; - } else { - if (!name->sub && _mdns_name_is_ours(name)) { - ours = true; - if (name->service && name->service[0] && name->proto && name->proto[0]) { - service = _mdns_get_service_item(name->service, name->proto); - } + } else if (!name->sub && _mdns_name_is_ours(name)) { + ours = true; + if (name->service && name->service[0] && name->proto && name->proto[0]) { + service = _mdns_get_service_item(name->service, name->proto); } + } else { if (!parsed_packet->authoritative || record_type == MDNS_NS) { //skip this record continue; From c3a5826d6040cb74678af715e7cbbc1180ff3910 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 19 Feb 2021 16:44:08 +0100 Subject: [PATCH 179/289] mdns: Fix parsing answers with questions when instance name not set mdns resolver didn't correctly resolved queries when host name wasn't assigned. Fixed by allowing processing also if some answer present (non-strict mode) Closes https://github.com/espressif/esp-idf/issues/6598 * Original commit: espressif/esp-idf@34049454dfaf5132d9b258ef4d04921befc8997b --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index ebf2c63c5..6d4708431 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2679,7 +2679,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } //if we have not set the hostname, we can not answer questions - if (header.questions && _str_null_or_empty(_mdns_server->hostname)) { + if (header.questions && !header.answers && _str_null_or_empty(_mdns_server->hostname)) { free(parsed_packet); return; } From ab3fa69b8fb8ec2f8065d78f7fa1f7d819459172 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 28 Dec 2020 17:37:03 +0100 Subject: [PATCH 180/289] mdns: Fixed the ip header TTL to be correctly set to 255 Defined in https://tools.ietf.org/html/rfc6762#section-11: All Multicast DNS responses (including responses sent via unicast) SHOULD be sent with IP TTL set to 255 * Original commit: espressif/esp-idf@5cce919cbef87f543bb9f5275b77b97b3b1ea67e --- components/mdns/mdns_networking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index 152ab2798..48d11918b 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -38,7 +38,7 @@ static esp_err_t _udp_pcb_main_init(void) _pcb_main = NULL; return ESP_ERR_INVALID_STATE; } - _pcb_main->mcast_ttl = 1; + _pcb_main->mcast_ttl = 255; _pcb_main->remote_port = MDNS_SERVICE_PORT; ip_addr_copy(_pcb_main->remote_ip, *(IP_ANY_TYPE)); udp_recv(_pcb_main, &_udp_recv, _mdns_server); From 3ad559bf3fc7ee81409fd078a4e5466ecfdf5037 Mon Sep 17 00:00:00 2001 From: Shubham Kulkarni Date: Thu, 25 Mar 2021 15:20:30 +0530 Subject: [PATCH 181/289] Split example_tests with Example_WIFI tag group into Example_OTA and Example_Protocols * Original commit: espressif/esp-idf@0a395134d45caa0cba1bebdfd2ddb6fb2cf93d75 --- examples/protocols/mdns/mdns_example_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index 52651035b..201acb569 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -87,7 +87,7 @@ def mdns_server(esp_host): continue -@ttfw_idf.idf_example_test(env_tag='Example_WIFI') +@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') def test_examples_protocol_mdns(env, extra_data): global stop_mdns_server """ From 6d649102ab052aac37ea90eae2dc04465aa5e5b5 Mon Sep 17 00:00:00 2001 From: Suren Gabrielyan Date: Sun, 18 Apr 2021 16:55:37 +0400 Subject: [PATCH 182/289] Docs: Added README.md for lwip fuzzer tests Closes IDFCI-540 * Original commit: espressif/esp-idf@53c18a85db104bb37ebeadec2faf5d42d764d0f9 --- components/mdns/test_afl_fuzz_host/README.md | 35 +++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/README.md b/components/mdns/test_afl_fuzz_host/README.md index 7d78bab55..4a9e68200 100644 --- a/components/mdns/test_afl_fuzz_host/README.md +++ b/components/mdns/test_afl_fuzz_host/README.md @@ -1,7 +1,25 @@ ## Introduction This test uses [american fuzzy lop](http://lcamtuf.coredump.cx/afl/) to mangle real mdns packets and look for exceptions caused by the parser. -A few actuall packets are collected and exported as bins in the ```in``` folder, which is then passed as input to AFL when testing. The setup procedure for the test includes all possible services and scenarios that could be used with the given input packets. Output of the parser before fuzzing can be found in [input_packets.txt](input_packets.txt) +A few actual packets are collected and exported as bins in the ```in``` folder, which is then passed as input to AFL when testing. The setup procedure for the test includes all possible services and scenarios that could be used with the given input packets.The output of the parser before fuzzing can be found in [input_packets.txt](input_packets.txt) + +## Building and running the tests using AFL +To build and run the tests using AFL(afl-clang-fast) instrumentation + +```bash +cd $IDF_PATH/components/mdns/test_afl_host +make fuzz +``` + +(Please note you have to install AFL instrumentation first, check `Installing AFL` section) + +## Building the tests using GCC INSTR(off) +To build the tests without AFL instrumentations and instead of that use GCC compiler(In this case it will only check for compilation issues and will not run AFL tests). + +```bash +cd $IDF_PATH/components/mdns/test_afl_host +make INSTR=off +``` ## Installing AFL To run the test yourself, you need to dounload the [latest afl archive](http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz) and extract it to a folder on your computer. @@ -9,7 +27,7 @@ To run the test yourself, you need to dounload the [latest afl archive](http://l The rest of the document will refer to that folder as ```PATH_TO_AFL```. ### Preparation -- On Mac, you will need to insall the latest Xcode and llvm support from [Homebrew](https://brew.sh) +- On Mac, you will need to install the latest Xcode and llvm support from [Homebrew](https://brew.sh) ```bash /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" @@ -20,9 +38,11 @@ The rest of the document will refer to that folder as ```PATH_TO_AFL```. - On Ubuntu you need the following packages: ```bash - sudo apt-get install make clang llvm libbsd-dev + sudo apt-get install make clang-4.0(or <=4.0) llvm-4.0(or <=4.0) libbsd-dev ``` +Please note that if specified package version can't be installed(due to system is the latest), you can download, build and install it manually. + ### Compile AFL Compiling AFL is as easy as running make: @@ -33,14 +53,16 @@ cd llvm_mode/ make ``` -After successful compilation, you can export the following variables to your shell (you can also add them to your profile if you want to use afl in other projects) +After successful compilation, you can export the following variables to your shell (you can also add them to your profile if you want to use AFL in other projects). ```bash export AFL_PATH=[PATH_TO_AFL] export PATH="$AFL_PATH:$PATH" ``` -## Running the test +Please note LLVM must be <=4.0.0, otherwise afl does not compile, as there are some limitations with building AFL on MacOS/Linux with the latest LLVM. Also, Windows build on cygwin is not fully supported. + +## Additional info Apple has a crash reporting service that could interfere with AFLs normal operation. To turn that off, run the following command: ```bash @@ -53,6 +75,3 @@ Ubuntu has a similar service. To turn that off, run as root: ```bash echo core >/proc/sys/kernel/core_pattern ``` - -After going through all of the requirements above, you can ```cd``` into this test's folder and simply run ```make fuzz```. - From 4d8aec1ad3ac176c720711351e0db8faf0d13e13 Mon Sep 17 00:00:00 2001 From: Suren Gabrielyan Date: Thu, 20 May 2021 12:25:15 +0400 Subject: [PATCH 183/289] mdns: Fix of crash when wifi interface get deleted and mdns receives the packets Closes https://github.com/espressif/esp-idf/issues/6973 * Original commit: espressif/esp-idf@03de74a728d4b278f55e1fc30e0425483b806e80 --- components/mdns/mdns.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 6d4708431..af3ef03d7 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -73,6 +73,17 @@ esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) return NULL; } + +/* + * @brief Clean internal mdns interface's pointer + */ +static inline void _mdns_clean_netif_ptr(mdns_if_t tcpip_if) { + if (tcpip_if < MDNS_IF_MAX) { + s_esp_netifs[tcpip_if] = NULL; + } +} + + /* * @brief Convert esp-netif handle to mdns if */ @@ -3133,6 +3144,8 @@ void _mdns_enable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) */ void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { + _mdns_clean_netif_ptr(tcpip_if); + if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) { _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); _mdns_pcb_deinit(tcpip_if, ip_protocol); From b62b4b3e25508d44e3bf7ea82c437deb1a102da6 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Fri, 16 Apr 2021 15:19:34 +0800 Subject: [PATCH 184/289] mdns: fix memory free issue when repeating the query in reply The repeated query will be copied in the next event loop while the memory is freed instantly. Delay the free to fix this issue. * Original commit: espressif/esp-idf@5f244c86f29da46c17610563a245d1663a46b439 --- components/mdns/mdns.c | 52 ++++++++++++++++--- .../mdns/private_include/mdns_private.h | 1 + 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index af3ef03d7..11a495195 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1057,7 +1057,26 @@ static void _mdns_free_tx_packet(mdns_tx_packet_t * packet) if (!packet) { return; } - queueFree(mdns_out_question_t, packet->questions); + mdns_out_question_t *q = packet->questions; + while (q) { + mdns_out_question_t *next = q->next; + if (q->own_dynamic_memory) { + if (q->host) { + free((char *)q->host); + } + if (q->service) { + free((char *)q->service); + } + if (q->proto) { + free((char *)q->proto); + } + if (q->domain) { + free((char *)q->domain); + } + } + free(q); + q = next; + } queueFree(mdns_out_answer_t, packet->answers); queueFree(mdns_out_answer_t, packet->servers); queueFree(mdns_out_answer_t, packet->additional); @@ -1341,8 +1360,18 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed _mdns_free_tx_packet(packet); return; } - memcpy(out_question, q, sizeof(mdns_out_question_t)); + out_question->type = q->type; + out_question->unicast = q->unicast; + out_question->host = q->host; + q->host = NULL; + out_question->service = q->service; + q->service = NULL; + out_question->proto = q->proto; + q->proto = NULL; + out_question->domain = q->domain; + q->domain = NULL; out_question->next = NULL; + out_question->own_dynamic_memory = true; queueToEnd(mdns_out_question_t, packet->questions, out_question); #endif // MDNS_REPEAT_QUERY_IN_RESPONSE } else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, send_flush, false)) { @@ -1409,6 +1438,7 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_ q->service = services[i]->service->service; q->proto = services[i]->service->proto; q->domain = MDNS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; if (!q->host || _mdns_question_exists(q, packet->questions)) { free(q); continue; @@ -1436,6 +1466,7 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_ q->service = NULL; q->proto = NULL; q->domain = MDNS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; if (_mdns_question_exists(q, packet->questions)) { free(q); } else { @@ -3117,10 +3148,18 @@ clear_rx_packet: while (parsed_packet->questions) { mdns_parsed_question_t * question = parsed_packet->questions; parsed_packet->questions = parsed_packet->questions->next; - free(question->host); - free(question->service); - free(question->proto); - free(question->domain); + if (question->host) { + free(question->host); + } + if (question->service) { + free(question->service); + } + if (question->proto) { + free(question->proto); + } + if (question->domain) { + free(question->domain); + } free(question); } free(parsed_packet); @@ -3650,6 +3689,7 @@ static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search q->service = search->service; q->proto = search->proto; q->domain = MDNS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; queueToEnd(mdns_out_question_t, packet->questions, q); if (search->type == MDNS_TYPE_PTR) { diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 9ed0dcfbd..d8d507413 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -299,6 +299,7 @@ typedef struct mdns_out_question_s { const char * service; const char * proto; const char * domain; + bool own_dynamic_memory; } mdns_out_question_t; typedef struct mdns_out_answer_s { From 1eb5df9780ffdcbda9e30a0931c548fe55abc9a2 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Tue, 30 Mar 2021 13:19:01 +0800 Subject: [PATCH 185/289] mdns: add mdns delegation This allows publishing mdns services for other devices. * Original commit: espressif/esp-idf@401ff56cc1ad1d11284143a348cc0c0e4a363e98 --- components/mdns/include/mdns.h | 28 + components/mdns/mdns.c | 582 ++++++++++++------ .../mdns/private_include/mdns_private.h | 22 +- .../protocols/mdns/main/mdns_example_main.c | 82 ++- 4 files changed, 494 insertions(+), 220 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 22da2afab..dcf8972bd 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -114,6 +114,10 @@ void mdns_free(void); */ esp_err_t mdns_hostname_set(const char * hostname); +esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t *address); + +bool mdns_hostname_exists(const char *hostname); + /** * @brief Set the default instance name for mDNS server * @@ -145,6 +149,12 @@ esp_err_t mdns_instance_name_set(const char * instance_name); */ 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); + +esp_err_t mdns_service_add_custom_host(const char *instance_name, const char *service_type, const char *proto, + const char *hostname, uint16_t port, mdns_txt_item_t txt[], size_t num_items); + +bool mdns_service_exists(const char *service_type, const char *proto, const char *hostname); + /** * @brief Remove service from mDNS server * @@ -159,6 +169,8 @@ esp_err_t mdns_service_add(const char * instance_name, const char * service_type */ esp_err_t mdns_service_remove(const char * service_type, const char * proto); +esp_err_t mdns_service_remove_for_host(const char * service_type, const char * proto, const char *hostname); + /** * @brief Set instance name for service * @@ -174,6 +186,8 @@ esp_err_t mdns_service_remove(const char * service_type, const char * proto); */ esp_err_t mdns_service_instance_name_set(const char * service_type, const char * proto, const char * instance_name); +esp_err_t mdns_service_instance_name_set_for_host(const char * service_type, const char * proto, const char *hostname, const char * instance_name); + /** * @brief Set service port * @@ -189,6 +203,10 @@ esp_err_t mdns_service_instance_name_set(const char * service_type, const char * */ esp_err_t mdns_service_port_set(const char * service_type, const char * proto, uint16_t port); + +esp_err_t mdns_service_port_set_for_host(const char *service_type, const char *proto, const char *hostname, + uint16_t port); + /** * @brief Replace all TXT items for service * @@ -205,6 +223,9 @@ esp_err_t mdns_service_port_set(const char * service_type, const char * proto, u */ esp_err_t mdns_service_txt_set(const char * service_type, const char * proto, mdns_txt_item_t txt[], uint8_t num_items); +esp_err_t mdns_service_txt_set_for_host(const char *service_type, const char *proto, const char *hostname, + mdns_txt_item_t txt[], uint8_t num_items); + /** * @brief Set/Add TXT item for service TXT record * @@ -221,6 +242,10 @@ esp_err_t mdns_service_txt_set(const char * service_type, const char * proto, md */ esp_err_t mdns_service_txt_item_set(const char * service_type, const char * proto, const char * key, const char * value); + +esp_err_t mdns_service_txt_item_set_for_host(const char *service_type, const char *proto, const char *hostname, + const char *key, const char *value); + /** * @brief Remove TXT item for service TXT record * @@ -236,6 +261,9 @@ esp_err_t mdns_service_txt_item_set(const char * service_type, const char * prot */ esp_err_t mdns_service_txt_item_remove(const char * service_type, const char * proto, const char * key); +esp_err_t mdns_service_txt_item_remove_for_host(const char *service_type, const char *proto, const char *hostname, + const char *key); + /** * @brief Remove and free all services from mDNS server * diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 11a495195..2a715fe30 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -31,6 +31,8 @@ static const char * MDNS_DEFAULT_DOMAIN = "local"; static const char * MDNS_SUB_STR = "_sub"; mdns_server_t * _mdns_server = NULL; +static mdns_host_item_t *_mdns_host_list = NULL; +static mdns_host_item_t _mdns_self_host; static const char *TAG = "MDNS"; @@ -43,6 +45,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye); /* * @brief Internal collection of mdns supported interfaces @@ -143,6 +146,12 @@ static char * _mdns_mangle_name(char* in) { return ret; } +static bool _mdns_service_match(const mdns_service_t *srv, const char *service, const char *proto, const char *hostname) +{ + return !strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && + (_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); +} + /** * @brief finds service from given service type * @param server the server @@ -151,11 +160,11 @@ static char * _mdns_mangle_name(char* in) { * * @return the service item if found or NULL on error */ -static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto) +static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto, const char *hostname) { mdns_srv_item_t * s = _mdns_server->services; while (s) { - if (!strcasecmp(s->service->service, service) && !strcasecmp(s->service->proto, proto)) { + if (_mdns_service_match(s->service, service, proto, hostname)) { return s; } s = s->next; @@ -163,6 +172,21 @@ static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char return NULL; } +static mdns_host_item_t *mdns_get_host_item(const char *hostname, uint8_t address_type) +{ + if (hostname == NULL || strcasecmp(hostname, _mdns_server->hostname) == 0) { + return &_mdns_self_host; + } + mdns_host_item_t *host = _mdns_host_list; + while (host != NULL) { + if (strcasecmp(host->hostname, hostname) == 0 && host->address.type == address_type) { + return host; + } + host = host->next; + } + return NULL; +} + static bool _mdns_can_add_more_services(void) { mdns_srv_item_t * s = _mdns_server->services; @@ -704,7 +728,11 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns return 0; } - str[0] = _mdns_server->hostname; + if (service->hostname) { + str[0] = service->hostname; + } else { + str[0] = _mdns_server->hostname; + } str[1] = MDNS_DEFAULT_DOMAIN; if (_str_null_or_empty(str[0])) { @@ -731,20 +759,19 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, uint32_t ip, bool flush, bool bye) +static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, const char * hostname, uint32_t ip, bool flush, bool bye) { const char * str[2]; uint16_t record_length = 0; uint8_t part_length; - str[0] = _mdns_server->hostname; + str[0] = hostname; str[1] = MDNS_DEFAULT_DOMAIN; if (_str_null_or_empty(str[0])) { return 0; } - part_length = _mdns_append_fqdn(packet, index, str, 2); if (!part_length) { return 0; @@ -778,17 +805,18 @@ static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, uint32 * * @param packet MDNS packet * @param index offset in the packet + * @param hostnamek the hostname address to add * @param ipv6 the IPv6 address to add * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, uint8_t * ipv6, bool flush, bool bye) +static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, const char * hostname, uint8_t * ipv6, bool flush, bool bye) { const char * str[2]; uint16_t record_length = 0; uint8_t part_length; - str[0] = _mdns_server->hostname; + str[0] = hostname; str[1] = MDNS_DEFAULT_DOMAIN; if (_str_null_or_empty(str[0])) { @@ -908,6 +936,7 @@ static bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) * @brief Append answer to packet * * @return number of answers added to the packet + * XXX: create the answers here */ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_answer_t * answer, mdns_if_t tcpip_if) { @@ -930,54 +959,71 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ } else if (answer->type == MDNS_TYPE_SDPTR) { return _mdns_append_sdptr_record(packet, index, answer->service, answer->flush, answer->bye) > 0; } else if (answer->type == MDNS_TYPE_A) { - esp_netif_ip_info_t if_ip_info; - if (!_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state != PCB_DUP) { - return 0; - } - if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { - return 0; - } - if (_mdns_append_a_record(packet, index, if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { - return 0; - } - if (!_mdns_if_is_dup(tcpip_if)) { + if (answer->host == &_mdns_self_host) { + esp_netif_ip_info_t if_ip_info; + if (!_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state != PCB_DUP) { + return 0; + } + if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { + return 0; + } + if (_mdns_append_a_record(packet, index, _mdns_server->hostname, if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { + return 0; + } + if (!_mdns_if_is_dup(tcpip_if)) { + return 1; + } + mdns_if_t other_if = _mdns_get_other_if (tcpip_if); + if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &if_ip_info)) { + return 1; + } + if (_mdns_append_a_record(packet, index, _mdns_server->hostname, if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { + return 2; + } return 1; + } else if (answer->host != NULL) { + if (_mdns_append_a_record(packet, index, answer->host->hostname, answer->host->address.u_addr.ip4.addr, answer->flush, answer->bye) <= 0) { + return 0; + } else { + return 1; + } } - mdns_if_t other_if = _mdns_get_other_if (tcpip_if); - if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &if_ip_info)) { - return 1; - } - if (_mdns_append_a_record(packet, index, if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { - return 2; - } - return 1; } #if CONFIG_LWIP_IPV6 else if (answer->type == MDNS_TYPE_AAAA) { - struct esp_ip6_addr if_ip6; - if (!_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state != PCB_DUP) { - return 0; - } - if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(tcpip_if), &if_ip6)) { - return 0; - } - if (_ipv6_address_is_zero(if_ip6)) { - return 0; - } - if (_mdns_append_aaaa_record(packet, index, (uint8_t*)if_ip6.addr, answer->flush, answer->bye) <= 0) { - return 0; - } - if (!_mdns_if_is_dup(tcpip_if)) { + if (answer->host == &_mdns_self_host) { + struct esp_ip6_addr if_ip6; + if (!_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state != PCB_DUP) { + return 0; + } + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(tcpip_if), &if_ip6)) { + return 0; + } + if (_ipv6_address_is_zero(if_ip6)) { + return 0; + } + if (_mdns_append_aaaa_record(packet, index, _mdns_server->hostname, (uint8_t*)if_ip6.addr, answer->flush, answer->bye) <= 0) { + return 0; + } + if (!_mdns_if_is_dup(tcpip_if)) { + return 1; + } + mdns_if_t other_if = _mdns_get_other_if (tcpip_if); + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &if_ip6)) { + return 1; + } + if (_mdns_append_aaaa_record(packet, index, _mdns_server->hostname, (uint8_t*)if_ip6.addr, answer->flush, answer->bye) > 0) { + return 2; + } return 1; + } else if (answer->host != NULL) { + if (_mdns_append_aaaa_record(packet, index, answer->host->hostname, (uint8_t*)answer->host->address.u_addr.ip6.addr, answer->flush, answer->bye) <= 0) { + return 0; + } else { + return 1; + } + } - mdns_if_t other_if = _mdns_get_other_if (tcpip_if); - if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &if_ip6)) { - return 1; - } - if (_mdns_append_aaaa_record(packet, index, (uint8_t*)if_ip6.addr, answer->flush, answer->bye) > 0) { - return 2; - } - return 1; } #endif return 0; @@ -1232,11 +1278,11 @@ static void _mdns_dealloc_answer(mdns_out_answer_t ** destination, uint16_t type /** * @brief Allocate new answer and add it to answer list (destination) */ -static bool _mdns_alloc_answer(mdns_out_answer_t ** destination, uint16_t type, mdns_service_t * service, bool flush, bool bye) +static bool _mdns_alloc_answer(mdns_out_answer_t ** destination, uint16_t type, mdns_service_t * service, mdns_host_item_t *host, bool flush, bool bye) { mdns_out_answer_t * d = *destination; while (d) { - if (d->type == type && d->service == service) { + if (d->type == type && d->service == service && d->host == host) { return true; } d = d->next; @@ -1249,6 +1295,7 @@ static bool _mdns_alloc_answer(mdns_out_answer_t ** destination, uint16_t type, } a->type = type; a->service = service; + a->host = host; a->custom_service = NULL; a->bye = bye; a->flush = flush; @@ -1283,10 +1330,58 @@ static mdns_tx_packet_t * _mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip return packet; } +static bool _mdns_create_answer_from_service(mdns_tx_packet_t *packet, mdns_service_t *service, + mdns_parsed_question_t *question, bool shared, bool send_flush) +{ + mdns_host_item_t *host4 = mdns_get_host_item(service->hostname, ESP_IPADDR_TYPE_V4); + mdns_host_item_t *host6 = mdns_get_host_item(service->hostname, ESP_IPADDR_TYPE_V6); + if (question->type == MDNS_TYPE_PTR || question->type == MDNS_TYPE_ANY) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service, NULL, false, false) || + !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || + !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false) || + !_mdns_alloc_answer(shared ? &packet->additional : &packet->answers, MDNS_TYPE_A, service, host4, + send_flush, false) || + !_mdns_alloc_answer(shared ? &packet->additional : &packet->answers, MDNS_TYPE_AAAA, service, host6, + send_flush, false)) { + return false; + } + } else if (question->type == MDNS_TYPE_SRV) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || + !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_A, service, host4, send_flush, false) || + !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_AAAA, service, host6, send_flush, false)) { + return false; + } + } else if (question->type == MDNS_TYPE_TXT) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false)) { + return false; + } + } else if (question->type == MDNS_TYPE_SDPTR) { + shared = true; + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, service, NULL, false, false)) { + return false; + } + } + return true; +} + +static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t *packet, const char *hostname, bool send_flush) +{ + mdns_host_item_t *host4; + mdns_host_item_t *host6; + host4 = mdns_get_host_item(hostname, ESP_IPADDR_TYPE_V4); + host6 = mdns_get_host_item(hostname, ESP_IPADDR_TYPE_V6); + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host4, send_flush, false) || + !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host6, send_flush, false)) { + return false; + } + return true; +} + /** * @brief Create answer packet to questions from parsed packet + * XXX: reply from here */ -static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed_packet) +static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) { if (!parsed_packet->questions) { return; @@ -1294,7 +1389,7 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed bool send_flush = parsed_packet->src_port == MDNS_SERVICE_PORT; bool unicast = false; bool shared = false; - mdns_tx_packet_t * packet = _mdns_alloc_packet_default(parsed_packet->tcpip_if, parsed_packet->ip_protocol); + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(parsed_packet->tcpip_if, parsed_packet->ip_protocol); if (!packet) { return; } @@ -1302,82 +1397,60 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed packet->distributed = parsed_packet->distributed; packet->id = parsed_packet->id; - mdns_parsed_question_t * q = parsed_packet->questions; + mdns_parsed_question_t *q = parsed_packet->questions; while (q) { - mdns_srv_item_t * service = NULL; + shared = q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_SDPTR || !parsed_packet->probe; if (q->service && q->proto) { - service = _mdns_get_service_item(q->service, q->proto); - if (!service) { - continue; + mdns_srv_item_t *service = _mdns_server->services; + while (service) { + if (_mdns_service_match(service->service, q->service, q->proto, q->host)) { + if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { + _mdns_free_tx_packet(packet); + return; + } + } + service = service->next; } - } - if (q->unicast) { - unicast = true; - } - if (service) { - if (q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_ANY) { - if (q->type == MDNS_TYPE_PTR || !parsed_packet->probe) { - shared = true; - } - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service->service, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service->service, send_flush, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service->service, send_flush, false) - || !_mdns_alloc_answer(shared?&packet->additional:&packet->answers, MDNS_TYPE_A, NULL, send_flush, false) - || !_mdns_alloc_answer(shared?&packet->additional:&packet->answers, MDNS_TYPE_AAAA, NULL, send_flush, false)) { - _mdns_free_tx_packet(packet); - return; - } - } else if (q->type == MDNS_TYPE_SRV) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service->service, send_flush, false) - || !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_A, NULL, send_flush, false) - || !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_AAAA, NULL, send_flush, false)) { - _mdns_free_tx_packet(packet); - return; - } - } else if (q->type == MDNS_TYPE_TXT) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service->service, send_flush, false)) { - _mdns_free_tx_packet(packet); - return; - } - } else if (q->type == MDNS_TYPE_SDPTR) { - shared = true; - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, service->service, false, false)) { - _mdns_free_tx_packet(packet); - return; - } - } - } else { - if (q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, send_flush, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, send_flush, false)) { - _mdns_free_tx_packet(packet); - return; - } -#ifdef MDNS_REPEAT_QUERY_IN_RESPONSE - mdns_out_question_t * out_question = malloc(sizeof(mdns_out_question_t)); - if (out_question == NULL) { - HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); - return; - } - out_question->type = q->type; - out_question->unicast = q->unicast; - out_question->host = q->host; - q->host = NULL; - out_question->service = q->service; - q->service = NULL; - out_question->proto = q->proto; - q->proto = NULL; - out_question->domain = q->domain; - q->domain = NULL; - out_question->next = NULL; - out_question->own_dynamic_memory = true; - queueToEnd(mdns_out_question_t, packet->questions, out_question); -#endif // MDNS_REPEAT_QUERY_IN_RESPONSE - } else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, send_flush, false)) { + } else if (q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA) { + if (!_mdns_create_answer_from_hostname(packet, q->host, send_flush)) { _mdns_free_tx_packet(packet); return; } + } else if (q->type == MDNS_TYPE_ANY) { + if (!_mdns_append_host_list(&packet->answers, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } + } else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, NULL, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } + +#ifdef MDNS_REPEAT_QUERY_IN_RESPONSE + if (q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA) { + mdns_out_question_t * out_question = malloc(sizeof(mdns_out_question_t)); + if (out_question == NULL) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return; + } + out_question->type = q->type; + out_question->unicast = q->unicast; + out_question->host = q->host; + q->host = NULL; + out_question->service = q->service; + q->service = NULL; + out_question->proto = q->proto; + q->proto = NULL; + out_question->domain = q->domain; + q->domain = NULL; + out_question->next = NULL; + out_question->own_dynamic_memory = true; + queueToEnd(mdns_out_question_t, packet->questions, out_question); + } +#endif // MDNS_REPEAT_QUERY_IN_RESPONSE + if (q->unicast) { + unicast = true; } q = q->next; } @@ -1413,6 +1486,32 @@ static bool _mdns_question_exists(mdns_out_question_t * needle, mdns_out_questio return false; } +bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye) { + if (!_str_null_or_empty(_mdns_server->hostname)) { + mdns_host_item_t *self_host = mdns_get_host_item(_mdns_server->hostname, ESP_IPADDR_TYPE_ANY); + if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, self_host, flush, bye)) { + return false; + } + if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, self_host, flush, bye)) { + return false; + } + } + mdns_host_item_t *host = _mdns_host_list; + while(host != NULL) { + if (host->address.type == ESP_IPADDR_TYPE_V4) { + if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { + return false; + } + } else if (host->address.type == ESP_IPADDR_TYPE_V6) { + if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { + return false; + } + } + host = host->next; + } + return true; +} + /** * @brief Create probe packet for particular services on particular PCB */ @@ -1446,13 +1545,13 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_ queueToEnd(mdns_out_question_t, packet->questions, q); } - if (!q->host || !_mdns_alloc_answer(&packet->servers, MDNS_TYPE_SRV, services[i]->service, false, false)) { + if (!q->host || !_mdns_alloc_answer(&packet->servers, MDNS_TYPE_SRV, services[i]->service, NULL, false, false)) { _mdns_free_tx_packet(packet); return NULL; } } - if (include_ip && !_str_null_or_empty(_mdns_server->hostname)) { + if (include_ip) { mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); if (!q) { HOOK_MALLOC_FAILED; @@ -1473,18 +1572,9 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_ queueToEnd(mdns_out_question_t, packet->questions, q); } - if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) { - if (!_mdns_alloc_answer(&packet->servers, MDNS_TYPE_A, NULL, false, false)) { - _mdns_free_tx_packet(packet); - return NULL; - } - } - - if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) { - if (!_mdns_alloc_answer(&packet->servers, MDNS_TYPE_AAAA, NULL, false, false)) { - _mdns_free_tx_packet(packet); - return NULL; - } + if (!_mdns_append_host_list(&packet->servers, false, false)) { + _mdns_free_tx_packet(packet); + return NULL; } } @@ -1504,17 +1594,16 @@ static mdns_tx_packet_t * _mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ uint8_t i; for (i=0; ianswers, MDNS_TYPE_SDPTR, services[i]->service, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, services[i]->service, true, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, services[i]->service, true, false)) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, false)) { _mdns_free_tx_packet(packet); return NULL; } } if (include_ip) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, true, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, true, false)) { + if (!_mdns_append_host_list(&packet->servers, true, false)) { _mdns_free_tx_packet(packet); return NULL; } @@ -1537,16 +1626,16 @@ static mdns_tx_packet_t * _mdns_create_announce_from_probe(mdns_tx_packet_t * pr mdns_out_answer_t * s = probe->servers; while (s) { if (s->type == MDNS_TYPE_SRV) { - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, s->service, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, s->service, false, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, s->service, true, false) - || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, s->service, true, false)) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, s->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, s->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, s->service, NULL, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, s->service, NULL, true, false)) { _mdns_free_tx_packet(packet); return NULL; } } else if (s->type == MDNS_TYPE_A || s->type == MDNS_TYPE_AAAA) { - if (!_mdns_alloc_answer(&packet->answers, s->type, NULL, true, false)) { + if (!_mdns_alloc_answer(&packet->answers, s->type, NULL, s->host, true, false)) { _mdns_free_tx_packet(packet); return NULL; } @@ -1569,14 +1658,13 @@ static void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco packet->flags = MDNS_FLAGS_AUTHORITATIVE; size_t i; for (i=0; ianswers, MDNS_TYPE_PTR, services[i]->service, true, true)) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, true, true)) { _mdns_free_tx_packet(packet); return; } } - if (include_ip && (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, true, true) || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, true, true))) { - _mdns_free_tx_packet(packet); - return; + if (include_ip) { + _mdns_append_host_list(&packet->answers, true, true); } _mdns_dispatch_tx_packet(packet); _mdns_free_tx_packet(packet); @@ -1732,18 +1820,17 @@ static void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco mdns_tx_packet_t * p = _mdns_get_next_pcb_packet(tcpip_if, ip_protocol); if (p) { for (i=0; ianswers, MDNS_TYPE_SDPTR, services[i]->service, false, false) - || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_PTR, services[i]->service, false, false) - || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_SRV, services[i]->service, true, false) - || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_TXT, services[i]->service, true, false)) { + if (!_mdns_alloc_answer(&p->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, false)) { break; } } if (include_ip) { _mdns_dealloc_answer(&p->additional, MDNS_TYPE_A, NULL); _mdns_dealloc_answer(&p->additional, MDNS_TYPE_AAAA, NULL); - _mdns_alloc_answer(&p->answers, MDNS_TYPE_A, NULL, true, false); - _mdns_alloc_answer(&p->answers, MDNS_TYPE_AAAA, NULL, true, false); + _mdns_append_host_list(&p->answers, true, false); } _pcb->state = PCB_ANNOUNCE_1; } @@ -1961,7 +2048,7 @@ static void _mdns_free_linked_txt(mdns_txt_linked_item_t *txt) * * @return pointer to the service or NULL on error */ -static mdns_service_t * _mdns_create_service(const char * service, const char * proto, uint16_t port, const char * instance, size_t num_items, mdns_txt_item_t txt[]) +static mdns_service_t * _mdns_create_service(const char * service, const char * proto, const char *hostname, uint16_t port, const char * instance, size_t num_items, mdns_txt_item_t txt[]) { mdns_service_t * s = (mdns_service_t *)malloc(sizeof(mdns_service_t)); if (!s) { @@ -1981,6 +2068,17 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * s->txt = new_txt; s->port = port; + assert(hostname != NULL); + if (hostname) { + s->hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); + if (!s->hostname) { + free(s); + return NULL; + } + } else { + s->hostname = NULL; + } + s->service = strndup(service, MDNS_NAME_BUF_LEN - 1); if (!s->service) { free(s); @@ -2341,6 +2439,39 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t * ip, mdns_if_t tcpip_if) } #endif +static bool _hostname_is_ours(const char *hostname) +{ + if (strcasecmp(hostname, _mdns_server->hostname) == 0) { + return true; + } + mdns_host_item_t *host = _mdns_host_list; + while (host != NULL) { + if (strcasecmp(hostname, host->hostname) == 0) { + return true; + } + host = host->next; + } + return false; +} + +static bool _mdns_delegate_hostname_add(const char *hostname, const esp_ip_addr_t *address) +{ + if (_hostname_is_ours(hostname)) { + return true; + } + + mdns_host_item_t *host = (mdns_host_item_t *)malloc(sizeof(mdns_host_item_t)); + + if (host == NULL) { + return false; + } + host->address = *address; + host->hostname = hostname; + host->next = _mdns_host_list; + _mdns_host_list = host; + return true; +} + /** * @brief Check if parsed name is discovery */ @@ -2369,7 +2500,7 @@ static bool _mdns_name_is_ours(mdns_name_t * name) if (_str_null_or_empty(name->service) && _str_null_or_empty(name->proto)) { if (!_str_null_or_empty(name->host) && !_str_null_or_empty(_mdns_server->hostname) - && strcasecmp(name->host, _mdns_server->hostname) == 0) + && _hostname_is_ours(name->host) == 0) { return true; } @@ -2382,7 +2513,7 @@ static bool _mdns_name_is_ours(mdns_name_t * name) } //find the service - mdns_srv_item_t * service = _mdns_get_service_item(name->service, name->proto); + mdns_srv_item_t * service = _mdns_get_service_item(name->service, name->proto, name->host); if (!service) { return false; } @@ -2860,7 +2991,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } else if (!name->sub && _mdns_name_is_ours(name)) { ours = true; if (name->service && name->service[0] && name->proto && name->proto[0]) { - service = _mdns_get_service_item(name->service, name->proto); + service = _mdns_get_service_item(name->service, name->proto, name->host); } } else { if (!parsed_packet->authoritative || record_type == MDNS_NS) { @@ -2878,7 +3009,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) _mdns_search_result_add_ptr(search_result, name->host, packet->tcpip_if, packet->ip_protocol); } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { if (discovery) { - service = _mdns_get_service_item(name->service, name->proto); + service = _mdns_get_service_item(name->service, name->proto, name->host); _mdns_remove_parsed_question(parsed_packet, MDNS_TYPE_SDPTR, service); } else if (parsed_packet->questions && !parsed_packet->probe) { _mdns_remove_parsed_question(parsed_packet, type, service); @@ -3831,7 +3962,7 @@ static void _mdns_free_action(mdns_action_t * action) { switch(action->type) { case ACTION_HOSTNAME_SET: - free(action->data.hostname); + free(action->data.hostname_set.hostname); break; case ACTION_INSTANCE_SET: free(action->data.instance); @@ -3892,9 +4023,10 @@ static void _mdns_execute_action(mdns_action_t * action) case ACTION_HOSTNAME_SET: _mdns_send_bye_all_pcbs_no_instance(true); free((char*)_mdns_server->hostname); - _mdns_server->hostname = action->data.hostname; + _mdns_server->hostname = action->data.hostname_set.hostname; + _mdns_self_host.hostname = action->data.hostname_set.hostname; _mdns_restart_all_pcbs(); - + xTaskNotifyGive(action->data.hostname_set.calling_task); break; case ACTION_INSTANCE_SET: _mdns_send_bye_all_pcbs_no_instance(false); @@ -3907,7 +4039,6 @@ static void _mdns_execute_action(mdns_action_t * action) action->data.srv_add.service->next = _mdns_server->services; _mdns_server->services = action->data.srv_add.service; _mdns_probe_all_pcbs(&action->data.srv_add.service, 1, false, false); - break; case ACTION_SERVICE_INSTANCE_SET: if (action->data.srv_instance.service->service->instance) { @@ -4058,6 +4189,8 @@ static void _mdns_execute_action(mdns_action_t * action) pbuf_free(action->data.rx_handle.packet->pb); free(action->data.rx_handle.packet); break; + case ACTION_DELEGATE_HOSTNAME_ADD: + _mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, &action->data.delegate_hostname.address); default: break; } @@ -4461,7 +4594,40 @@ esp_err_t mdns_hostname_set(const char * hostname) return ESP_ERR_NO_MEM; } action->type = ACTION_HOSTNAME_SET; - action->data.hostname = new_hostname; + action->data.hostname_set.hostname = new_hostname; + action->data.hostname_set.calling_task = xTaskGetCurrentTaskHandle(); + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + assert(false); + free(new_hostname); + free(action); + return ESP_ERR_NO_MEM; + } + xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); + return ERR_OK; +} + +esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t *address) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_ARG; + } + if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + return ESP_ERR_INVALID_ARG; + } + char * new_hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); + if (!new_hostname) { + return ESP_ERR_NO_MEM; + } + + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + free(new_hostname); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_DELEGATE_HOSTNAME_ADD; + action->data.delegate_hostname.hostname = new_hostname; + action->data.delegate_hostname.address = *address; if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { free(new_hostname); free(action); @@ -4470,6 +4636,10 @@ esp_err_t mdns_hostname_set(const char * hostname) return ERR_OK; } +bool mdns_hostname_exists(const char *hostname) { + return _hostname_is_ours(hostname); +} + esp_err_t mdns_instance_name_set(const char * instance) { if (!_mdns_server) { @@ -4503,7 +4673,9 @@ esp_err_t mdns_instance_name_set(const char * instance) * MDNS SERVICES * */ -esp_err_t mdns_service_add(const char * instance, const char * service, const char * proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items) +esp_err_t mdns_service_add_custom_host(const char *instance, const char *service, const char *proto, + const char *hostname, uint16_t port, + mdns_txt_item_t txt[], size_t num_items) { if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { return ESP_ERR_INVALID_ARG; @@ -4513,12 +4685,12 @@ esp_err_t mdns_service_add(const char * instance, const char * service, const ch return ESP_ERR_NO_MEM; } - mdns_srv_item_t * item = _mdns_get_service_item(service, proto); + mdns_srv_item_t * item = _mdns_get_service_item(service, proto, hostname); if (item) { return ESP_ERR_INVALID_ARG; } - mdns_service_t * s = _mdns_create_service(service, proto, port, instance, num_items, txt); + mdns_service_t * s = _mdns_create_service(service, proto, hostname, port, instance, num_items, txt); if (!s) { return ESP_ERR_NO_MEM; } @@ -4551,7 +4723,7 @@ esp_err_t mdns_service_add(const char * instance, const char * service, const ch size_t start = xTaskGetTickCount(); size_t timeout_ticks = pdMS_TO_TICKS(MDNS_SERVICE_ADD_TIMEOUT_MS); - while (_mdns_get_service_item(service, proto) == NULL) + while (_mdns_get_service_item(service, proto, hostname) == NULL) { uint32_t expired = xTaskGetTickCount() - start; if (expired >= timeout_ticks) { @@ -4563,12 +4735,24 @@ esp_err_t mdns_service_add(const char * instance, const char * service, const ch return ESP_OK; } -esp_err_t mdns_service_port_set(const char * service, const char * proto, uint16_t port) +esp_err_t mdns_service_add(const char *instance, const char *service, const char *proto, uint16_t port, + mdns_txt_item_t txt[], size_t num_items) +{ + assert(_mdns_server->hostname != NULL); + return mdns_service_add_custom_host(instance, service, proto, _mdns_server->hostname, port, txt, num_items); +} + +bool mdns_service_exists(const char *service_type, const char *proto, const char *hostname) +{ + return _mdns_get_service_item(service_type, proto, hostname) != NULL; +} + +esp_err_t mdns_service_port_set_for_host(const char *service, const char *proto, const char *hostname, uint16_t port) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto); + mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -4588,12 +4772,17 @@ esp_err_t mdns_service_port_set(const char * service, const char * proto, uint16 return ESP_OK; } -esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_txt_item_t txt[], uint8_t num_items) +esp_err_t mdns_service_port_set(const char *service, const char *proto, uint16_t port) { + return mdns_service_port_set_for_host(service, proto, _mdns_server->hostname, port); +} + +esp_err_t mdns_service_txt_set_for_host(const char *service, const char *proto, const char *hostname, + mdns_txt_item_t txt[], uint8_t num_items) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || (num_items && txt == NULL)) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto); + mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -4624,13 +4813,17 @@ esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_tx return ESP_OK; } +esp_err_t mdns_service_txt_set(const char *service, const char *proto, mdns_txt_item_t txt[], uint8_t num_items) +{ + return mdns_service_txt_set_for_host(service, proto, _mdns_server->hostname, txt, num_items); +} -esp_err_t mdns_service_txt_item_set(const char * service, const char * proto, const char * key, const char * value) +esp_err_t mdns_service_txt_item_set_for_host(const char * service, const char * proto, const char *hostname, const char * key, const char * value) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(key) || !value) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto); + mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -4662,12 +4855,17 @@ esp_err_t mdns_service_txt_item_set(const char * service, const char * proto, co return ESP_OK; } -esp_err_t mdns_service_txt_item_remove(const char * service, const char * proto, const char * key) +esp_err_t mdns_service_txt_item_set(const char *service, const char *proto, const char *key, const char *value) +{ + return mdns_service_txt_item_set_for_host(service, proto, _mdns_server->hostname, key, value); +} + +esp_err_t mdns_service_txt_item_remove_for_host(const char * service, const char * proto, const char *hostname, const char * key) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(key)) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto); + mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -4692,7 +4890,13 @@ esp_err_t mdns_service_txt_item_remove(const char * service, const char * proto, return ESP_OK; } -esp_err_t mdns_service_instance_name_set(const char * service, const char * proto, const char * instance) +esp_err_t mdns_service_txt_item_remove(const char *service, const char *proto, const char *key) +{ + return mdns_service_txt_item_remove_for_host(service, proto, _mdns_server->hostname, key); +} + +esp_err_t mdns_service_instance_name_set_for_host(const char *service, const char *proto, const char *hostname, + const char *instance) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; @@ -4700,7 +4904,7 @@ esp_err_t mdns_service_instance_name_set(const char * service, const char * prot if (_str_null_or_empty(instance) || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto); + mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -4726,12 +4930,17 @@ esp_err_t mdns_service_instance_name_set(const char * service, const char * prot return ESP_OK; } -esp_err_t mdns_service_remove(const char * service, const char * proto) +esp_err_t mdns_service_instance_name_set(const char *service, const char *proto, const char *instance) +{ + return mdns_service_instance_name_set_for_host(service, proto, _mdns_server->hostname, instance); +} + +esp_err_t mdns_service_remove_for_host(const char * service, const char * proto, const char *hostname) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto); + mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -4750,6 +4959,11 @@ esp_err_t mdns_service_remove(const char * service, const char * proto) return ESP_OK; } +esp_err_t mdns_service_remove(const char *service_type, const char *proto) +{ + return mdns_service_remove_for_host(service_type, proto, _mdns_server->hostname); +} + esp_err_t mdns_service_remove_all(void) { if (!_mdns_server) { diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index d8d507413..b813c5b43 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -17,8 +17,10 @@ #include "esp_event_base.h" #include "esp_task.h" #include "esp_timer.h" +#include "esp_netif_ip_addr.h" +#include "freertos/FreeRTOS.h" -//#define MDNS_ENABLE_DEBUG +#define MDNS_ENABLE_DEBUG #ifdef MDNS_ENABLE_DEBUG #define _mdns_dbg_printf(...) printf(__VA_ARGS__) @@ -182,6 +184,7 @@ typedef enum { ACTION_TX_HANDLE, ACTION_RX_HANDLE, ACTION_TASK_STOP, + ACTION_DELEGATE_HOSTNAME_ADD, ACTION_MAX } mdns_action_type_t; @@ -280,6 +283,7 @@ typedef struct { const char * instance; const char * service; const char * proto; + const char * hostname; uint16_t priority; uint16_t weight; uint16_t port; @@ -302,12 +306,19 @@ typedef struct mdns_out_question_s { bool own_dynamic_memory; } mdns_out_question_t; +typedef struct mdns_host_item_t { + const char * hostname; + esp_ip_addr_t address; + struct mdns_host_item_t *next; +} mdns_host_item_t; + typedef struct mdns_out_answer_s { struct mdns_out_answer_s * next; uint16_t type; uint8_t bye; uint8_t flush; mdns_service_t * service; + mdns_host_item_t* host; const char * custom_instance; const char * custom_service; const char * custom_proto; @@ -381,7 +392,10 @@ typedef struct mdns_server_s { typedef struct { mdns_action_type_t type; union { - char * hostname; + struct { + char * hostname; + xTaskHandle calling_task; + } hostname_set; char * instance; struct { esp_event_base_t event_base; @@ -424,6 +438,10 @@ typedef struct { struct { mdns_rx_packet_t * packet; } rx_handle; + struct { + const char * hostname; + esp_ip_addr_t address; + } delegate_hostname; } data; } mdns_action_t; diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 8f655fdad..fcad5eaa7 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -24,34 +24,47 @@ #define EXAMPLE_BUTTON_GPIO 0 static const char *TAG = "mdns-test"; -static char* generate_hostname(void); +static char *generate_hostname(void); #if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 -static void query_mdns_host_with_gethostbyname(char * host); -static void query_mdns_host_with_getaddrinfo(char * host); +static void query_mdns_host_with_gethostbyname(char *host); +static void query_mdns_host_with_getaddrinfo(char *host); #endif static void initialise_mdns(void) { - char* hostname = generate_hostname(); + printf("generate_hostname\n"); + char *hostname = generate_hostname(); //initialize mDNS + printf("mdns_init\n"); ESP_ERROR_CHECK( mdns_init() ); + printf("mdns_hostname_set\n"); //set mDNS hostname (required if you want to advertise services) ESP_ERROR_CHECK( mdns_hostname_set(hostname) ); ESP_LOGI(TAG, "mdns hostname set to: [%s]", hostname); //set default mDNS instance name + printf("mdns_instance_name_set\n"); ESP_ERROR_CHECK( mdns_instance_name_set(EXAMPLE_MDNS_INSTANCE) ); //structure with TXT records mdns_txt_item_t serviceTxtData[3] = { - {"board","esp32"}, - {"u","user"}, - {"p","password"} + {"board", "esp32"}, + {"u", "user"}, + {"p", "password"} }; //initialize service + printf("mdns_service_add\n"); ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) ); + esp_ip_addr_t addr; + ip6_addr_t ip6_addr; + ip6addr_aton("fe80::849b:bb01:415c:b722", &ip6_addr); + addr.type = ESP_IPADDR_TYPE_V6; + memcpy(addr.u_addr.ip6.addr, ip6_addr.addr, sizeof(ip6_addr.addr)); + ESP_ERROR_CHECK(mdns_delegate_hostname_add("test-device", &addr)); + ESP_ERROR_CHECK( mdns_service_add_custom_host("test0", "_http", "_tcp", "test-device", 1234, serviceTxtData, 3) ); //add another TXT item + printf("mdns_service_txt_item_set\n"); ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") ); //change TXT item value ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "u", "admin") ); @@ -59,33 +72,34 @@ static void initialise_mdns(void) } /* these strings match tcpip_adapter_if_t enumeration */ -static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; +static const char *if_str[] = {"STA", "AP", "ETH", "MAX"}; /* these strings match mdns_ip_protocol_t enumeration */ -static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; +static const char *ip_protocol_str[] = {"V4", "V6", "MAX"}; -static void mdns_print_results(mdns_result_t * results){ - mdns_result_t * r = results; - mdns_ip_addr_t * a = NULL; +static void mdns_print_results(mdns_result_t *results) +{ + mdns_result_t *r = results; + mdns_ip_addr_t *a = NULL; int i = 1, t; - while(r){ + while (r) { printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]); - if(r->instance_name){ + if (r->instance_name) { printf(" PTR : %s\n", r->instance_name); } - if(r->hostname){ + if (r->hostname) { printf(" SRV : %s.local:%u\n", r->hostname, r->port); } - if(r->txt_count){ + if (r->txt_count) { printf(" TXT : [%u] ", r->txt_count); - for(t=0; ttxt_count; t++){ - printf("%s=%s; ", r->txt[t].key, r->txt[t].value?r->txt[t].value:"NULL"); + for (t = 0; t < r->txt_count; t++) { + printf("%s=%s; ", r->txt[t].key, r->txt[t].value ? r->txt[t].value : "NULL"); } printf("\n"); } a = r->addr; - while(a){ - if(a->addr.type == ESP_IPADDR_TYPE_V6){ + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); } else { printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); @@ -97,17 +111,17 @@ static void mdns_print_results(mdns_result_t * results){ } -static void query_mdns_service(const char * service_name, const char * proto) +static void query_mdns_service(const char *service_name, const char *proto) { ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); - mdns_result_t * results = NULL; + mdns_result_t *results = NULL; esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); - if(err){ + if (err) { ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); return; } - if(!results){ + if (!results) { ESP_LOGW(TAG, "No results found!"); return; } @@ -116,7 +130,7 @@ static void query_mdns_service(const char * service_name, const char * proto) mdns_query_results_free(results); } -static void query_mdns_host(const char * host_name) +static void query_mdns_host(const char *host_name) { ESP_LOGI(TAG, "Query A: %s.local", host_name); @@ -124,8 +138,8 @@ static void query_mdns_host(const char * host_name) addr.addr = 0; esp_err_t err = mdns_query_a(host_name, 2000, &addr); - if(err){ - if(err == ESP_ERR_NOT_FOUND){ + if (err) { + if (err == ESP_ERR_NOT_FOUND) { ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err)); return; } @@ -174,7 +188,7 @@ static void mdns_example_task(void *pvParameters) query_mdns_host_with_getaddrinfo("tinytester-lwip.local"); #endif - while(1) { + while (1) { check_button(); vTaskDelay(50 / portTICK_PERIOD_MS); } @@ -201,7 +215,7 @@ void app_main(void) /** Generate host name based on sdkconfig, optionally adding a portion of MAC address to it. * @return host name string allocated from the heap */ -static char* generate_hostname(void) +static char *generate_hostname(void) { #ifndef CONFIG_MDNS_ADD_MAC_TO_HOSTNAME return strdup(CONFIG_MDNS_HOSTNAME); @@ -221,7 +235,7 @@ static char* generate_hostname(void) * @brief Executes gethostbyname and displays list of resolved addresses. * Note: This function is used only to test advertised mdns hostnames resolution */ -static void query_mdns_host_with_gethostbyname(char * host) +static void query_mdns_host_with_gethostbyname(char *host) { struct hostent *res = gethostbyname(host); if (res) { @@ -237,10 +251,10 @@ static void query_mdns_host_with_gethostbyname(char * host) * @brief Executes getaddrinfo and displays list of resolved addresses. * Note: This function is used only to test advertised mdns hostnames resolution */ -static void query_mdns_host_with_getaddrinfo(char * host) +static void query_mdns_host_with_getaddrinfo(char *host) { struct addrinfo hints; - struct addrinfo * res; + struct addrinfo *res; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -249,8 +263,8 @@ static void query_mdns_host_with_getaddrinfo(char * host) if (!getaddrinfo(host, NULL, &hints, &res)) { while (res) { ESP_LOGI(TAG, "getaddrinfo: %s resolved to: %s", host, - res->ai_family == AF_INET? - inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr): + res->ai_family == AF_INET ? + inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr) : inet_ntoa(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr)); res = res->ai_next; } From c8821199a22bfcccb56e6c83a722c47e78e94919 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Fri, 2 Apr 2021 18:06:10 +0800 Subject: [PATCH 186/289] mdns: add remove delegate host api * Original commit: espressif/esp-idf@2174693096b73ce93261611c44ecba647cd01859 --- components/mdns/include/mdns.h | 2 + components/mdns/mdns.c | 76 +++++++++++++++++++ .../mdns/private_include/mdns_private.h | 1 + .../protocols/mdns/main/mdns_example_main.c | 6 ++ 4 files changed, 85 insertions(+) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index dcf8972bd..54cd8a3ee 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -116,6 +116,8 @@ esp_err_t mdns_hostname_set(const char * hostname); esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t *address); +esp_err_t mdns_delegate_hostname_remove(const char * hostname); + bool mdns_hostname_exists(const char *hostname); /** diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 2a715fe30..35aa4e09c 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2472,6 +2472,48 @@ static bool _mdns_delegate_hostname_add(const char *hostname, const esp_ip_addr_ return true; } +static bool _mdns_delegate_hostname_remove(const char *hostname) +{ + mdns_srv_item_t *srv = _mdns_server->services; + mdns_srv_item_t *prev_srv = NULL; + while (srv) { + if (strcasecmp(srv->service->hostname, hostname) == 0) { + mdns_srv_item_t *to_free = srv; + _mdns_send_bye(&srv, 1, false); + _mdns_remove_scheduled_service_packets(srv->service); + if (prev_srv == NULL) { + _mdns_server->services = srv->next; + srv = srv->next; + } else { + prev_srv->next = srv->next; + } + _mdns_free_service(to_free->service); + free(to_free); + } else { + prev_srv = srv; + srv = srv->next; + } + } + mdns_host_item_t *host = _mdns_host_list; + mdns_host_item_t *prev_host = NULL; + while (host != NULL) { + if (strcasecmp(hostname, host->hostname) == 0) { + if (prev_host == NULL) { + _mdns_host_list = host->next; + } else { + prev_host->next = host->next; + } + free((char *)host->hostname); + free(host); + break; + } else { + prev_host = host; + host = host->next; + } + } + return true; +} + /** * @brief Check if parsed name is discovery */ @@ -4191,6 +4233,11 @@ static void _mdns_execute_action(mdns_action_t * action) break; case ACTION_DELEGATE_HOSTNAME_ADD: _mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, &action->data.delegate_hostname.address); + break; + case ACTION_DELEGATE_HOSTNAME_REMOVE: + _mdns_delegate_hostname_remove(action->data.delegate_hostname.hostname); + free((char *)action->data.delegate_hostname.hostname); + break; default: break; } @@ -4636,6 +4683,35 @@ esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t return ERR_OK; } +esp_err_t mdns_delegate_hostname_remove(const char * hostname) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_ARG; + } + if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + return ESP_ERR_INVALID_ARG; + } + char * new_hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); + if (!new_hostname) { + return ESP_ERR_NO_MEM; + } + + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + free(new_hostname); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_DELEGATE_HOSTNAME_REMOVE; + action->data.delegate_hostname.hostname = new_hostname; + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(new_hostname); + free(action); + return ESP_ERR_NO_MEM; + } + return ERR_OK; +} + bool mdns_hostname_exists(const char *hostname) { return _hostname_is_ours(hostname); } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index b813c5b43..6acdf9283 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -185,6 +185,7 @@ typedef enum { ACTION_RX_HANDLE, ACTION_TASK_STOP, ACTION_DELEGATE_HOSTNAME_ADD, + ACTION_DELEGATE_HOSTNAME_REMOVE, ACTION_MAX } mdns_action_type_t; diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index fcad5eaa7..525193d20 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -187,10 +187,16 @@ static void mdns_example_task(void *pvParameters) query_mdns_host_with_gethostbyname("tinytester-lwip.local"); query_mdns_host_with_getaddrinfo("tinytester-lwip.local"); #endif + bool removed = false; while (1) { check_button(); vTaskDelay(50 / portTICK_PERIOD_MS); + if (pdTICKS_TO_MS(xTaskGetTickCount()) >= 15 * 1000 && ! removed) { + printf("Remove device\n"); + ESP_ERROR_CHECK(mdns_delegate_hostname_remove("test-device")); + removed = true; + } } } From 4049b3b5ed2fece2d3c4e92d02e99d54fda98e46 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Wed, 7 Apr 2021 16:21:16 +0800 Subject: [PATCH 187/289] mdns: make delegate host address a list Also adds unit test and doc string for new apis. * Original commit: espressif/esp-idf@2d34352f3db0fa71366a838933a29138a90eb2af --- components/mdns/include/mdns.h | 177 +++++++++++- components/mdns/mdns.c | 263 +++++++++++------- .../mdns/private_include/mdns_private.h | 7 +- components/mdns/test/test_mdns.c | 15 + .../mdns/test_afl_fuzz_host/esp32_compat.h | 1 + .../mdns/test_afl_fuzz_host/esp32_mock.c | 15 + .../mdns/test_afl_fuzz_host/esp32_mock.h | 5 + components/mdns/test_afl_fuzz_host/mdns_di.h | 6 +- .../protocols/mdns/main/mdns_example_main.c | 87 +++--- 9 files changed, 419 insertions(+), 157 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 54cd8a3ee..416740d13 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -114,11 +114,49 @@ void mdns_free(void); */ esp_err_t mdns_hostname_set(const char * hostname); -esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t *address); +/** + * @brief Adds a hostname and address to be delegated + * A/AAAA queries will be replied for the hostname and + * services can be added to this host. + * + * @param hostname Hostname to add + * @param address_list The IP address list of the host + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + * + */ +esp_err_t mdns_delegate_hostname_add(const char * hostname, const mdns_ip_addr_t *address_list); +/** + * @brief Remove a delegated hostname + * All the services added to this host will also be removed. + * + * @param hostname Hostname to remove + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + * + */ esp_err_t mdns_delegate_hostname_remove(const char * hostname); -bool mdns_hostname_exists(const char *hostname); +/** + * @brief Query whether a hostname has been added + * + * @param hostname Hostname to query + * + * @return + * - true The hostname has been added. + * - false The hostname has not been added. + * + */ +bool mdns_hostname_exists(const char * hostname); /** * @brief Set the default instance name for mDNS server @@ -152,10 +190,39 @@ esp_err_t mdns_instance_name_set(const char * instance_name); 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); -esp_err_t mdns_service_add_custom_host(const char *instance_name, const char *service_type, const char *proto, - const char *hostname, uint16_t port, mdns_txt_item_t txt[], size_t num_items); +/** + * @brief Add service to mDNS server with a delegated hostname + * + * @param instance_name instance name to set. If NULL, + * global instance name or hostname will be used + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param port service port + * @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 service + */ +esp_err_t mdns_service_add_for_host(const char * instance_name, const char * service_type, const char * proto, + const char * hostname, uint16_t port, mdns_txt_item_t txt[], size_t num_items); -bool mdns_service_exists(const char *service_type, const char *proto, const char *hostname); +/** + * @brief Check whether a service has been added. + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, checks for the local hostname. + * + * @return + * - true Correspondding service has been added. + * - false Service not found. + */ +bool mdns_service_exists(const char * service_type, const char * proto, const char * hostname); /** * @brief Remove service from mDNS server @@ -171,6 +238,19 @@ bool mdns_service_exists(const char *service_type, const char *proto, const char */ esp_err_t mdns_service_remove(const char * service_type, const char * proto); +/** + * @brief Remove service from mDNS server with hostname + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * + * @return + * - 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_remove_for_host(const char * service_type, const char * proto, const char *hostname); /** @@ -188,7 +268,22 @@ esp_err_t mdns_service_remove_for_host(const char * service_type, const char * p */ esp_err_t mdns_service_instance_name_set(const char * service_type, const char * proto, const char * instance_name); -esp_err_t mdns_service_instance_name_set_for_host(const char * service_type, const char * proto, const char *hostname, const char * instance_name); +/** + * @brief Set instance name for service with hostname + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param instance_name instance name to set + * + * @return + * - 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_instance_name_set_for_host(const char * service_type, const char * proto, const char * hostname, + const char * instance_name); /** * @brief Set service port @@ -206,7 +301,21 @@ esp_err_t mdns_service_instance_name_set_for_host(const char * service_type, con esp_err_t mdns_service_port_set(const char * service_type, const char * proto, uint16_t port); -esp_err_t mdns_service_port_set_for_host(const char *service_type, const char *proto, const char *hostname, +/** + * @brief Set service port with hostname + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param port service port + * + * @return + * - 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_for_host(const char * service_type, const char * proto, const char * hostname, uint16_t port); /** @@ -225,7 +334,22 @@ esp_err_t mdns_service_port_set_for_host(const char *service_type, const char *p */ esp_err_t mdns_service_txt_set(const char * service_type, const char * proto, mdns_txt_item_t txt[], uint8_t num_items); -esp_err_t mdns_service_txt_set_for_host(const char *service_type, const char *proto, const char *hostname, +/** + * @brief Replace all TXT items for service with hostname + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param txt 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_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_txt_set_for_host(const char * service_type, const char * proto, const char * hostname, mdns_txt_item_t txt[], uint8_t num_items); /** @@ -245,8 +369,23 @@ esp_err_t mdns_service_txt_set_for_host(const char *service_type, const char *pr esp_err_t mdns_service_txt_item_set(const char * service_type, const char * proto, const char * key, const char * value); -esp_err_t mdns_service_txt_item_set_for_host(const char *service_type, const char *proto, const char *hostname, - const char *key, const char *value); +/** + * @brief Set/Add TXT item for service TXT record with hostname + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param key the key that you want to add/update + * @param value the new value of the key + * + * @return + * - 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_txt_item_set_for_host(const char * service_type, const char * proto, const char * hostname, + const char * key, const char * value); /** * @brief Remove TXT item for service TXT record @@ -263,8 +402,22 @@ esp_err_t mdns_service_txt_item_set_for_host(const char *service_type, const cha */ esp_err_t mdns_service_txt_item_remove(const char * service_type, const char * proto, const char * key); -esp_err_t mdns_service_txt_item_remove_for_host(const char *service_type, const char *proto, const char *hostname, - const char *key); +/** + * @brief Remove TXT item for service TXT record with hostname + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param key the key that you want to remove + * + * @return + * - 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_txt_item_remove_for_host(const char * service_type, const char * proto, const char * hostname, + const char * key); /** * @brief Remove and free all services from mDNS server diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 35aa4e09c..e72dce5ae 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -31,7 +31,7 @@ static const char * MDNS_DEFAULT_DOMAIN = "local"; static const char * MDNS_SUB_STR = "_sub"; mdns_server_t * _mdns_server = NULL; -static mdns_host_item_t *_mdns_host_list = NULL; +static mdns_host_item_t * _mdns_host_list = NULL; static mdns_host_item_t _mdns_self_host; static const char *TAG = "MDNS"; @@ -146,7 +146,8 @@ static char * _mdns_mangle_name(char* in) { return ret; } -static bool _mdns_service_match(const mdns_service_t *srv, const char *service, const char *proto, const char *hostname) +static bool _mdns_service_match(const mdns_service_t * srv, const char * service, const char * proto, + const char * hostname) { return !strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && (_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); @@ -160,7 +161,7 @@ static bool _mdns_service_match(const mdns_service_t *srv, const char *service, * * @return the service item if found or NULL on error */ -static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto, const char *hostname) +static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto, const char * hostname) { mdns_srv_item_t * s = _mdns_server->services; while (s) { @@ -172,14 +173,14 @@ static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char return NULL; } -static mdns_host_item_t *mdns_get_host_item(const char *hostname, uint8_t address_type) +static mdns_host_item_t * mdns_get_host_item(const char * hostname) { if (hostname == NULL || strcasecmp(hostname, _mdns_server->hostname) == 0) { return &_mdns_self_host; } - mdns_host_item_t *host = _mdns_host_list; + mdns_host_item_t * host = _mdns_host_list; while (host != NULL) { - if (strcasecmp(host->hostname, hostname) == 0 && host->address.type == address_type) { + if (strcasecmp(host->hostname, hostname) == 0) { return host; } host = host->next; @@ -754,7 +755,7 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns * * @param packet MDNS packet * @param index offset in the packet - * @param server the server + * @param hostname the hostname address to add * @param ip the IP address to add * * @return length of added data: 0 on error or length on success @@ -805,7 +806,7 @@ static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, const * * @param packet MDNS packet * @param index offset in the packet - * @param hostnamek the hostname address to add + * @param hostname the hostname address to add * @param ipv6 the IPv6 address to add * * @return length of added data: 0 on error or length on success @@ -932,11 +933,36 @@ static bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) } #endif +static uint8_t _mdns_append_host_answer(uint8_t * packet, uint16_t * index, mdns_host_item_t * host, + uint8_t address_type, bool flush, bool bye) +{ + mdns_ip_addr_t * addr = host->address_list; + uint8_t num_records = 0; + + while (addr != NULL) { + if (addr->addr.type == address_type) { + if (address_type == ESP_IPADDR_TYPE_V4 && + _mdns_append_a_record(packet, index, host->hostname, addr->addr.u_addr.ip4.addr, flush, bye) <= 0) { + break; + } +#if CONFIG_LWIP_IPV6 + if (address_type == ESP_IPADDR_TYPE_V6 && + _mdns_append_aaaa_record(packet, index, host->hostname, (uint8_t *)addr->addr.u_addr.ip6.addr, flush, + bye) <= 0) { + break; + } +#endif // CONFIG_LWIP_IPV6 + num_records++; + } + addr = addr->next; + } + return num_records; +} + /** * @brief Append answer to packet * * @return number of answers added to the packet - * XXX: create the answers here */ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_answer_t * answer, mdns_if_t tcpip_if) { @@ -982,11 +1008,7 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ } return 1; } else if (answer->host != NULL) { - if (_mdns_append_a_record(packet, index, answer->host->hostname, answer->host->address.u_addr.ip4.addr, answer->flush, answer->bye) <= 0) { - return 0; - } else { - return 1; - } + return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V4, answer->flush, answer->bye); } } #if CONFIG_LWIP_IPV6 @@ -1017,12 +1039,7 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_ } return 1; } else if (answer->host != NULL) { - if (_mdns_append_aaaa_record(packet, index, answer->host->hostname, (uint8_t*)answer->host->address.u_addr.ip6.addr, answer->flush, answer->bye) <= 0) { - return 0; - } else { - return 1; - } - + return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V6, answer->flush, answer->bye); } } #endif @@ -1278,7 +1295,8 @@ static void _mdns_dealloc_answer(mdns_out_answer_t ** destination, uint16_t type /** * @brief Allocate new answer and add it to answer list (destination) */ -static bool _mdns_alloc_answer(mdns_out_answer_t ** destination, uint16_t type, mdns_service_t * service, mdns_host_item_t *host, bool flush, bool bye) +static bool _mdns_alloc_answer(mdns_out_answer_t ** destination, uint16_t type, mdns_service_t * service, + mdns_host_item_t * host, bool flush, bool bye) { mdns_out_answer_t * d = *destination; while (d) { @@ -1330,25 +1348,24 @@ static mdns_tx_packet_t * _mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip return packet; } -static bool _mdns_create_answer_from_service(mdns_tx_packet_t *packet, mdns_service_t *service, - mdns_parsed_question_t *question, bool shared, bool send_flush) +static bool _mdns_create_answer_from_service(mdns_tx_packet_t * packet, mdns_service_t * service, + mdns_parsed_question_t * question, bool shared, bool send_flush) { - mdns_host_item_t *host4 = mdns_get_host_item(service->hostname, ESP_IPADDR_TYPE_V4); - mdns_host_item_t *host6 = mdns_get_host_item(service->hostname, ESP_IPADDR_TYPE_V6); + mdns_host_item_t * host = mdns_get_host_item(service->hostname); if (question->type == MDNS_TYPE_PTR || question->type == MDNS_TYPE_ANY) { if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service, NULL, false, false) || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false) || - !_mdns_alloc_answer(shared ? &packet->additional : &packet->answers, MDNS_TYPE_A, service, host4, - send_flush, false) || - !_mdns_alloc_answer(shared ? &packet->additional : &packet->answers, MDNS_TYPE_AAAA, service, host6, + !_mdns_alloc_answer(shared ? &packet->additional : &packet->answers, MDNS_TYPE_A, service, host, send_flush, + false) || + !_mdns_alloc_answer(shared ? &packet->additional : &packet->answers, MDNS_TYPE_AAAA, service, host, send_flush, false)) { return false; } } else if (question->type == MDNS_TYPE_SRV) { if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || - !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_A, service, host4, send_flush, false) || - !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_AAAA, service, host6, send_flush, false)) { + !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_A, service, host, send_flush, false) || + !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_AAAA, service, host, send_flush, false)) { return false; } } else if (question->type == MDNS_TYPE_TXT) { @@ -1364,14 +1381,11 @@ static bool _mdns_create_answer_from_service(mdns_tx_packet_t *packet, mdns_serv return true; } -static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t *packet, const char *hostname, bool send_flush) +static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t * packet, const char * hostname, bool send_flush) { - mdns_host_item_t *host4; - mdns_host_item_t *host6; - host4 = mdns_get_host_item(hostname, ESP_IPADDR_TYPE_V4); - host6 = mdns_get_host_item(hostname, ESP_IPADDR_TYPE_V6); - if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host4, send_flush, false) || - !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host6, send_flush, false)) { + mdns_host_item_t * host = mdns_get_host_item(hostname); + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host, send_flush, false) || + !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, send_flush, false)) { return false; } return true; @@ -1379,7 +1393,6 @@ static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t *packet, const ch /** * @brief Create answer packet to questions from parsed packet - * XXX: reply from here */ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) { @@ -1486,9 +1499,10 @@ static bool _mdns_question_exists(mdns_out_question_t * needle, mdns_out_questio return false; } -bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye) { +bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye) +{ if (!_str_null_or_empty(_mdns_server->hostname)) { - mdns_host_item_t *self_host = mdns_get_host_item(_mdns_server->hostname, ESP_IPADDR_TYPE_ANY); + mdns_host_item_t * self_host = mdns_get_host_item(_mdns_server->hostname); if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, self_host, flush, bye)) { return false; } @@ -1496,16 +1510,13 @@ bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool b return false; } } - mdns_host_item_t *host = _mdns_host_list; - while(host != NULL) { - if (host->address.type == ESP_IPADDR_TYPE_V4) { - if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { - return false; - } - } else if (host->address.type == ESP_IPADDR_TYPE_V6) { - if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { - return false; - } + mdns_host_item_t * host = _mdns_host_list; + while (host != NULL) { + if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { + return false; + } + if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { + return false; } host = host->next; } @@ -2048,7 +2059,9 @@ static void _mdns_free_linked_txt(mdns_txt_linked_item_t *txt) * * @return pointer to the service or NULL on error */ -static mdns_service_t * _mdns_create_service(const char * service, const char * proto, const char *hostname, uint16_t port, const char * instance, size_t num_items, mdns_txt_item_t txt[]) +static mdns_service_t * _mdns_create_service(const char * service, const char * proto, const char * hostname, + uint16_t port, const char * instance, size_t num_items, + mdns_txt_item_t txt[]) { mdns_service_t * s = (mdns_service_t *)malloc(sizeof(mdns_service_t)); if (!s) { @@ -2068,7 +2081,6 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * s->txt = new_txt; s->port = port; - assert(hostname != NULL); if (hostname) { s->hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); if (!s->hostname) { @@ -2219,6 +2231,9 @@ static void _mdns_free_service(mdns_service_t * service) free((char *)service->instance); free((char *)service->service); free((char *)service->proto); + if (service->hostname) { + free((char *)service->hostname); + } while (service->txt) { mdns_txt_linked_item_t * s = service->txt; service->txt = service->txt->next; @@ -2439,12 +2454,12 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t * ip, mdns_if_t tcpip_if) } #endif -static bool _hostname_is_ours(const char *hostname) +static bool _hostname_is_ours(const char * hostname) { if (strcasecmp(hostname, _mdns_server->hostname) == 0) { return true; } - mdns_host_item_t *host = _mdns_host_list; + mdns_host_item_t * host = _mdns_host_list; while (host != NULL) { if (strcasecmp(hostname, host->hostname) == 0) { return true; @@ -2454,31 +2469,64 @@ static bool _hostname_is_ours(const char *hostname) return false; } -static bool _mdns_delegate_hostname_add(const char *hostname, const esp_ip_addr_t *address) +static bool _mdns_delegate_hostname_add(const char * hostname, mdns_ip_addr_t * address_list) { if (_hostname_is_ours(hostname)) { return true; } - mdns_host_item_t *host = (mdns_host_item_t *)malloc(sizeof(mdns_host_item_t)); + mdns_host_item_t * host = (mdns_host_item_t *)malloc(sizeof(mdns_host_item_t)); if (host == NULL) { return false; } - host->address = *address; + host->address_list = address_list; host->hostname = hostname; host->next = _mdns_host_list; _mdns_host_list = host; return true; } -static bool _mdns_delegate_hostname_remove(const char *hostname) +static void free_address_list(mdns_ip_addr_t * address_list) { - mdns_srv_item_t *srv = _mdns_server->services; - mdns_srv_item_t *prev_srv = NULL; + while (address_list != NULL) { + mdns_ip_addr_t * next = address_list->next; + free(address_list); + address_list = next; + } +} + +static mdns_ip_addr_t * copy_address_list(const mdns_ip_addr_t * address_list) +{ + mdns_ip_addr_t * head = NULL; + mdns_ip_addr_t * tail = NULL; + while (address_list != NULL) { + mdns_ip_addr_t * addr = (mdns_ip_addr_t *)malloc(sizeof(mdns_ip_addr_t)); + if (addr == NULL) { + free_address_list(head); + return NULL; + } + addr->addr = address_list->addr; + addr->next = NULL; + if (head == NULL) { + head = addr; + tail = addr; + } else { + tail->next = addr; + tail = tail->next; + } + address_list = address_list->next; + } + return head; +} + +static bool _mdns_delegate_hostname_remove(const char * hostname) +{ + mdns_srv_item_t * srv = _mdns_server->services; + mdns_srv_item_t * prev_srv = NULL; while (srv) { if (strcasecmp(srv->service->hostname, hostname) == 0) { - mdns_srv_item_t *to_free = srv; + mdns_srv_item_t * to_free = srv; _mdns_send_bye(&srv, 1, false); _mdns_remove_scheduled_service_packets(srv->service); if (prev_srv == NULL) { @@ -2486,6 +2534,7 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) srv = srv->next; } else { prev_srv->next = srv->next; + srv = srv->next; } _mdns_free_service(to_free->service); free(to_free); @@ -2494,8 +2543,8 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) srv = srv->next; } } - mdns_host_item_t *host = _mdns_host_list; - mdns_host_item_t *prev_host = NULL; + mdns_host_item_t * host = _mdns_host_list; + mdns_host_item_t * prev_host = NULL; while (host != NULL) { if (strcasecmp(hostname, host->hostname) == 0) { if (prev_host == NULL) { @@ -2503,6 +2552,8 @@ static bool _mdns_delegate_hostname_remove(const char *hostname) } else { prev_host->next = host->next; } + printf("Free host %p\n", host); + free_address_list(host->address_list); free((char *)host->hostname); free(host); break; @@ -2542,7 +2593,7 @@ static bool _mdns_name_is_ours(mdns_name_t * name) if (_str_null_or_empty(name->service) && _str_null_or_empty(name->proto)) { if (!_str_null_or_empty(name->host) && !_str_null_or_empty(_mdns_server->hostname) - && _hostname_is_ours(name->host) == 0) + && _hostname_is_ours(name->host)) { return true; } @@ -4232,7 +4283,8 @@ static void _mdns_execute_action(mdns_action_t * action) free(action->data.rx_handle.packet); break; case ACTION_DELEGATE_HOSTNAME_ADD: - _mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, &action->data.delegate_hostname.address); + _mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, + action->data.delegate_hostname.address_list); break; case ACTION_DELEGATE_HOSTNAME_REMOVE: _mdns_delegate_hostname_remove(action->data.delegate_hostname.hostname); @@ -4644,7 +4696,6 @@ esp_err_t mdns_hostname_set(const char * hostname) action->data.hostname_set.hostname = new_hostname; action->data.hostname_set.calling_task = xTaskGetCurrentTaskHandle(); if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { - assert(false); free(new_hostname); free(action); return ESP_ERR_NO_MEM; @@ -4653,12 +4704,12 @@ esp_err_t mdns_hostname_set(const char * hostname) return ERR_OK; } -esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t *address) +esp_err_t mdns_delegate_hostname_add(const char * hostname, const mdns_ip_addr_t * address_list) { if (!_mdns_server) { - return ESP_ERR_INVALID_ARG; + return ESP_ERR_INVALID_STATE; } - if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1) || address_list == NULL) { return ESP_ERR_INVALID_ARG; } char * new_hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); @@ -4674,7 +4725,7 @@ esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t } action->type = ACTION_DELEGATE_HOSTNAME_ADD; action->data.delegate_hostname.hostname = new_hostname; - action->data.delegate_hostname.address = *address; + action->data.delegate_hostname.address_list = copy_address_list(address_list); if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { free(new_hostname); free(action); @@ -4686,7 +4737,7 @@ esp_err_t mdns_delegate_hostname_add(const char * hostname, const esp_ip_addr_t esp_err_t mdns_delegate_hostname_remove(const char * hostname) { if (!_mdns_server) { - return ESP_ERR_INVALID_ARG; + return ESP_ERR_INVALID_STATE; } if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; @@ -4712,14 +4763,15 @@ esp_err_t mdns_delegate_hostname_remove(const char * hostname) return ERR_OK; } -bool mdns_hostname_exists(const char *hostname) { +bool mdns_hostname_exists(const char * hostname) +{ return _hostname_is_ours(hostname); } esp_err_t mdns_instance_name_set(const char * instance) { if (!_mdns_server) { - return ESP_ERR_INVALID_ARG; + return ESP_ERR_INVALID_STATE; } if (_str_null_or_empty(instance) || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; @@ -4749,9 +4801,8 @@ esp_err_t mdns_instance_name_set(const char * instance) * MDNS SERVICES * */ -esp_err_t mdns_service_add_custom_host(const char *instance, const char *service, const char *proto, - const char *hostname, uint16_t port, - mdns_txt_item_t txt[], size_t num_items) +esp_err_t mdns_service_add_for_host(const char * instance, const char * service, const char * proto, + const char * hostname, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { return ESP_ERR_INVALID_ARG; @@ -4799,8 +4850,7 @@ esp_err_t mdns_service_add_custom_host(const char *instance, const char *service size_t start = xTaskGetTickCount(); size_t timeout_ticks = pdMS_TO_TICKS(MDNS_SERVICE_ADD_TIMEOUT_MS); - while (_mdns_get_service_item(service, proto, hostname) == NULL) - { + while (_mdns_get_service_item(service, proto, hostname) == NULL) { uint32_t expired = xTaskGetTickCount() - start; if (expired >= timeout_ticks) { return ESP_FAIL; // Timeout @@ -4811,19 +4861,21 @@ esp_err_t mdns_service_add_custom_host(const char *instance, const char *service return ESP_OK; } -esp_err_t mdns_service_add(const char *instance, const char *service, const char *proto, uint16_t port, +esp_err_t mdns_service_add(const char * instance, const char * service, const char * proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - assert(_mdns_server->hostname != NULL); - return mdns_service_add_custom_host(instance, service, proto, _mdns_server->hostname, port, txt, num_items); + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + return mdns_service_add_for_host(instance, service, proto, _mdns_server->hostname, port, txt, num_items); } -bool mdns_service_exists(const char *service_type, const char *proto, const char *hostname) +bool mdns_service_exists(const char * service_type, const char * proto, const char * hostname) { return _mdns_get_service_item(service_type, proto, hostname) != NULL; } -esp_err_t mdns_service_port_set_for_host(const char *service, const char *proto, const char *hostname, uint16_t port) +esp_err_t mdns_service_port_set_for_host(const char * service, const char * proto, const char * hostname, uint16_t port) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { return ESP_ERR_INVALID_ARG; @@ -4848,11 +4900,15 @@ esp_err_t mdns_service_port_set_for_host(const char *service, const char *proto, return ESP_OK; } -esp_err_t mdns_service_port_set(const char *service, const char *proto, uint16_t port) { +esp_err_t mdns_service_port_set(const char * service, const char * proto, uint16_t port) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } return mdns_service_port_set_for_host(service, proto, _mdns_server->hostname, port); } -esp_err_t mdns_service_txt_set_for_host(const char *service, const char *proto, const char *hostname, +esp_err_t mdns_service_txt_set_for_host(const char * service, const char * proto, const char * hostname, mdns_txt_item_t txt[], uint8_t num_items) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || (num_items && txt == NULL)) { @@ -4889,12 +4945,16 @@ esp_err_t mdns_service_txt_set_for_host(const char *service, const char *proto, return ESP_OK; } -esp_err_t mdns_service_txt_set(const char *service, const char *proto, mdns_txt_item_t txt[], uint8_t num_items) +esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_txt_item_t txt[], uint8_t num_items) { + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } return mdns_service_txt_set_for_host(service, proto, _mdns_server->hostname, txt, num_items); } -esp_err_t mdns_service_txt_item_set_for_host(const char * service, const char * proto, const char *hostname, const char * key, const char * value) +esp_err_t mdns_service_txt_item_set_for_host(const char * service, const char * proto, const char * hostname, + const char * key, const char * value) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(key) || !value) { return ESP_ERR_INVALID_ARG; @@ -4931,12 +4991,16 @@ esp_err_t mdns_service_txt_item_set_for_host(const char * service, const char * return ESP_OK; } -esp_err_t mdns_service_txt_item_set(const char *service, const char *proto, const char *key, const char *value) +esp_err_t mdns_service_txt_item_set(const char * service, const char * proto, const char * key, const char * value) { + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } return mdns_service_txt_item_set_for_host(service, proto, _mdns_server->hostname, key, value); } -esp_err_t mdns_service_txt_item_remove_for_host(const char * service, const char * proto, const char *hostname, const char * key) +esp_err_t mdns_service_txt_item_remove_for_host(const char * service, const char * proto, const char * hostname, + const char * key) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(key)) { return ESP_ERR_INVALID_ARG; @@ -4966,13 +5030,16 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char * service, const char return ESP_OK; } -esp_err_t mdns_service_txt_item_remove(const char *service, const char *proto, const char *key) +esp_err_t mdns_service_txt_item_remove(const char * service, const char * proto, const char * key) { + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } return mdns_service_txt_item_remove_for_host(service, proto, _mdns_server->hostname, key); } -esp_err_t mdns_service_instance_name_set_for_host(const char *service, const char *proto, const char *hostname, - const char *instance) +esp_err_t mdns_service_instance_name_set_for_host(const char * service, const char * proto, const char * hostname, + const char * instance) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; @@ -5006,12 +5073,15 @@ esp_err_t mdns_service_instance_name_set_for_host(const char *service, const cha return ESP_OK; } -esp_err_t mdns_service_instance_name_set(const char *service, const char *proto, const char *instance) +esp_err_t mdns_service_instance_name_set(const char * service, const char * proto, const char * instance) { + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } return mdns_service_instance_name_set_for_host(service, proto, _mdns_server->hostname, instance); } -esp_err_t mdns_service_remove_for_host(const char * service, const char * proto, const char *hostname) +esp_err_t mdns_service_remove_for_host(const char * service, const char * proto, const char * hostname) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; @@ -5035,8 +5105,11 @@ esp_err_t mdns_service_remove_for_host(const char * service, const char * proto, return ESP_OK; } -esp_err_t mdns_service_remove(const char *service_type, const char *proto) +esp_err_t mdns_service_remove(const char * service_type, const char * proto) { + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } return mdns_service_remove_for_host(service_type, proto, _mdns_server->hostname); } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 6acdf9283..4b8f8806c 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -19,8 +19,9 @@ #include "esp_timer.h" #include "esp_netif_ip_addr.h" #include "freertos/FreeRTOS.h" +#include "mdns.h" -#define MDNS_ENABLE_DEBUG +//#define MDNS_ENABLE_DEBUG #ifdef MDNS_ENABLE_DEBUG #define _mdns_dbg_printf(...) printf(__VA_ARGS__) @@ -309,7 +310,7 @@ typedef struct mdns_out_question_s { typedef struct mdns_host_item_t { const char * hostname; - esp_ip_addr_t address; + mdns_ip_addr_t *address_list; struct mdns_host_item_t *next; } mdns_host_item_t; @@ -441,7 +442,7 @@ typedef struct { } rx_handle; struct { const char * hostname; - esp_ip_addr_t address; + mdns_ip_addr_t *address_list; } delegate_hostname; } data; } mdns_action_t; diff --git a/components/mdns/test/test_mdns.c b/components/mdns/test/test_mdns.c index 9dc9fe090..abdad0e63 100644 --- a/components/mdns/test/test_mdns.c +++ b/components/mdns/test/test_mdns.c @@ -4,6 +4,7 @@ #define MDNS_HOSTNAME "test-hostname" +#define MDNS_DELEGATE_HOSTNAME "delegate-hostname" #define MDNS_INSTANCE "test-instance" #define MDNS_SERVICE_NAME "_http" #define MDNS_SERVICE_PROTO "_tcp" @@ -42,6 +43,10 @@ TEST_CASE("mdns api return expected err-code and do not leak memory", "[mdns][le { mdns_txt_item_t serviceTxtData[CONFIG_MDNS_MAX_SERVICES] = { {NULL, NULL}, }; + 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; for (int i=0; itcpip_if], ip_protocol_str[r->ip_protocol]); - if (r->instance_name) { + if(r->instance_name){ printf(" PTR : %s\n", r->instance_name); } - if (r->hostname) { + if(r->hostname){ printf(" SRV : %s.local:%u\n", r->hostname, r->port); } - if (r->txt_count) { + if(r->txt_count){ printf(" TXT : [%u] ", r->txt_count); - for (t = 0; t < r->txt_count; t++) { - printf("%s=%s; ", r->txt[t].key, r->txt[t].value ? r->txt[t].value : "NULL"); + for(t=0; ttxt_count; t++){ + printf("%s=%s; ", r->txt[t].key, r->txt[t].value?r->txt[t].value:"NULL"); } printf("\n"); } a = r->addr; - while (a) { - if (a->addr.type == ESP_IPADDR_TYPE_V6) { + while(a){ + if(a->addr.type == ESP_IPADDR_TYPE_V6){ printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); } else { printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); @@ -111,17 +110,17 @@ static void mdns_print_results(mdns_result_t *results) } -static void query_mdns_service(const char *service_name, const char *proto) +static void query_mdns_service(const char * service_name, const char * proto) { ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); - mdns_result_t *results = NULL; + mdns_result_t * results = NULL; esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); - if (err) { + if(err){ ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); return; } - if (!results) { + if(!results){ ESP_LOGW(TAG, "No results found!"); return; } @@ -130,7 +129,7 @@ static void query_mdns_service(const char *service_name, const char *proto) mdns_query_results_free(results); } -static void query_mdns_host(const char *host_name) +static void query_mdns_host(const char * host_name) { ESP_LOGI(TAG, "Query A: %s.local", host_name); @@ -138,8 +137,8 @@ static void query_mdns_host(const char *host_name) addr.addr = 0; esp_err_t err = mdns_query_a(host_name, 2000, &addr); - if (err) { - if (err == ESP_ERR_NOT_FOUND) { + if(err){ + if(err == ESP_ERR_NOT_FOUND){ ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err)); return; } @@ -193,7 +192,7 @@ static void mdns_example_task(void *pvParameters) check_button(); vTaskDelay(50 / portTICK_PERIOD_MS); if (pdTICKS_TO_MS(xTaskGetTickCount()) >= 15 * 1000 && ! removed) { - printf("Remove device\n"); + ESP_LOGI(TAG, "Remove delegate device\n"); ESP_ERROR_CHECK(mdns_delegate_hostname_remove("test-device")); removed = true; } @@ -221,7 +220,7 @@ void app_main(void) /** Generate host name based on sdkconfig, optionally adding a portion of MAC address to it. * @return host name string allocated from the heap */ -static char *generate_hostname(void) +static char* generate_hostname(void) { #ifndef CONFIG_MDNS_ADD_MAC_TO_HOSTNAME return strdup(CONFIG_MDNS_HOSTNAME); @@ -241,7 +240,7 @@ static char *generate_hostname(void) * @brief Executes gethostbyname and displays list of resolved addresses. * Note: This function is used only to test advertised mdns hostnames resolution */ -static void query_mdns_host_with_gethostbyname(char *host) +static void query_mdns_host_with_gethostbyname(char * host) { struct hostent *res = gethostbyname(host); if (res) { @@ -257,10 +256,10 @@ static void query_mdns_host_with_gethostbyname(char *host) * @brief Executes getaddrinfo and displays list of resolved addresses. * Note: This function is used only to test advertised mdns hostnames resolution */ -static void query_mdns_host_with_getaddrinfo(char *host) +static void query_mdns_host_with_getaddrinfo(char * host) { struct addrinfo hints; - struct addrinfo *res; + struct addrinfo * res; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -269,8 +268,8 @@ static void query_mdns_host_with_getaddrinfo(char *host) if (!getaddrinfo(host, NULL, &hints, &res)) { while (res) { ESP_LOGI(TAG, "getaddrinfo: %s resolved to: %s", host, - res->ai_family == AF_INET ? - inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr) : + res->ai_family == AF_INET? + inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr): inet_ntoa(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr)); res = res->ai_next; } From 418fb60dd926f1c8dd3ea1df9aa7086ff5277130 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Thu, 15 Apr 2021 20:03:53 +0800 Subject: [PATCH 188/289] mdns: fix mdns probe/reply behavior * send correct hostnames when probing. * add test for mdns host delegation. * Original commit: espressif/esp-idf@d2a5d25984432d149ca31aea4a0d177f3509dd7b --- components/mdns/mdns.c | 91 +++++++++++-------- examples/protocols/mdns/README.md | 1 + .../protocols/mdns/main/Kconfig.projbuild | 6 ++ .../protocols/mdns/main/mdns_example_main.c | 21 +++-- examples/protocols/mdns/mdns_example_test.py | 8 ++ 5 files changed, 80 insertions(+), 47 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index e72dce5ae..305ba734f 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -45,6 +45,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static bool _mdns_append_host_list_in_services(mdns_out_answer_t ** destination, mdns_srv_item_t * services[], size_t services_len, bool flush, bool bye); static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye); /* @@ -1499,26 +1500,43 @@ static bool _mdns_question_exists(mdns_out_question_t * needle, mdns_out_questio return false; } -bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye) +static bool _mdns_append_host(mdns_out_answer_t ** destination, mdns_host_item_t * host, bool flush, bool bye) +{ + if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { + return false; + } + if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { + return false; + } + return true; +} + +static bool _mdns_append_host_list_in_services(mdns_out_answer_t ** destination, mdns_srv_item_t * services[], + size_t services_len, bool flush, bool bye) +{ + for (size_t i = 0; i < services_len; i++) { + mdns_host_item_t *host = mdns_get_host_item(services[i]->service->hostname); + if (!_mdns_append_host(destination, host, flush, bye)) { + return false; + } + } + return true; +} + +static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye) { if (!_str_null_or_empty(_mdns_server->hostname)) { mdns_host_item_t * self_host = mdns_get_host_item(_mdns_server->hostname); - if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, self_host, flush, bye)) { - return false; - } - if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, self_host, flush, bye)) { + if (!_mdns_append_host(destination, self_host, flush, bye)) { return false; } } mdns_host_item_t * host = _mdns_host_list; while (host != NULL) { - if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { - return false; - } - if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { - return false; - } host = host->next; + if (!_mdns_append_host(destination, host, flush, bye)) { + return false; + } } return true; } @@ -1563,27 +1581,29 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_ } if (include_ip) { - mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); - if (!q) { - HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); - return NULL; - } - q->next = NULL; - q->unicast = first; - q->type = MDNS_TYPE_ANY; - q->host = _mdns_server->hostname; - q->service = NULL; - q->proto = NULL; - q->domain = MDNS_DEFAULT_DOMAIN; - q->own_dynamic_memory = false; - if (_mdns_question_exists(q, packet->questions)) { - free(q); - } else { - queueToEnd(mdns_out_question_t, packet->questions, q); + for (i = 0; i < len; i++) { + mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); + if (!q) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return NULL; + } + q->next = NULL; + q->unicast = first; + q->type = MDNS_TYPE_ANY; + q->host = services[i]->service->hostname; + q->service = NULL; + q->proto = NULL; + q->domain = MDNS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; + if (_mdns_question_exists(q, packet->questions)) { + free(q); + } else { + queueToEnd(mdns_out_question_t, packet->questions, q); + } } - if (!_mdns_append_host_list(&packet->servers, false, false)) { + if (!_mdns_append_host_list_in_services(&packet->servers, services, len, false, false)) { _mdns_free_tx_packet(packet); return NULL; } @@ -1614,7 +1634,7 @@ static mdns_tx_packet_t * _mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ } } if (include_ip) { - if (!_mdns_append_host_list(&packet->servers, true, false)) { + if (!_mdns_append_host_list_in_services(&packet->servers, services, len, true, false)) { _mdns_free_tx_packet(packet); return NULL; } @@ -1675,7 +1695,7 @@ static void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco } } if (include_ip) { - _mdns_append_host_list(&packet->answers, true, true); + _mdns_append_host_list_in_services(&packet->answers, services, len, true, true); } _mdns_dispatch_tx_packet(packet); _mdns_free_tx_packet(packet); @@ -1841,7 +1861,7 @@ static void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco if (include_ip) { _mdns_dealloc_answer(&p->additional, MDNS_TYPE_A, NULL); _mdns_dealloc_answer(&p->additional, MDNS_TYPE_AAAA, NULL); - _mdns_append_host_list(&p->answers, true, false); + _mdns_append_host_list_in_services(&p->answers, services, len, true, false); } _pcb->state = PCB_ANNOUNCE_1; } @@ -2231,9 +2251,7 @@ static void _mdns_free_service(mdns_service_t * service) free((char *)service->instance); free((char *)service->service); free((char *)service->proto); - if (service->hostname) { - free((char *)service->hostname); - } + free((char *)service->hostname); while (service->txt) { mdns_txt_linked_item_t * s = service->txt; service->txt = service->txt->next; @@ -2552,7 +2570,6 @@ static bool _mdns_delegate_hostname_remove(const char * hostname) } else { prev_host->next = host->next; } - printf("Free host %p\n", host); free_address_list(host->address_list); free((char *)host->hostname); free(host); diff --git a/examples/protocols/mdns/README.md b/examples/protocols/mdns/README.md index 2b99f2d4c..e6644d5e5 100644 --- a/examples/protocols/mdns/README.md +++ b/examples/protocols/mdns/README.md @@ -5,6 +5,7 @@ Shows how to use mDNS to advertise lookup services and hosts ## Example workflow - mDNS is initialized with host name and instance name defined through the project configuration and `_http._tcp` service is added to be advertised +- A delegated host `esp32-delegated._local` is added and another `_http._tcp` service is added for this host. - WiFi STA is started and trying to connect to the access point defined through the project configuration - The system event handler is used to pass the network events to mDNS so the service is aware when the interface comes up or down - GPIO0 (BOOT Button) is initialized as pulled-up input that can be monitored for button press diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index c4ae7e13b..ca2f2bbf3 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -12,6 +12,12 @@ menu "Example Configuration" help mDNS Instance Name for example to use + config MDNS_PUBLISH_DELEGATE_HOST + bool "Publish a delegated host" + help + Enable publishing a delegated host other than ESP32. + The example will also add a mock service for this host. + config MDNS_RESOLVE_TEST_SERVICES bool "Resolve test services" default n diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index ecdb47e4e..244ac4156 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -34,6 +34,9 @@ static void query_mdns_host_with_getaddrinfo(char * host); static void initialise_mdns(void) { char *hostname = generate_hostname(); + char delegated_hostname[64]; + + snprintf(delegated_hostname, sizeof(delegated_hostname), "%s-delegated", hostname); //initialize mDNS ESP_ERROR_CHECK( mdns_init() ); //set mDNS hostname (required if you want to advertise services) @@ -51,19 +54,23 @@ static void initialise_mdns(void) //initialize service ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) ); + +#if CONFIG_MDNS_PUBLISH_DELEGATE_HOST mdns_ip_addr_t addr4, addr6; ip4_addr_t ip4_addr; ip6_addr_t ip6_addr; - ip4addr_aton("10.0.0.1", &ip4_addr); + ip4addr_aton("10.0.0.1", &ip4_addr); // mock address addr4.addr.u_addr.ip4.addr = ip4_addr.addr; addr4.addr.type = ESP_IPADDR_TYPE_V4; addr4.next = &addr6; - ip6addr_aton("fd11:22::1", &ip6_addr); + ip6addr_aton("fd11:22::1", &ip6_addr); // mock address memcpy(addr6.addr.u_addr.ip6.addr, ip6_addr.addr, sizeof(ip6_addr.addr)); addr6.addr.type = ESP_IPADDR_TYPE_V6; addr6.next = NULL; - ESP_ERROR_CHECK( mdns_delegate_hostname_add("test-device", &addr4) ); - ESP_ERROR_CHECK( mdns_service_add_for_host("test0", "_http", "_tcp", "test-device", 1234, serviceTxtData, 3) ); + ESP_ERROR_CHECK( mdns_delegate_hostname_add(delegated_hostname, &addr4) ); + ESP_ERROR_CHECK( mdns_service_add_for_host("test0", "_http", "_tcp", delegated_hostname, 1234, serviceTxtData, 3) ); +#endif // CONFIG_MDNS_PUBLISH_DELEGATE_HOST + //add another TXT item ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") ); //change TXT item value @@ -186,16 +193,10 @@ static void mdns_example_task(void *pvParameters) query_mdns_host_with_gethostbyname("tinytester-lwip.local"); query_mdns_host_with_getaddrinfo("tinytester-lwip.local"); #endif - bool removed = false; while (1) { check_button(); vTaskDelay(50 / portTICK_PERIOD_MS); - if (pdTICKS_TO_MS(xTaskGetTickCount()) >= 15 * 1000 && ! removed) { - ESP_LOGI(TAG, "Remove delegate device\n"); - ESP_ERROR_CHECK(mdns_delegate_hostname_remove("test-device")); - removed = true; - } } } diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index 201acb569..26295d6a7 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -13,6 +13,7 @@ from tiny_test_fw import DUT stop_mdns_server = Event() esp_answered = Event() +esp_delegated_answered = Event() def get_dns_query_for_esp(esp_host): @@ -68,6 +69,8 @@ def mdns_server(esp_host): if not esp_answered.is_set(): sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT)) time.sleep(0.2) + sock.sendto(get_dns_query_for_esp(esp_host + '-delegated'), (MCAST_GRP,UDP_PORT)) + time.sleep(0.2) data, addr = sock.recvfrom(1024) dns = dpkt.dns.DNS(data) if len(dns.qd) > 0 and dns.qd[0].type == dpkt.dns.DNS_A: @@ -81,6 +84,9 @@ def mdns_server(esp_host): if dns.an[0].name == esp_host + u'.local': print('Received answer to esp32-mdns query: {}'.format(dns.__repr__())) esp_answered.set() + if dns.an[0].name == esp_host + u'-delegated.local': + print('Received answer to esp32-mdns-delegate query: {}'.format(dns.__repr__())) + esp_delegated_answered.set() except socket.timeout: break except dpkt.UnpackError: @@ -120,6 +126,8 @@ def test_examples_protocol_mdns(env, extra_data): # 3. check the mdns name is accessible if not esp_answered.wait(timeout=30): raise ValueError('Test has failed: did not receive mdns answer within timeout') + if not esp_delegated_answered.wait(timeout=30): + raise ValueError('Test has failed: did not receive mdns answer for delegated host within timeout') # 4. check DUT output if mdns advertized host is resolved dut1.expect(re.compile(r'mdns-test: Query A: tinytester.local resolved to: 127.0.0.1'), timeout=30) dut1.expect(re.compile(r'mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1'), timeout=30) From 121b525108ee8fdeafadd27fbfd517f68fdc0df0 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Wed, 21 Apr 2021 16:15:51 +0800 Subject: [PATCH 189/289] mdns: fix empty address change announce packets * Original commit: espressif/esp-idf@7bbb72d86540f04d37b0e2c4efb6dc66ee9c9ea0 --- components/mdns/mdns.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 305ba734f..0558e9a0c 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1612,6 +1612,23 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_ return packet; } +/** + * @brief Create announce packet for self IP addresses + */ +static mdns_tx_packet_t * _mdns_create_announce_self_ip(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t * packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return NULL; + } + mdns_host_item_t * host = mdns_get_host_item(_mdns_server->hostname); + if (!_mdns_append_host(&packet->servers, host, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + return packet; +} + /** * @brief Create announce packet for particular services on particular PCB */ @@ -1872,7 +1889,12 @@ static void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco } _pcb->state = PCB_ANNOUNCE_1; - mdns_tx_packet_t * p = _mdns_create_announce_packet(tcpip_if, ip_protocol, services, len, include_ip); + mdns_tx_packet_t * p = NULL; + if (services != NULL) { + p = _mdns_create_announce_packet(tcpip_if, ip_protocol, services, len, include_ip); + } else { + p = _mdns_create_announce_self_ip(tcpip_if, ip_protocol); + } if (p) { _mdns_schedule_tx_packet(p, 0); } From 9fa25ef3b6272d7d7a620b34570bf8954f032f3e Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Fri, 30 Apr 2021 17:22:14 +0800 Subject: [PATCH 190/289] mdns: fix wrong service hostname after mangling * Original commit: espressif/esp-idf@439b31d065eddfdfb6eb4cf9c00454edfebc3d9b --- components/mdns/mdns.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 0558e9a0c..e96d971bd 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -47,6 +47,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static bool _mdns_append_host_list_in_services(mdns_out_answer_t ** destination, mdns_srv_item_t * services[], size_t services_len, bool flush, bool bye); static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye); +static void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); /* * @brief Internal collection of mdns supported interfaces @@ -3227,8 +3228,10 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } else { char * new_host = _mdns_mangle_name((char *)_mdns_server->hostname); if (new_host) { + _mdns_remap_self_service_hostname(_mdns_server->hostname, new_host); free((char *)_mdns_server->hostname); _mdns_server->hostname = new_host; + _mdns_self_host.hostname = new_host; } _mdns_restart_all_pcbs(); } @@ -3333,8 +3336,10 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; char * new_host = _mdns_mangle_name((char *)_mdns_server->hostname); if (new_host) { + _mdns_remap_self_service_hostname(_mdns_server->hostname, new_host); free((char *)_mdns_server->hostname); _mdns_server->hostname = new_host; + _mdns_self_host.hostname = new_host; } _mdns_restart_all_pcbs(); } @@ -3381,8 +3386,10 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; char * new_host = _mdns_mangle_name((char *)_mdns_server->hostname); if (new_host) { + _mdns_remap_self_service_hostname(_mdns_server->hostname, new_host); free((char *)_mdns_server->hostname); _mdns_server->hostname = new_host; + _mdns_self_host.hostname = new_host; } _mdns_restart_all_pcbs(); } @@ -4087,6 +4094,19 @@ static void _mdns_tx_handle_packet(mdns_tx_packet_t * p) } } +static void _mdns_remap_self_service_hostname(const char * old_hostname, const char * new_hostname) +{ + mdns_srv_item_t * service = _mdns_server->services; + + while (service) { + if (strcmp(service->service->hostname, old_hostname) == 0) { + free((char *)service->service->hostname); + service->service->hostname = strdup(new_hostname); + } + service = service->next; + } +} + /** * @brief Free action data */ @@ -4154,6 +4174,7 @@ static void _mdns_execute_action(mdns_action_t * action) break; case ACTION_HOSTNAME_SET: _mdns_send_bye_all_pcbs_no_instance(true); + _mdns_remap_self_service_hostname(_mdns_server->hostname, action->data.hostname_set.hostname); free((char*)_mdns_server->hostname); _mdns_server->hostname = action->data.hostname_set.hostname; _mdns_self_host.hostname = action->data.hostname_set.hostname; From 402baebfee7f023913e98db91c4a086337fd9b7d Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Thu, 6 May 2021 16:03:42 +0800 Subject: [PATCH 191/289] mdns: fix wrong SRV/PTR record handling * Original commit: espressif/esp-idf@e6135552d26480e39e11632437020535b1667b7a --- components/mdns/mdns.c | 100 ++++++++++-------- .../mdns/private_include/mdns_private.h | 2 +- examples/protocols/mdns/sdkconfig.ci | 1 + 3 files changed, 55 insertions(+), 48 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index e96d971bd..0bb56ecd6 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1418,7 +1418,7 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_ if (q->service && q->proto) { mdns_srv_item_t *service = _mdns_server->services; while (service) { - if (_mdns_service_match(service->service, q->service, q->proto, q->host)) { + if (_mdns_service_match(service->service, q->service, q->proto, NULL)) { if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { _mdns_free_tx_packet(packet); return; @@ -1515,6 +1515,13 @@ static bool _mdns_append_host(mdns_out_answer_t ** destination, mdns_host_item_t static bool _mdns_append_host_list_in_services(mdns_out_answer_t ** destination, mdns_srv_item_t * services[], size_t services_len, bool flush, bool bye) { + if (services == NULL) { + mdns_host_item_t * host = mdns_get_host_item(_mdns_server->hostname); + if (host != NULL) { + return _mdns_append_host(destination, host, flush, bye); + } + return true; + } for (size_t i = 0; i < services_len; i++) { mdns_host_item_t *host = mdns_get_host_item(services[i]->service->hostname); if (!_mdns_append_host(destination, host, flush, bye)) { @@ -1542,6 +1549,44 @@ static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, return true; } +static bool _mdns_append_host_question(mdns_out_question_t **questions, const char *hostname, bool unicast) +{ + mdns_out_question_t *q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); + if (!q) { + HOOK_MALLOC_FAILED; + return false; + } + q->next = NULL; + q->unicast = unicast; + q->type = MDNS_TYPE_ANY; + q->host = hostname; + q->service = NULL; + q->proto = NULL; + q->domain = MDNS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; + if (_mdns_question_exists(q, *questions)) { + free(q); + } else { + queueToEnd(mdns_out_question_t, *questions, q); + } + return true; +} + +static bool _mdns_append_host_questions_for_services(mdns_out_question_t **questions, mdns_srv_item_t *services[], + size_t len, bool unicast) +{ + if (!_str_null_or_empty(_mdns_server->hostname) && + !_mdns_append_host_question(questions, _mdns_server->hostname, unicast)) { + return false; + } + for (size_t i = 0; i < len; i++) { + if (!_mdns_append_host_question(questions, services[i]->service->hostname, unicast)) { + return false; + } + } + return true; +} + /** * @brief Create probe packet for particular services on particular PCB */ @@ -1582,26 +1627,9 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_ } if (include_ip) { - for (i = 0; i < len; i++) { - mdns_out_question_t * q = (mdns_out_question_t *)malloc(sizeof(mdns_out_question_t)); - if (!q) { - HOOK_MALLOC_FAILED; - _mdns_free_tx_packet(packet); - return NULL; - } - q->next = NULL; - q->unicast = first; - q->type = MDNS_TYPE_ANY; - q->host = services[i]->service->hostname; - q->service = NULL; - q->proto = NULL; - q->domain = MDNS_DEFAULT_DOMAIN; - q->own_dynamic_memory = false; - if (_mdns_question_exists(q, packet->questions)) { - free(q); - } else { - queueToEnd(mdns_out_question_t, packet->questions, q); - } + if (!_mdns_append_host_questions_for_services(&packet->questions, services, len, first)) { + _mdns_free_tx_packet(packet); + return NULL; } if (!_mdns_append_host_list_in_services(&packet->servers, services, len, false, false)) { @@ -1613,23 +1641,6 @@ static mdns_tx_packet_t * _mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_ return packet; } -/** - * @brief Create announce packet for self IP addresses - */ -static mdns_tx_packet_t * _mdns_create_announce_self_ip(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_tx_packet_t * packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); - if (!packet) { - return NULL; - } - mdns_host_item_t * host = mdns_get_host_item(_mdns_server->hostname); - if (!_mdns_append_host(&packet->servers, host, true, false)) { - _mdns_free_tx_packet(packet); - return NULL; - } - return packet; -} - /** * @brief Create announce packet for particular services on particular PCB */ @@ -1890,12 +1901,7 @@ static void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco } _pcb->state = PCB_ANNOUNCE_1; - mdns_tx_packet_t * p = NULL; - if (services != NULL) { - p = _mdns_create_announce_packet(tcpip_if, ip_protocol, services, len, include_ip); - } else { - p = _mdns_create_announce_self_ip(tcpip_if, ip_protocol); - } + mdns_tx_packet_t * p = _mdns_create_announce_packet(tcpip_if, ip_protocol, services, len, include_ip); if (p) { _mdns_schedule_tx_packet(p, 0); } @@ -2646,7 +2652,7 @@ static bool _mdns_name_is_ours(mdns_name_t * name) } //find the service - mdns_srv_item_t * service = _mdns_get_service_item(name->service, name->proto, name->host); + mdns_srv_item_t * service = _mdns_get_service_item(name->service, name->proto, NULL); if (!service) { return false; } @@ -3124,7 +3130,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } else if (!name->sub && _mdns_name_is_ours(name)) { ours = true; if (name->service && name->service[0] && name->proto && name->proto[0]) { - service = _mdns_get_service_item(name->service, name->proto, name->host); + service = _mdns_get_service_item(name->service, name->proto, NULL); } } else { if (!parsed_packet->authoritative || record_type == MDNS_NS) { @@ -3142,7 +3148,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) _mdns_search_result_add_ptr(search_result, name->host, packet->tcpip_if, packet->ip_protocol); } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { if (discovery) { - service = _mdns_get_service_item(name->service, name->proto, name->host); + service = _mdns_get_service_item(name->service, name->proto, NULL); _mdns_remove_parsed_question(parsed_packet, MDNS_TYPE_SDPTR, service); } else if (parsed_packet->questions && !parsed_packet->probe) { _mdns_remove_parsed_question(parsed_packet, type, service); diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 4b8f8806c..3851c4694 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -215,7 +215,7 @@ typedef struct { } mdns_header_t; typedef struct { - char host[MDNS_NAME_BUF_LEN]; + char host[MDNS_NAME_BUF_LEN]; // hostname for A/AAAA records, instance name for SRV records char service[MDNS_NAME_BUF_LEN]; char proto[MDNS_NAME_BUF_LEN]; char domain[MDNS_NAME_BUF_LEN]; diff --git a/examples/protocols/mdns/sdkconfig.ci b/examples/protocols/mdns/sdkconfig.ci index 42c55b8c0..0587c0624 100644 --- a/examples/protocols/mdns/sdkconfig.ci +++ b/examples/protocols/mdns/sdkconfig.ci @@ -1,3 +1,4 @@ CONFIG_MDNS_RESOLVE_TEST_SERVICES=y CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y From 8a8d58d4dcbc5f9d13865bed03e4992adbd9eca6 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Tue, 11 May 2021 13:47:03 +0800 Subject: [PATCH 192/289] mdns: fix test script delayed response * Original commit: espressif/esp-idf@a4f263948c35c13340b6f4b59a649c5073787d5e --- components/mdns/mdns.c | 40 ++++++++----------- .../protocols/mdns/main/mdns_example_main.c | 21 +++++----- examples/protocols/mdns/mdns_example_test.py | 32 +++++++++------ 3 files changed, 48 insertions(+), 45 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 0bb56ecd6..fe2c2f85f 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -160,6 +160,7 @@ static bool _mdns_service_match(const mdns_service_t * srv, const char * service * @param server the server * @param service service type to match * @param proto proto to match + * @param hostname hostname of the service (if non-null) * * @return the service item if found or NULL on error */ @@ -177,7 +178,7 @@ static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char static mdns_host_item_t * mdns_get_host_item(const char * hostname) { - if (hostname == NULL || strcasecmp(hostname, _mdns_server->hostname) == 0) { + if (strcasecmp(hostname, _mdns_server->hostname) == 0) { return &_mdns_self_host; } mdns_host_item_t * host = _mdns_host_list; @@ -1122,22 +1123,14 @@ static void _mdns_free_tx_packet(mdns_tx_packet_t * packet) if (!packet) { return; } - mdns_out_question_t *q = packet->questions; + mdns_out_question_t * q = packet->questions; while (q) { - mdns_out_question_t *next = q->next; + mdns_out_question_t * next = q->next; if (q->own_dynamic_memory) { - if (q->host) { - free((char *)q->host); - } - if (q->service) { - free((char *)q->service); - } - if (q->proto) { - free((char *)q->proto); - } - if (q->domain) { - free((char *)q->domain); - } + free((char *)q->host); + free((char *)q->service); + free((char *)q->proto); + free((char *)q->domain); } free(q); q = next; @@ -4870,7 +4863,8 @@ esp_err_t mdns_instance_name_set(const char * instance) esp_err_t mdns_service_add_for_host(const char * instance, const char * service, const char * proto, const char * hostname, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { + if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(hostname) || + !port) { return ESP_ERR_INVALID_ARG; } @@ -4930,7 +4924,7 @@ esp_err_t mdns_service_add_for_host(const char * instance, const char * service, esp_err_t mdns_service_add(const char * instance, const char * service, const char * proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!_mdns_server) { + if (!_mdns_server || _str_null_or_empty(_mdns_server->hostname)) { return ESP_ERR_INVALID_STATE; } return mdns_service_add_for_host(instance, service, proto, _mdns_server->hostname, port, txt, num_items); @@ -5405,7 +5399,7 @@ void mdns_debug_packet(const uint8_t * data, size_t len) header.answers = 0; header.additional = 0; header.servers = 0; - _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + _mdns_dbg_printf("ERROR: parse header questions\n"); break; } @@ -5453,7 +5447,7 @@ void mdns_debug_packet(const uint8_t * data, size_t len) content = _mdns_parse_fqdn(data, content, name); if (!content) { - _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + _mdns_dbg_printf("ERROR: parse mdns records\n"); break; } @@ -5467,7 +5461,7 @@ void mdns_debug_packet(const uint8_t * data, size_t len) content = data_ptr + data_len; if (content > (data + len)) { - _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + _mdns_dbg_printf("ERROR: content length overflow\n"); break; } @@ -5520,13 +5514,13 @@ void mdns_debug_packet(const uint8_t * data, size_t len) _mdns_dbg_printf("[%u] ", data_len); if (type == MDNS_TYPE_PTR) { if (!_mdns_parse_fqdn(data, data_ptr, name)) { - _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + _mdns_dbg_printf("ERROR: parse PTR\n"); continue; } _mdns_dbg_printf("%s.%s.%s.%s.\n", name->host, name->service, name->proto, name->domain); } else if (type == MDNS_TYPE_SRV) { if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name)) { - _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + _mdns_dbg_printf("ERROR: parse SRV\n"); continue; } uint16_t priority = _mdns_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); @@ -5538,7 +5532,7 @@ void mdns_debug_packet(const uint8_t * data, size_t len) while (i < data_len) { uint8_t partLen = data_ptr[i++]; if ((i+partLen) > data_len) { - _mdns_dbg_printf("ERROR: %s:%u\n", __FILE__, __LINE__); + _mdns_dbg_printf("ERROR: parse TXT\n"); break; } char txt[partLen+1]; diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 244ac4156..f8641197b 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -9,6 +9,7 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "esp_netif_ip_addr.h" #include "esp_system.h" #include "esp_event.h" #include "esp_log.h" @@ -33,10 +34,8 @@ static void query_mdns_host_with_getaddrinfo(char * host); static void initialise_mdns(void) { - char *hostname = generate_hostname(); - char delegated_hostname[64]; + char * hostname = generate_hostname(); - snprintf(delegated_hostname, sizeof(delegated_hostname), "%s-delegated", hostname); //initialize mDNS ESP_ERROR_CHECK( mdns_init() ); //set mDNS hostname (required if you want to advertise services) @@ -56,19 +55,21 @@ static void initialise_mdns(void) ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) ); #if CONFIG_MDNS_PUBLISH_DELEGATE_HOST + char *delegated_hostname; + if (-1 == asprintf(&delegated_hostname, "%s-delegated", hostname)) { + abort(); + } + mdns_ip_addr_t addr4, addr6; - ip4_addr_t ip4_addr; - ip6_addr_t ip6_addr; - ip4addr_aton("10.0.0.1", &ip4_addr); // mock address - addr4.addr.u_addr.ip4.addr = ip4_addr.addr; + esp_netif_str_to_ip4("10.0.0.1", &addr4.addr.u_addr.ip4); addr4.addr.type = ESP_IPADDR_TYPE_V4; - addr4.next = &addr6; - ip6addr_aton("fd11:22::1", &ip6_addr); // mock address - memcpy(addr6.addr.u_addr.ip6.addr, ip6_addr.addr, sizeof(ip6_addr.addr)); + esp_netif_str_to_ip6("fd11:22::1", &addr6.addr.u_addr.ip6); addr6.addr.type = ESP_IPADDR_TYPE_V6; + addr4.next = &addr6; addr6.next = NULL; ESP_ERROR_CHECK( mdns_delegate_hostname_add(delegated_hostname, &addr4) ); ESP_ERROR_CHECK( mdns_service_add_for_host("test0", "_http", "_tcp", delegated_hostname, 1234, serviceTxtData, 3) ); + free(delegated_hostname); #endif // CONFIG_MDNS_PUBLISH_DELEGATE_HOST //add another TXT item diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index 26295d6a7..5bbae2111 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -1,5 +1,6 @@ import os import re +import select import socket import struct import subprocess @@ -10,6 +11,7 @@ import dpkt import dpkt.dns import ttfw_idf from tiny_test_fw import DUT +from tiny_test_fw.Utility import console_log stop_mdns_server = Event() esp_answered = Event() @@ -19,7 +21,7 @@ esp_delegated_answered = Event() def get_dns_query_for_esp(esp_host): dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') dns.qd[0].name = esp_host + u'.local' - print('Created query for esp host: {} '.format(dns.__repr__())) + console_log('Created query for esp host: {} '.format(dns.__repr__())) return dns.pack() @@ -33,7 +35,7 @@ def get_dns_answer_to_mdns(tester_host): arr.name = tester_host arr.ip = socket.inet_aton('127.0.0.1') dns. an.append(arr) - print('Created answer to mdns query: {} '.format(dns.__repr__())) + console_log('Created answer to mdns query: {} '.format(dns.__repr__())) return dns.pack() @@ -57,35 +59,41 @@ def mdns_server(esp_host): MCAST_GRP = '224.0.0.251' TESTER_NAME = u'tinytester.local' TESTER_NAME_LWIP = u'tinytester-lwip.local' + QUERY_TIMEOUT = 0.2 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + sock.setblocking(False) sock.bind((UDP_IP,UDP_PORT)) mreq = struct.pack('4sl', socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) - sock.settimeout(30) + last_query_timepoint = time.time() while not stop_mdns_server.is_set(): try: - if not esp_answered.is_set(): + current_time = time.time() + if not esp_answered.is_set() and current_time - last_query_timepoint > QUERY_TIMEOUT: sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT)) - time.sleep(0.2) sock.sendto(get_dns_query_for_esp(esp_host + '-delegated'), (MCAST_GRP,UDP_PORT)) - time.sleep(0.2) + last_query_timepoint = current_time + timeout = max(0, QUERY_TIMEOUT - (current_time - last_query_timepoint)) + read_socks, _, _ = select.select([sock], [], [], timeout) + if not read_socks: + continue data, addr = sock.recvfrom(1024) dns = dpkt.dns.DNS(data) if len(dns.qd) > 0 and dns.qd[0].type == dpkt.dns.DNS_A: if dns.qd[0].name == TESTER_NAME: - print('Received query: {} '.format(dns.__repr__())) + console_log('Received query: {} '.format(dns.__repr__())) sock.sendto(get_dns_answer_to_mdns(TESTER_NAME), (MCAST_GRP,UDP_PORT)) elif dns.qd[0].name == TESTER_NAME_LWIP: - print('Received query: {} '.format(dns.__repr__())) + console_log('Received query: {} '.format(dns.__repr__())) sock.sendto(get_dns_answer_to_mdns_lwip(TESTER_NAME_LWIP, dns.id), addr) if len(dns.an) > 0 and dns.an[0].type == dpkt.dns.DNS_A: if dns.an[0].name == esp_host + u'.local': - print('Received answer to esp32-mdns query: {}'.format(dns.__repr__())) + console_log('Received answer to esp32-mdns query: {}'.format(dns.__repr__())) esp_answered.set() if dns.an[0].name == esp_host + u'-delegated.local': - print('Received answer to esp32-mdns-delegate query: {}'.format(dns.__repr__())) + console_log('Received answer to esp32-mdns-delegate query: {}'.format(dns.__repr__())) esp_delegated_answered.set() except socket.timeout: break @@ -117,7 +125,7 @@ def test_examples_protocol_mdns(env, extra_data): thread1.start() try: ip_address = dut1.expect(re.compile(r' sta ip: ([^,]+),'), timeout=30)[0] - print('Connected to AP with IP: {}'.format(ip_address)) + console_log('Connected to AP with IP: {}'.format(ip_address)) except DUT.ExpectTimeout: stop_mdns_server.set() thread1.join() @@ -135,7 +143,7 @@ def test_examples_protocol_mdns(env, extra_data): # 5. check the DUT answers to `dig` command dig_output = subprocess.check_output(['dig', '+short', '-p', '5353', '@224.0.0.251', '{}.local'.format(specific_host)]) - print('Resolving {} using "dig" succeeded with:\n{}'.format(specific_host, dig_output)) + console_log('Resolving {} using "dig" succeeded with:\n{}'.format(specific_host, dig_output)) if not ip_address.encode('utf-8') in dig_output: raise ValueError('Test has failed: Incorrectly resolved DUT hostname using dig' "Output should've contained DUT's IP address:{}".format(ip_address)) From bc4cda8ea72d655d8c4487fb59e50cf0ad4b8ef8 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 8 Jun 2021 13:27:15 +0200 Subject: [PATCH 193/289] mdns: Fix fuzzer from miss-interpreting adding services as timeouts * Original commit: espressif/esp-idf@14099fe15efb1b0cde0a8370096c55bba62ff937 --- components/mdns/test_afl_fuzz_host/esp32_mock.c | 8 ++------ components/mdns/test_afl_fuzz_host/sdkconfig.h | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.c b/components/mdns/test_afl_fuzz_host/esp32_mock.c index 0a01514ff..d806093fc 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.c +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.c @@ -48,12 +48,8 @@ esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, uint32_t xTaskGetTickCount(void) { - struct timeval tv; - struct timezone tz; - if (gettimeofday(&tv, &tz) == 0) { - return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - } - return 0; + static uint32_t tick = 0; + return tick++; } /// Queue mock diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index 43d4a278a..1b5997b64 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -294,7 +294,7 @@ #define CONFIG_MDNS_TASK_STACK_SIZE 4096 #define CONFIG_MDNS_TASK_AFFINITY_CPU0 1 #define CONFIG_MDNS_TASK_AFFINITY 0x0 -#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 100 +#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 1 #define CONFIG_MDNS_TIMER_PERIOD_MS 100 #define CONFIG_MQTT_PROTOCOL_311 1 #define CONFIG_MQTT_TRANSPORT_SSL 1 From 93e6efedc7dac339ee90494cf121f65cb2c4e405 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 9 Jun 2021 09:58:58 +0200 Subject: [PATCH 194/289] mdns: Minor correction of the test code * Original commit: espressif/esp-idf@7d762451731cb305c3b090509827740f0195a496 --- components/mdns/test_afl_fuzz_host/test.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/test.c b/components/mdns/test_afl_fuzz_host/test.c index 0c123f6fa..776a089cd 100644 --- a/components/mdns/test_afl_fuzz_host/test.c +++ b/components/mdns/test_afl_fuzz_host/test.c @@ -204,9 +204,7 @@ int main(int argc, char** argv) // // Note: parameter1 is a file (mangled packet) which caused the crash file = fopen(argv[1], "r"); - if (file) { - len = fread(buf, 1, 1460, file); - } + assert(file >= 0 ); fclose(file); } From 27fc2850005fd5fe91f713869188a79532256e33 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 9 Jun 2021 09:59:25 +0200 Subject: [PATCH 195/289] mdns: Fix crashes reported by the fuzzer * Original commit: espressif/esp-idf@79ba738626d643d8c6f32bdcd455e0d2476f94c7 --- components/mdns/mdns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index fe2c2f85f..1858859ba 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2751,7 +2751,7 @@ static bool _mdns_question_matches(mdns_parsed_question_t * question, uint16_t t && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { return true; } - } else if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { + } else if (service && (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT)) { const char * name = _mdns_get_service_instance_name(service->service); if (name && question->host && !strcasecmp(name, question->host) && !strcasecmp(service->service->service, question->service) @@ -3292,7 +3292,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } 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) { + if (col && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running && service) { do_not_reply = true; _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); } else if (ttl > 2250 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { From 73b1763029ad2ba841363eb908f7d0f648a5b20f Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Wed, 9 Jun 2021 10:01:17 +0800 Subject: [PATCH 196/289] example: set example wifi scan method to all channel: in CI example test we could have runners with same SSID in the same lab. Use scan on all channel will let DUT connect to the AP with best RSSI. * Original commit: espressif/esp-idf@97a09e51ceaf4e0f6a953bc24727549b8072f518 --- .../protocol_examples_common/Kconfig.projbuild | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index afbdf08a2..cd4028d9d 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -23,7 +23,7 @@ menu "Example Connection Configuration" choice EXAMPLE_WIFI_SCAN_METHOD prompt "WiFi Scan Method" - default EXAMPLE_WIFI_SCAN_METHOD_FAST + default EXAMPLE_WIFI_SCAN_METHOD_ALL_CHANNEL help WiFi scan method: From 2ddaee2b6e44a12f75d9746cb641ff601376fcaf Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Tue, 15 Jun 2021 20:13:00 +0800 Subject: [PATCH 197/289] mdns: allow explicit txt value length * Original commit: espressif/esp-idf@b4e0088b68321acc4698b01faec7e2ffbe1e37c1 --- components/mdns/include/mdns.h | 51 +++++++- components/mdns/mdns.c | 109 +++++++++++++----- .../mdns/private_include/mdns_private.h | 4 +- .../protocols/mdns/main/mdns_example_main.c | 7 +- 4 files changed, 140 insertions(+), 31 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 416740d13..29c22b022 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -79,6 +79,7 @@ typedef struct mdns_result_s { uint16_t port; /*!< service port */ // TXT mdns_txt_item_t * txt; /*!< txt record */ + uint8_t *txt_value_len; /*!< array of txt value len of each record */ size_t txt_count; /*!< number of txt items */ // A and AAAA mdns_ip_addr_t * addr; /*!< linked list of IP addresses found */ @@ -173,6 +174,8 @@ esp_err_t mdns_instance_name_set(const char * instance_name); /** * @brief Add service to mDNS server * + * @note The value length of txt items will be automatically decided by strlen + * * @param instance_name instance name to set. If NULL, * global instance name or hostname will be used * @param service_type service type (_http, _ftp, etc) @@ -189,10 +192,11 @@ esp_err_t mdns_instance_name_set(const char * instance_name); */ 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); - /** * @brief Add service to mDNS server with a delegated hostname * + * @note The value length of txt items will be automatically decided by strlen + * * @param instance_name instance name to set. If NULL, * global instance name or hostname will be used * @param service_type service type (_http, _ftp, etc) @@ -321,6 +325,8 @@ esp_err_t mdns_service_port_set_for_host(const char * service_type, const char * /** * @brief Replace all TXT items for service * + * @note The value length of txt items will be automatically decided by strlen + * * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param txt array of TXT data (eg. {{"var","val"},{"other","2"}}) @@ -337,6 +343,8 @@ esp_err_t mdns_service_txt_set(const char * service_type, const char * proto, md /** * @brief Replace all TXT items for service with hostname * + * @note The value length of txt items will be automatically decided by strlen + * * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param hostname service hostname. If NULL, local hostname will be used. @@ -355,6 +363,8 @@ esp_err_t mdns_service_txt_set_for_host(const char * service_type, const char * /** * @brief Set/Add TXT item for service TXT record * + * @note The value length will be automatically decided by strlen + * * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param key the key that you want to add/update @@ -368,10 +378,29 @@ esp_err_t mdns_service_txt_set_for_host(const char * service_type, const char * */ esp_err_t mdns_service_txt_item_set(const char * service_type, const char * proto, const char * key, const char * value); +/** + * @brief Set/Add TXT item for service TXT record + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param key the key that you want to add/update + * @param value the new value of the key + * @param value_len the length of the value + * + * @return + * - 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_txt_item_set_with_explicit_value_len(const char *service_type, const char *proto, + const char *key, const char *value, uint8_t value_len); /** * @brief Set/Add TXT item for service TXT record with hostname * + * @note The value length will be automatically decided by strlen + * * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param hostname service hostname. If NULL, local hostname will be used. @@ -387,6 +416,26 @@ esp_err_t mdns_service_txt_item_set(const char * service_type, const char * prot esp_err_t mdns_service_txt_item_set_for_host(const char * service_type, const char * proto, const char * hostname, const char * key, const char * value); +/** + * @brief Set/Add TXT item for service TXT record with hostname and txt value length + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param key the key that you want to add/update + * @param value the new value of the key + * @param value_len the length of the value + * + * @return + * - 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_txt_item_set_for_host_with_explicit_value_len(const char *service_type, const char *proto, + const char *hostname, const char *key, + const char *value, uint8_t value_len); + /** * @brief Remove TXT item for service TXT record * diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 1858859ba..04396f257 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -43,7 +43,7 @@ static void _mdns_search_finish_done(void); static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * search, mdns_name_t * name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, esp_ip_addr_t * ip, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); static bool _mdns_append_host_list_in_services(mdns_out_answer_t ** destination, mdns_srv_item_t * services[], size_t services_len, bool flush, bool bye); static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye); @@ -418,6 +418,17 @@ static inline uint8_t _mdns_append_type(uint8_t * packet, uint16_t * index, uint return 10; } +static inline uint8_t _mdns_append_string_with_len(uint8_t * packet, uint16_t * index, const char * string, uint8_t len) +{ + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, string, len); + *index += len; + return len + 1; +} + /** * @brief appends single string to a packet, incrementing the index * @@ -656,10 +667,12 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns char * tmp; mdns_txt_linked_item_t * txt = service->txt; while (txt) { - tmp = (char *)malloc(2 + strlen(txt->key) + strlen(txt->value)); + uint8_t txt_data_len = strlen(txt->key) + txt->value_len + 1; + tmp = (char *)malloc(txt_data_len); if (tmp) { - sprintf(tmp, "%s=%s", txt->key, txt->value); - uint8_t l = _mdns_append_string(packet, index, tmp); + int offset = sprintf(tmp, "%s=", txt->key); + memcpy(tmp + offset, txt->value, txt->value_len); + uint8_t l = _mdns_append_string_with_len(packet, index, tmp, txt_data_len); free(tmp); if (!l) { return 0; @@ -2072,6 +2085,7 @@ static mdns_txt_linked_item_t * _mdns_allocate_txt(size_t num_items, mdns_txt_it free(new_item); break; } + new_item->value_len = strlen(new_item->value); new_item->next = new_txt; new_txt = new_item; } @@ -2842,7 +2856,8 @@ static int _mdns_txt_item_name_get_len(const uint8_t * data, size_t len) /** * @brief Create TXT result array from parsed TXT data */ -static void _mdns_result_txt_create(const uint8_t * data, size_t len, mdns_txt_item_t ** out_txt, size_t * out_count) +static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_item_t **out_txt, uint8_t **out_value_len, + size_t *out_count) { *out_txt = NULL; *out_count = 0; @@ -2862,7 +2877,14 @@ static void _mdns_result_txt_create(const uint8_t * data, size_t len, mdns_txt_i HOOK_MALLOC_FAILED; return; } + uint8_t * txt_value_len = (uint8_t *)malloc(num_items); + if (!txt_value_len) { + free(txt); + HOOK_MALLOC_FAILED; + return; + } memset(txt, 0, sizeof(mdns_txt_item_t) * num_items); + memset(txt_value_len, 0, num_items); size_t txt_num = 0; while (i < len) { @@ -2886,29 +2908,33 @@ static void _mdns_result_txt_create(const uint8_t * data, size_t len, mdns_txt_i goto handle_error;//error } - mdns_txt_item_t * t = &txt[txt_num++]; + mdns_txt_item_t * t = &txt[txt_num]; + uint8_t * value_len = &txt_value_len[txt_num]; + txt_num++; memcpy(key, data + i, name_len); key[name_len] = 0; i += name_len + 1; t->key = key; - int value_len = partLen - name_len - 1; - if (value_len > 0) { - char * value = (char *)malloc(value_len + 1); + int new_value_len = partLen - name_len - 1; + if (new_value_len > 0) { + char * value = (char *)malloc(new_value_len + 1); if (!value) { HOOK_MALLOC_FAILED; goto handle_error;//error } - memcpy(value, data + i, value_len); - value[value_len] = 0; - i += value_len; + memcpy(value, data + i, new_value_len); + value[new_value_len] = 0; + *value_len = new_value_len; + i += new_value_len; t->value = value; } } *out_txt = txt; *out_count = txt_num; + *out_value_len = txt_value_len; return; handle_error : @@ -2917,6 +2943,7 @@ handle_error : free((char *)t->key); free((char *)t->value); } + free(txt_value_len); free(txt); } @@ -3246,6 +3273,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } else if (type == MDNS_TYPE_TXT) { if (search_result) { mdns_txt_item_t * txt = NULL; + uint8_t *txt_value_len = NULL; size_t txt_count = 0; mdns_result_t * result = NULL; @@ -3266,16 +3294,17 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } } if (!result->txt) { - _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_count); + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); if (txt_count) { result->txt = txt; result->txt_count = txt_count; + result->txt_value_len = txt_value_len; } } } else { - _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_count); + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); if (txt_count) { - _mdns_search_result_add_txt(search_result, txt, txt_count, packet->tcpip_if, packet->ip_protocol); + _mdns_search_result_add_txt(search_result, txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol); } } } else if (ours) { @@ -3824,7 +3853,7 @@ static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char /** * @brief Called from parser to add TXT data to search result */ -static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) { mdns_result_t * r = search->result; while (r) { @@ -3833,6 +3862,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it goto free_txt; } r->txt = txt; + r->txt_value_len = txt_value_len; r->txt_count = txt_count; return; } @@ -3847,6 +3877,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it memset(r, 0 , sizeof(mdns_result_t)); r->txt = txt; + r->txt_value_len = txt_value_len; r->txt_count = txt_count; r->tcpip_if = tcpip_if; r->ip_protocol = ip_protocol; @@ -4225,6 +4256,7 @@ static void _mdns_execute_action(mdns_action_t * action) free((char *)txt->value); free(key); txt->value = value; + txt->value_len = action->data.srv_txt_set.value_len; break; } txt = txt->next; @@ -4238,6 +4270,7 @@ static void _mdns_execute_action(mdns_action_t * action) } txt->key = key; txt->value = value; + txt->value_len = action->data.srv_txt_set.value_len; txt->next = service->txt; service->txt = txt; } @@ -4860,8 +4893,8 @@ esp_err_t mdns_instance_name_set(const char * instance) * MDNS SERVICES * */ -esp_err_t mdns_service_add_for_host(const char * instance, const char * service, const char * proto, - const char * hostname, uint16_t port, mdns_txt_item_t txt[], size_t num_items) +esp_err_t mdns_service_add_for_host(const char * instance, const char * service, const char * proto, const char * hostname, + uint16_t port, mdns_txt_item_t txt[], size_t num_items) { if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(hostname) || !port) { @@ -5013,17 +5046,19 @@ esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_tx return mdns_service_txt_set_for_host(service, proto, _mdns_server->hostname, txt, num_items); } -esp_err_t mdns_service_txt_item_set_for_host(const char * service, const char * proto, const char * hostname, - const char * key, const char * value) +esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char *service, const char *proto, + const char *hostname, const char *key, + const char *value, uint8_t value_len) { - if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(key) || !value) { + if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || + _str_null_or_empty(key) || !value) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); + mdns_srv_item_t *s = _mdns_get_service_item(service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } - mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + mdns_action_t *action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); if (!action) { HOOK_MALLOC_FAILED; return ESP_ERR_NO_MEM; @@ -5036,12 +5071,14 @@ esp_err_t mdns_service_txt_item_set_for_host(const char * service, const char * free(action); return ESP_ERR_NO_MEM; } - action->data.srv_txt_set.value = strdup(value); + action->data.srv_txt_set.value = (char *)malloc(value_len); if (!action->data.srv_txt_set.value) { free(action->data.srv_txt_set.key); free(action); return ESP_ERR_NO_MEM; } + memcpy(action->data.srv_txt_set.value, value, value_len); + action->data.srv_txt_set.value_len = value_len; if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { free(action->data.srv_txt_set.key); free(action->data.srv_txt_set.value); @@ -5051,12 +5088,31 @@ esp_err_t mdns_service_txt_item_set_for_host(const char * service, const char * return ESP_OK; } -esp_err_t mdns_service_txt_item_set(const char * service, const char * proto, const char * key, const char * value) +esp_err_t mdns_service_txt_item_set_for_host(const char *service, const char *proto, const char *hostname, + const char *key, const char *value) +{ + return mdns_service_txt_item_set_for_host_with_explicit_value_len(service, proto, hostname, key, value, + strlen(value)); +} + + +esp_err_t mdns_service_txt_item_set(const char *service, const char *proto, const char *key, const char *value) { if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_txt_item_set_for_host(service, proto, _mdns_server->hostname, key, value); + return mdns_service_txt_item_set_for_host_with_explicit_value_len(service, proto, _mdns_server->hostname, key, + value, strlen(value)); +} + +esp_err_t mdns_service_txt_item_set_with_explicit_value_len(const char *service, const char *proto, const char *key, + const char *value, uint8_t value_len) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + return mdns_service_txt_item_set_for_host_with_explicit_value_len(service, proto, _mdns_server->hostname, key, + value, value_len); } esp_err_t mdns_service_txt_item_remove_for_host(const char * service, const char * proto, const char * hostname, @@ -5215,6 +5271,7 @@ void mdns_query_results_free(mdns_result_t * results) free((char *)(r->txt[i].value)); } free(r->txt); + free(r->txt_value_len); while (r->addr) { a = r->addr; diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 3851c4694..e1a091b45 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -277,7 +277,8 @@ typedef struct { typedef struct mdns_txt_linked_item_s { const char * key; /*!< item key name */ - const char * value; /*!< item value string */ + char * value; /*!< item value string */ + uint8_t value_len; /*!< item value length */ struct mdns_txt_linked_item_s * next; /*!< next result, or NULL for the last result in the list */ } mdns_txt_linked_item_t; @@ -426,6 +427,7 @@ typedef struct { mdns_srv_item_t * service; char * key; char * value; + uint8_t value_len; } srv_txt_set; struct { mdns_srv_item_t * service; diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index f8641197b..ff026fd62 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -75,7 +75,7 @@ static void initialise_mdns(void) //add another TXT item ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") ); //change TXT item value - ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "u", "admin") ); + ESP_ERROR_CHECK( mdns_service_txt_item_set_with_explicit_value_len("_http", "_tcp", "u", "admin", strlen("admin")) ); free(hostname); } @@ -98,9 +98,10 @@ 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 : [%zu] ", r->txt_count); for(t=0; ttxt_count; t++){ - printf("%s=%s; ", r->txt[t].key, r->txt[t].value?r->txt[t].value:"NULL"); + printf("%s=%s(%d); ", r->txt[t].key, r->txt[t].value?r->txt[t].value:"NULL", + r->txt_value_len[t]); } printf("\n"); } From 5a81eaea3ffb937247fec8c01f9b8ccf39093e44 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 10 Jun 2021 15:00:33 +0200 Subject: [PATCH 198/289] mdns: Support for One-Shot mDNS queries * Original commit: espressif/esp-idf@f167238fac37818aed75dc689eed54ad47528ab9 --- components/mdns/mdns.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 04396f257..4ff5ae8f7 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1448,7 +1448,8 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_ } #ifdef MDNS_REPEAT_QUERY_IN_RESPONSE - if (q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA) { + if (parsed_packet->src_port != MDNS_SERVICE_PORT && // Repeat the queries only for "One-Shot mDNS queries" + (q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA)) { mdns_out_question_t * out_question = malloc(sizeof(mdns_out_question_t)); if (out_question == NULL) { HOOK_MALLOC_FAILED; From 46f28a8011f29e07590e5365f1562e105e45ccfe Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Wed, 23 Jun 2021 20:17:23 +0800 Subject: [PATCH 199/289] mdns: fix memory leak in mdns_free when adding delegated hostnames * Original commit: espressif/esp-idf@0baee932111268c4a2103e1c1adeb7d99914a937 --- components/mdns/mdns.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 4ff5ae8f7..8fb6bd275 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4181,6 +4181,13 @@ static void _mdns_free_action(mdns_action_t * action) pbuf_free(action->data.rx_handle.packet->pb); free(action->data.rx_handle.packet); break; + case ACTION_DELEGATE_HOSTNAME_ADD: + free((char *)action->data.delegate_hostname.hostname); + free_address_list(action->data.delegate_hostname.address_list); + break; + case ACTION_DELEGATE_HOSTNAME_REMOVE: + free((char *)action->data.delegate_hostname.hostname); + break; default: break; } From 8a120829e2e76ab6e98573e0617cb72bb0613410 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Tue, 29 Jun 2021 15:18:44 +0800 Subject: [PATCH 200/289] mdns: return ESP_OK rather than ERR_OK in API functions * Original commit: espressif/esp-idf@2386113972ee51ea93e9740d8c34bfe9289ce909 --- components/mdns/mdns.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 8fb6bd275..e55f8c194 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4801,7 +4801,7 @@ esp_err_t mdns_hostname_set(const char * hostname) return ESP_ERR_NO_MEM; } xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); - return ERR_OK; + return ESP_OK; } esp_err_t mdns_delegate_hostname_add(const char * hostname, const mdns_ip_addr_t * address_list) @@ -4831,7 +4831,7 @@ esp_err_t mdns_delegate_hostname_add(const char * hostname, const mdns_ip_addr_t free(action); return ESP_ERR_NO_MEM; } - return ERR_OK; + return ESP_OK; } esp_err_t mdns_delegate_hostname_remove(const char * hostname) @@ -4860,7 +4860,7 @@ esp_err_t mdns_delegate_hostname_remove(const char * hostname) free(action); return ESP_ERR_NO_MEM; } - return ERR_OK; + return ESP_OK; } bool mdns_hostname_exists(const char * hostname) @@ -4894,7 +4894,7 @@ esp_err_t mdns_instance_name_set(const char * instance) free(action); return ESP_ERR_NO_MEM; } - return ERR_OK; + return ESP_OK; } /* From 5f6b6f92735ced4a65c3a23659306413d4d4f9bf Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 25 Jun 2021 08:33:38 +0200 Subject: [PATCH 201/289] mdns/fuzzer: Fix non-instrumentation test to reproduce fuzzer issues Regression from 2893d7e21b skipped reading the packet causing issues when locally reproducing crashed found by the fuzzer * Original commit: espressif/esp-idf@dae803335e6bc6d9751a360cd3f675ce4027853b --- components/mdns/test_afl_fuzz_host/test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/mdns/test_afl_fuzz_host/test.c b/components/mdns/test_afl_fuzz_host/test.c index 776a089cd..58b304e92 100644 --- a/components/mdns/test_afl_fuzz_host/test.c +++ b/components/mdns/test_afl_fuzz_host/test.c @@ -205,6 +205,7 @@ int main(int argc, char** argv) // Note: parameter1 is a file (mangled packet) which caused the crash file = fopen(argv[1], "r"); assert(file >= 0 ); + len = fread(buf, 1, 1460, file); fclose(file); } From 40da0d29be0b38511557ca1644e0f14e89cc890c Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 25 Jun 2021 08:34:39 +0200 Subject: [PATCH 202/289] mdns: Fix crashes reported by the fuzzer tests * Original commit: espressif/esp-idf@4a2e72677c6fb7681a7e2acd1a878d3deb114079 --- components/mdns/mdns.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index e55f8c194..53e04a6b5 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3171,9 +3171,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) if (discovery) { service = _mdns_get_service_item(name->service, name->proto, NULL); _mdns_remove_parsed_question(parsed_packet, MDNS_TYPE_SDPTR, service); - } else if (parsed_packet->questions && !parsed_packet->probe) { + } else if (service && parsed_packet->questions && !parsed_packet->probe) { _mdns_remove_parsed_question(parsed_packet, type, service); - } else { + } else if (service) { //check if TTL is more than half of the full TTL value (4500) if (ttl > 2250) { _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); @@ -3262,7 +3262,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } _mdns_restart_all_pcbs(); } - } else { + } else if (service) { _mdns_pcb_send_bye(packet->tcpip_if, packet->ip_protocol, &service, 1, false); _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, false); } From 47c7266103e9349cd4bff3a9159a8890bc29c5ac Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 3 Jun 2021 16:56:12 +0200 Subject: [PATCH 203/289] mdns: Add asynchronous query API Closes https://github.com/espressif/esp-idf/issues/7090 * Original commit: espressif/esp-idf@d81482d699232b22f4a5cbee2a76199a5285dadb --- components/mdns/include/mdns.h | 48 ++++++++++++++++++ components/mdns/mdns.c | 46 +++++++++++++++++ .../mdns/test_afl_fuzz_host/esp32_compat.h | 4 +- .../protocols/mdns/main/mdns_example_main.c | 49 +++++++++++++++++++ 4 files changed, 145 insertions(+), 2 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 29c22b022..7089eabe6 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -30,6 +30,11 @@ extern "C" { #define MDNS_TYPE_NSEC 0x002F #define MDNS_TYPE_ANY 0x00FF +/** + * @brief Asynchronous query handle + */ +typedef struct mdns_search_once_s mdns_search_once_t; + /** * @brief mDNS enum to specify the ip_protocol type */ @@ -477,6 +482,49 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char * service_type, const */ esp_err_t mdns_service_remove_all(void); +/** + * @brief Deletes the finished query. Call this only after the search has ended! + * + * @param search pointer to search object + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE search has not finished + * - ESP_ERR_INVALID_ARG pointer to search object is NULL + */ +esp_err_t mdns_query_async_delete(mdns_search_once_t* search); + +/** + * @brief Get results from search pointer. Results available as a pointer to the output parameter. + * Pointer to search object has to be deleted via `mdns_query_async_delete` once the query has finished. + * The results although have to be freed manually. + * + * @param search pointer to search object + * @param timeout time in milliseconds to wait for answers + * @param results pointer to the results of the query + * + * @return + * True if search has finished before or at timeout + * False if search timeout is over + */ +bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, mdns_result_t ** results); + +/** + * @brief Query mDNS for host or service asynchronousely. + * Search has to be tested for progress and deleted manually! + * + * @param name service instance or host name (NULL for PTR queries) + * @param service_type service type (_http, _arduino, _ftp etc.) (NULL for host queries) + * @param proto service protocol (_tcp, _udp, etc.) (NULL for host queries) + * @param type type of query (MDNS_TYPE_*) + * @param timeout time in milliseconds during which mDNS query is active + * @param max_results maximum results to be collected + * + * @return mdns_search_once_s pointer to new search object if query initiated successfully. + * NULL otherwise. + */ +mdns_search_once_t* mdns_query_async_new(const char * name, const char * service_type, const char * proto, uint16_t type, uint32_t timeout, size_t max_results); + /** * @brief Query mDNS for host or service * All following query methods are derived from this one diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 53e04a6b5..10132f60b 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -5292,6 +5292,52 @@ void mdns_query_results_free(mdns_result_t * results) } } +esp_err_t mdns_query_async_delete(mdns_search_once_t* search) +{ + if (!search) { + return ESP_ERR_INVALID_ARG; + } + if (search->state != SEARCH_OFF) { + return ESP_ERR_INVALID_STATE; + } + + MDNS_SERVICE_LOCK(); + _mdns_search_free(search); + MDNS_SERVICE_UNLOCK(); + + return ESP_OK; +} + +bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, mdns_result_t ** results) +{ + if (xSemaphoreTake(search->done_semaphore, pdMS_TO_TICKS(timeout)) == pdTRUE) { + *results = search->result; + return true; + } + return false; +} + +mdns_search_once_t* mdns_query_async_new(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, size_t max_results) +{ + mdns_search_once_t *search = NULL; + + if (!_mdns_server || !timeout || _str_null_or_empty(service) != _str_null_or_empty(proto)) { + return NULL; + } + + search = _mdns_search_init(name, service, proto, type, timeout, max_results); + if (!search) { + return NULL; + } + + if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { + _mdns_search_free(search); + return NULL; + } + + return search; +} + esp_err_t mdns_query(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t ** results) { mdns_search_once_t * search = NULL; diff --git a/components/mdns/test_afl_fuzz_host/esp32_compat.h b/components/mdns/test_afl_fuzz_host/esp32_compat.h index 2c980baaf..984f4096b 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_compat.h +++ b/components/mdns/test_afl_fuzz_host/esp32_compat.h @@ -63,10 +63,10 @@ #define pdMS_TO_TICKS(a) a #define portTICK_RATE_MS 10 -#define xSemaphoreTake(s,d) #define xTaskDelete(a) -#define vTaskDelete(a) free(a) +#define vTaskDelete(a) free(a) #define xSemaphoreGive(s) +#define xSemaphoreTake(s,d) true #define xQueueCreateMutex(s) #define _mdns_pcb_init(a,b) true #define _mdns_pcb_deinit(a,b) true diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index ff026fd62..fc5b45037 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -138,6 +138,54 @@ static void query_mdns_service(const char * service_name, const char * proto) mdns_query_results_free(results); } +static bool check_and_print_result(mdns_search_once_t *search) +{ + // Check if any result is available + mdns_result_t * result = NULL; + if (!mdns_query_async_get_results(search, 0, &result)) { + return false; + } + + if (!result) { // search timeout, but no result + return true; + } + + // If yes, print the result + mdns_ip_addr_t * a = result->addr; + while (a) { + if(a->addr.type == ESP_IPADDR_TYPE_V6){ + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + // and free the result + mdns_query_results_free(result); + return true; +} + +static void query_mdns_hosts_async(const char * host_name) +{ + ESP_LOGI(TAG, "Query both A and AAA: %s.local", host_name); + + mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1); + mdns_query_async_delete(s_a); + mdns_search_once_t *s_aaaa = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_AAAA, 1000, 1); + while (s_a || s_aaaa) { + if (s_a && check_and_print_result(s_a)) { + ESP_LOGI(TAG, "Query A %s.local finished", host_name); + mdns_query_async_delete(s_a); + s_a = NULL; + } + if (s_aaaa && check_and_print_result(s_aaaa)) { + ESP_LOGI(TAG, "Query AAAA %s.local finished", host_name); + mdns_query_async_delete(s_aaaa); + s_aaaa = NULL; + } + } +} + static void query_mdns_host(const char * host_name) { ESP_LOGI(TAG, "Query A: %s.local", host_name); @@ -174,6 +222,7 @@ static void check_button(void) static bool old_level = true; bool new_level = gpio_get_level(EXAMPLE_BUTTON_GPIO); if (!new_level && old_level) { + query_mdns_hosts_async("esp32-mdns"); query_mdns_host("esp32"); query_mdns_service("_arduino", "_tcp"); query_mdns_service("_http", "_tcp"); From b0957e70fd724612545451bf5665aeaea842199a Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 29 Jun 2021 10:02:44 +0200 Subject: [PATCH 204/289] mdns: Clean the main mdns module from lwip dependencies * Reduced number of include paths * Abstract the internals of mdns packet (specifics defined in mdns_networking.c) * Use ESP_IP addresses instead of lwip addresses * Original commit: espressif/esp-idf@54e329444a5dd19c51e84b5f1e16455a0f1c6225 --- components/mdns/mdns.c | 44 ++++++++----------- components/mdns/mdns_networking.c | 27 +++++++++++- .../mdns/private_include/mdns_networking.h | 31 +++++++------ .../mdns/private_include/mdns_private.h | 6 +-- 4 files changed, 60 insertions(+), 48 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 10132f60b..ea69afccc 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1115,7 +1115,7 @@ static void _mdns_dispatch_tx_packet(mdns_tx_packet_t * p) #ifdef MDNS_ENABLE_DEBUG _mdns_dbg_printf("\nTX[%u][%u]: ", p->tcpip_if, p->ip_protocol); - if (p->dst.type == IPADDR_TYPE_V4) { + if (p->dst.type == ESP_IPADDR_TYPE_V4) { _mdns_dbg_printf("To: " IPSTR ":%u, ", IP2STR(&p->dst.u_addr.ip4), p->port); } else { _mdns_dbg_printf("To: " IPV6STR ":%u, ", IPV62STR(p->dst.u_addr.ip6), p->port); @@ -1345,11 +1345,12 @@ static mdns_tx_packet_t * _mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip packet->ip_protocol = ip_protocol; packet->port = MDNS_SERVICE_PORT; if (ip_protocol == MDNS_IP_PROTOCOL_V4) { - IP4_ADDR(&packet->dst.u_addr.ip4, 224, 0, 0, 251); + esp_ip_addr_t addr = ESP_IP4ADDR_INIT(224, 0, 0, 251); + memcpy(&packet->dst, &addr, sizeof(esp_ip_addr_t)); } #if CONFIG_LWIP_IPV6 else { - esp_ip_addr_t addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); + esp_ip_addr_t addr = ESP_IP6ADDR_INIT(0x000002ff, 0, 0, 0xfb000000); memcpy(&packet->dst, &addr, sizeof(esp_ip_addr_t)); } #endif @@ -2973,15 +2974,15 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) { static mdns_name_t n; mdns_header_t header; - const uint8_t * data = (const uint8_t*)packet->pb->payload; - size_t len = packet->pb->len; + const uint8_t * data = _mdns_get_packet_data(packet); + size_t len = _mdns_get_packet_len(packet); const uint8_t * content = data + MDNS_HEAD_LEN; bool do_not_reply = false; mdns_search_once_t * search_result = NULL; #ifdef MDNS_ENABLE_DEBUG _mdns_dbg_printf("\nRX[%u][%u]: ", packet->tcpip_if, (uint32_t)packet->ip_protocol); - if (packet->src.type == IPADDR_TYPE_V4) { + if (packet->src.type == ESP_IPADDR_TYPE_V4) { _mdns_dbg_printf("From: " IPSTR ":%u, To: " IPSTR ", ", IP2STR(&packet->src.u_addr.ip4), packet->src_port, IP2STR(&packet->dest.u_addr.ip4)); } else { _mdns_dbg_printf("From: " IPV6STR ":%u, To: " IPV6STR ", ", IPV62STR(packet->src.u_addr.ip6), packet->src_port, IPV62STR(packet->dest.u_addr.ip6)); @@ -3023,12 +3024,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) parsed_packet->authoritative = header.flags.value == MDNS_FLAGS_AUTHORITATIVE; parsed_packet->distributed = header.flags.value == MDNS_FLAGS_DISTRIBUTED; parsed_packet->id = header.id; -#if CONFIG_LWIP_IPV6 - ip_addr_copy(parsed_packet->src, packet->src); -#else - ip4_addr_copy(parsed_packet->src.u_addr.ip4, packet->src.u_addr.ip4); -#endif - + esp_netif_ip_addr_copy(&parsed_packet->src, &packet->src); parsed_packet->src_port = packet->src_port; if (header.questions) { @@ -3334,7 +3330,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) #if CONFIG_LWIP_IPV6 else if (type == MDNS_TYPE_AAAA) {//ipv6 esp_ip_addr_t ip6; - ip6.type = IPADDR_TYPE_V6; + ip6.type = ESP_IPADDR_TYPE_V6; 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) @@ -3384,7 +3380,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) #endif else if (type == MDNS_TYPE_A) { esp_ip_addr_t ip; - ip.type = IPADDR_TYPE_V4; + ip.type = ESP_IPADDR_TYPE_V4; memcpy(&(ip.u_addr.ip4.addr), data_ptr, 4); if (search_result) { //check for more applicable searches (PTR & A/AAAA at the same time) @@ -3695,7 +3691,7 @@ static mdns_ip_addr_t * _mdns_result_addr_create_ip(esp_ip_addr_t * ip) } memset(a, 0 , sizeof(mdns_ip_addr_t)); a->addr.type = ip->type; - if (ip->type == IPADDR_TYPE_V6) { + if (ip->type == ESP_IPADDR_TYPE_V6) { memcpy(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16); } else { a->addr.u_addr.ip4.addr = ip->u_addr.ip4.addr; @@ -3711,10 +3707,10 @@ static void _mdns_result_add_ip(mdns_result_t * r, esp_ip_addr_t * ip) mdns_ip_addr_t * a = r->addr; while (a) { if (a->addr.type == ip->type) { - if (a->addr.type == IPADDR_TYPE_V4 && a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { + if (a->addr.type == ESP_IPADDR_TYPE_V4 && a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { return; } - if (a->addr.type == IPADDR_TYPE_V6 && !memcmp(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { + if (a->addr.type == ESP_IPADDR_TYPE_V6 && !memcmp(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { return; } } @@ -3736,8 +3732,8 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * mdns_result_t * r = NULL; mdns_ip_addr_t * a = NULL; - if ((search->type == MDNS_TYPE_A && ip->type == IPADDR_TYPE_V4) - || (search->type == MDNS_TYPE_AAAA && ip->type == IPADDR_TYPE_V6) + if ((search->type == MDNS_TYPE_A && ip->type == ESP_IPADDR_TYPE_V4) + || (search->type == MDNS_TYPE_AAAA && ip->type == ESP_IPADDR_TYPE_V6) || search->type == MDNS_TYPE_ANY) { r = search->result; while (r) { @@ -4178,8 +4174,7 @@ static void _mdns_free_action(mdns_action_t * action) _mdns_free_tx_packet(action->data.tx_handle.packet); break; case ACTION_RX_HANDLE: - pbuf_free(action->data.rx_handle.packet->pb); - free(action->data.rx_handle.packet); + _mdns_packet_free(action->data.rx_handle.packet); break; case ACTION_DELEGATE_HOSTNAME_ADD: free((char *)action->data.delegate_hostname.hostname); @@ -4379,8 +4374,7 @@ static void _mdns_execute_action(mdns_action_t * action) break; case ACTION_RX_HANDLE: mdns_parse_packet(action->data.rx_handle.packet); - pbuf_free(action->data.rx_handle.packet->pb); - free(action->data.rx_handle.packet); + _mdns_packet_free(action->data.rx_handle.packet); break; case ACTION_DELEGATE_HOSTNAME_ADD: _mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, @@ -5421,7 +5415,7 @@ esp_err_t mdns_query_a(const char * name, uint32_t timeout, esp_ip4_addr_t * add mdns_ip_addr_t * a = result->addr; while (a) { - if (a->addr.type == IPADDR_TYPE_V4) { + if (a->addr.type == ESP_IPADDR_TYPE_V4) { addr->addr = a->addr.u_addr.ip4.addr; mdns_query_results_free(result); return ESP_OK; @@ -5459,7 +5453,7 @@ esp_err_t mdns_query_aaaa(const char * name, uint32_t timeout, esp_ip6_addr_t * mdns_ip_addr_t * a = result->addr; while (a) { - if (a->addr.type == IPADDR_TYPE_V6) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { memcpy(addr->addr, a->addr.u_addr.ip6.addr, 16); mdns_query_results_free(result); return ESP_OK; diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c index 48d11918b..5f7a6673f 100644 --- a/components/mdns/mdns_networking.c +++ b/components/mdns/mdns_networking.c @@ -4,11 +4,18 @@ * */ #include -#include "mdns_networking.h" #include "esp_log.h" +#include "lwip/ip_addr.h" +#include "lwip/pbuf.h" +#include "lwip/igmp.h" +#include "lwip/udp.h" +#include "lwip/mld6.h" +#include "lwip/priv/tcpip_priv.h" +#include "esp_system.h" +#include "esp_event.h" +#include "mdns_networking.h" #include "esp_netif_net_stack.h" - extern mdns_server_t * _mdns_server; /* @@ -345,3 +352,19 @@ size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, c } return len; } + +void* _mdns_get_packet_data(mdns_rx_packet_t *packet) +{ + return packet->pb->payload; +} + +size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +{ + return packet->pb->len; +} + +void _mdns_packet_free(mdns_rx_packet_t *packet) +{ + pbuf_free(packet->pb); + free(packet); +} diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h index 5a8156af9..53772c835 100644 --- a/components/mdns/private_include/mdns_networking.h +++ b/components/mdns/private_include/mdns_networking.h @@ -7,22 +7,6 @@ */ #include "mdns.h" #include "mdns_private.h" -#include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" -#include "lwip/ip_addr.h" -#include "lwip/pbuf.h" -#include "lwip/igmp.h" -#include "lwip/udp.h" -#include "lwip/mld6.h" -#include "lwip/priv/tcpip_priv.h" -#include "esp_wifi.h" -#include "esp_system.h" -#include "esp_event.h" -#if CONFIG_ETH_ENABLED -#include "esp_eth.h" -#endif /** @@ -51,4 +35,19 @@ esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); */ size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len); +/** + * @brief Gets data pointer to the mDNS packet + */ +void* _mdns_get_packet_data(mdns_rx_packet_t *packet); + +/** + * @brief Gets data length of c + */ +size_t _mdns_get_packet_len(mdns_rx_packet_t *packet); + +/** + * @brief Free the mDNS packet + */ +void _mdns_packet_free(mdns_rx_packet_t *packet); + #endif /* ESP_MDNS_NETWORKING_H_ */ diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index e1a091b45..6931d4f5a 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -14,12 +14,8 @@ #ifndef MDNS_PRIVATE_H_ #define MDNS_PRIVATE_H_ -#include "esp_event_base.h" -#include "esp_task.h" -#include "esp_timer.h" -#include "esp_netif_ip_addr.h" -#include "freertos/FreeRTOS.h" #include "mdns.h" +#include "esp_task.h" //#define MDNS_ENABLE_DEBUG From af2275341e9554de16092d6ce908b31e97733bde Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 29 Jun 2021 15:02:48 +0200 Subject: [PATCH 205/289] mdns: Fix fuzzer IDF-mock layer Removed lwip dependencies Simplified the mocks for esp32 and esp-netif * Original commit: espressif/esp-idf@619235c2ee5a1fe8411bd2be2de8798209f95902 --- components/mdns/test_afl_fuzz_host/Makefile | 6 +- .../mdns/test_afl_fuzz_host/esp32_compat.h | 188 ------------------ .../mdns/test_afl_fuzz_host/esp32_mock.c | 2 +- .../mdns/test_afl_fuzz_host/esp32_mock.h | 159 ++++++++++++++- .../esp_netif_loopback_mock.c | 36 ---- ..._netif_objects_mock.c => esp_netif_mock.c} | 44 ++-- .../mdns/test_afl_fuzz_host/mdns_mock.h | 24 ++- components/mdns/test_afl_fuzz_host/test.c | 1 + 8 files changed, 197 insertions(+), 263 deletions(-) delete mode 100644 components/mdns/test_afl_fuzz_host/esp32_compat.h delete mode 100644 components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c rename components/mdns/test_afl_fuzz_host/{esp_netif_objects_mock.c => esp_netif_mock.c} (64%) diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 8d98d501e..4d6067bb4 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -3,8 +3,8 @@ FUZZ=afl-fuzz COMPONENTS_DIR=../.. COMPILER_ICLUDE_DIR=$(shell echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf) -CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversion -Wno-macro-redefined -Wno-int-to-void-pointer-cast -DHOOK_MALLOC_FAILED -DESP_EVENT_H_ -D__ESP_LOG_H__ -DMDNS_TEST_MODE \ - -I. -I.. -I../include -I../private_include -I ./build/config -include esp32_compat.h \ +CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversion -Wno-macro-redefined -Wno-int-to-void-pointer-cast -DHOOK_MALLOC_FAILED -DESP_EVENT_H_ -D__ESP_LOG_H__ \ + -I. -I.. -I../include -I../private_include -I ./build/config \ -I$(COMPONENTS_DIR) \ -I$(COMPONENTS_DIR)/driver/include \ -I$(COMPONENTS_DIR)/esp_common/include \ @@ -49,7 +49,7 @@ else endif CPP=$(CC) LD=$(CC) -OBJECTS=esp32_mock.o esp_netif_loopback_mock.o mdns.o test.o esp_netif_objects_mock.o +OBJECTS=esp32_mock.o mdns.o test.o esp_netif_mock.o OS := $(shell uname) ifeq ($(OS),Darwin) diff --git a/components/mdns/test_afl_fuzz_host/esp32_compat.h b/components/mdns/test_afl_fuzz_host/esp32_compat.h deleted file mode 100644 index 984f4096b..000000000 --- a/components/mdns/test_afl_fuzz_host/esp32_compat.h +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef _ESP32_COMPAT_H_ -#define _ESP32_COMPAT_H_ - -#ifdef MDNS_TEST_MODE - -// Not to include -#define ESP_MDNS_NETWORKING_H_ -#define _TCPIP_ADAPTER_H_ - - -#ifdef USE_BSD_STRING -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#define ESP_FAIL -1 - -#define ESP_ERR_NO_MEM 0x101 -#define ESP_ERR_INVALID_ARG 0x102 -#define ESP_ERR_INVALID_STATE 0x103 -#define ESP_ERR_INVALID_SIZE 0x104 -#define ESP_ERR_NOT_FOUND 0x105 -#define ESP_ERR_NOT_SUPPORTED 0x106 -#define ESP_ERR_TIMEOUT 0x107 -#define ESP_ERR_INVALID_RESPONSE 0x108 -#define ESP_ERR_INVALID_CRC 0x109 - -#define pdTRUE true -#define pdFALSE false -#define pdPASS ( pdTRUE ) -#define pdFAIL ( pdFALSE ) - -#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_SYSTEM_H__ -#define INC_TASK_H - -#define pdMS_TO_TICKS(a) a -#define portTICK_RATE_MS 10 -#define xTaskDelete(a) -#define vTaskDelete(a) free(a) -#define xSemaphoreGive(s) -#define xSemaphoreTake(s,d) true -#define xQueueCreateMutex(s) -#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 queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U -#define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1) -#define vTaskDelay(m) usleep((m)*0) -#define pbuf_free(p) free(p) -#define esp_random() (rand()%UINT32_MAX) -#define tcpip_adapter_get_ip_info(i,d) true -#define tcpip_adapter_dhcpc_get_status(a, b) TCPIP_ADAPTER_DHCP_STARTED -#define tcpip_adapter_get_ip6_linklocal(i,d) (ESP_OK) -#define tcpip_adapter_get_hostname(i, n) *(n) = "esp32-0123456789AB" - -#define IP4_ADDR(ipaddr, a,b,c,d) \ - (ipaddr)->addr = ((uint32_t)((d) & 0xff) << 24) | \ - ((uint32_t)((c) & 0xff) << 16) | \ - ((uint32_t)((b) & 0xff) << 8) | \ - (uint32_t)((a) & 0xff) -#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) -#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) - -#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) -#define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \ - IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0) -#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \ - IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0) - -#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 } - -typedef int32_t esp_err_t; - -typedef void * xSemaphoreHandle; -typedef void * SemaphoreHandle_t; -typedef void * xQueueHandle; -typedef void * QueueHandle_t; -typedef void * TaskHandle_t; -typedef int BaseType_t; -typedef uint32_t TickType_t; -typedef uint32_t portTickType; - - -extern const char * WIFI_EVENT; -extern const char * IP_EVENT; -extern const char * ETH_EVENT; - -/* status of DHCP client or DHCP server */ -typedef enum { - TCPIP_ADAPTER_DHCP_INIT = 0, /**< DHCP client/server in initial state */ - TCPIP_ADAPTER_DHCP_STARTED, /**< DHCP client/server already been started */ - TCPIP_ADAPTER_DHCP_STOPPED, /**< DHCP client/server already been stopped */ - TCPIP_ADAPTER_DHCP_STATUS_MAX -} tcpip_adapter_dhcp_status_t; - -struct udp_pcb { - uint8_t dummy; -}; - -struct ip4_addr { - uint32_t addr; -}; -typedef struct ip4_addr ip4_addr_t; - -struct ip6_addr { - uint32_t addr[4]; -}; -typedef struct ip6_addr ip6_addr_t; - -typedef struct { - ip4_addr_t ip; - ip4_addr_t netmask; - ip4_addr_t gw; -} tcpip_adapter_ip_info_t; - -typedef enum { - TCPIP_ADAPTER_IF_STA = 0, /**< ESP32 station interface */ - TCPIP_ADAPTER_IF_AP, /**< ESP32 soft-AP interface */ - TCPIP_ADAPTER_IF_ETH, /**< ESP32 ethernet interface */ - TCPIP_ADAPTER_IF_MAX -} tcpip_adapter_if_t; - -typedef struct { - ip6_addr_t ip; -} tcpip_adapter_ip6_info_t; - -typedef void* system_event_t; - -struct pbuf { - struct pbuf *next; - void *payload; - uint16_t tot_len; - uint16_t len; - uint8_t /*pbuf_type*/ type; - uint8_t flags; - uint16_t ref; -}; - -#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) -#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) -#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) -#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ - (dest).addr[1] = (src).addr[1]; \ - (dest).addr[2] = (src).addr[2]; \ - (dest).addr[3] = (src).addr[3];}while(0) - -#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ - ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ - ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) - -#include "esp32_mock.h" - -uint32_t xTaskGetTickCount(void); - - -#endif //MDNS_TEST_MODE - -#endif //_ESP32_COMPAT_H_ diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.c b/components/mdns/test_afl_fuzz_host/esp32_mock.c index d806093fc..08ac305c5 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.c +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.c @@ -3,7 +3,7 @@ #include #include #include -#include "esp32_compat.h" +#include "esp32_mock.h" void* g_queue; int g_queue_send_shall_fail = 0; diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h index 9f97127d2..5acf53842 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.h @@ -1,12 +1,161 @@ -#ifndef ESP32_MOCK_H_ -#define ESP32_MOCK_H_ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ESP32_COMPAT_H_ +#define _ESP32_COMPAT_H_ + +// Skip these include files +#define ESP_MDNS_NETWORKING_H_ +#define _TCPIP_ADAPTER_H_ +#define _ESP_TASK_H_ + +#ifdef USE_BSD_STRING +#include +#endif +#include +#include +#include +#include +#include +#include +#include #include "esp_timer.h" +#define ESP_FAIL -1 + +#define ESP_ERR_NO_MEM 0x101 +#define ESP_ERR_INVALID_ARG 0x102 +#define ESP_ERR_INVALID_STATE 0x103 +#define ESP_ERR_INVALID_SIZE 0x104 +#define ESP_ERR_NOT_FOUND 0x105 +#define ESP_ERR_NOT_SUPPORTED 0x106 +#define ESP_ERR_TIMEOUT 0x107 +#define ESP_ERR_INVALID_RESPONSE 0x108 +#define ESP_ERR_INVALID_CRC 0x109 + +#define pdTRUE true +#define pdFALSE false +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) + +#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_SYSTEM_H__ +#define INC_TASK_H + +#define pdMS_TO_TICKS(a) a +#define portTICK_RATE_MS 10 +#define xSemaphoreTake(s,d) true +#define xTaskDelete(a) +#define vTaskDelete(a) free(a) +#define xSemaphoreGive(s) +#define xQueueCreateMutex(s) +#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 queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U +#define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1) +#define vTaskDelay(m) usleep((m)*0) +#define esp_random() (rand()%UINT32_MAX) + + +#define ESP_TASK_PRIO_MAX 25 +#define ESP_TASKD_EVENT_PRIO 5 +#define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len +#define xTaskHandle TaskHandle_t + + +typedef int32_t esp_err_t; + +typedef void * xSemaphoreHandle; +typedef void * SemaphoreHandle_t; +typedef void * xQueueHandle; +typedef void * QueueHandle_t; +typedef void * TaskHandle_t; +typedef int BaseType_t; +typedef uint32_t TickType_t; +typedef uint32_t portTickType; + + +extern const char * WIFI_EVENT; +extern const char * IP_EVENT; +extern const char * ETH_EVENT; + +/* status of DHCP client or DHCP server */ +typedef enum { + TCPIP_ADAPTER_DHCP_INIT = 0, /**< DHCP client/server in initial state */ + TCPIP_ADAPTER_DHCP_STARTED, /**< DHCP client/server already been started */ + TCPIP_ADAPTER_DHCP_STOPPED, /**< DHCP client/server already been stopped */ + TCPIP_ADAPTER_DHCP_STATUS_MAX +} tcpip_adapter_dhcp_status_t; + +struct udp_pcb { + uint8_t dummy; +}; + +struct ip4_addr { + uint32_t addr; +}; +typedef struct ip4_addr ip4_addr_t; + +struct ip6_addr { + uint32_t addr[4]; +}; +typedef struct ip6_addr ip6_addr_t; + +typedef struct { + ip4_addr_t ip; + ip4_addr_t netmask; + ip4_addr_t gw; +} tcpip_adapter_ip_info_t; + +typedef enum { + TCPIP_ADAPTER_IF_STA = 0, /**< ESP32 station interface */ + TCPIP_ADAPTER_IF_AP, /**< ESP32 soft-AP interface */ + TCPIP_ADAPTER_IF_ETH, /**< ESP32 ethernet interface */ + TCPIP_ADAPTER_IF_MAX +} tcpip_adapter_if_t; + +typedef struct { + ip6_addr_t ip; +} tcpip_adapter_ip6_info_t; + +typedef void* system_event_t; + +struct pbuf { + struct pbuf *next; + void *payload; + uint16_t tot_len; + uint16_t len; + uint8_t /*pbuf_type*/ type; + uint8_t flags; + uint16_t ref; +}; + +uint32_t xTaskGetTickCount(void); typedef void (*esp_timer_cb_t)(void* arg); // Queue mock QueueHandle_t xQueueCreate( uint32_t uxQueueLength, - uint32_t uxItemSize ); + uint32_t uxItemSize ); void vQueueDelete( QueueHandle_t xQueue ); @@ -22,11 +171,9 @@ esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id, 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 -// Task signify mock TaskHandle_t xTaskGetCurrentTaskHandle(void); void xTaskNotifyGive(TaskHandle_t task); BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time ); -#endif /* ESP32_MOCK_H_ */ +#endif //_ESP32_COMPAT_H_ diff --git a/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c b/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c deleted file mode 100644 index 72ada5f9d..000000000 --- a/components/mdns/test_afl_fuzz_host/esp_netif_loopback_mock.c +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) CO LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "esp32_compat.h" -#include "esp_netif_lwip_internal.h" - -esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) -{ - return ESP_ERR_NOT_SUPPORTED; -} - -esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) -{ - return ESP_ERR_NOT_SUPPORTED; -} - -const char *esp_netif_get_ifkey(esp_netif_t *esp_netif) -{ - return NULL; -} - -esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6) -{ - return ESP_ERR_NOT_SUPPORTED; -} diff --git a/components/mdns/test_afl_fuzz_host/esp_netif_objects_mock.c b/components/mdns/test_afl_fuzz_host/esp_netif_mock.c similarity index 64% rename from components/mdns/test_afl_fuzz_host/esp_netif_objects_mock.c rename to components/mdns/test_afl_fuzz_host/esp_netif_mock.c index 124144992..36118199b 100644 --- a/components/mdns/test_afl_fuzz_host/esp_netif_objects_mock.c +++ b/components/mdns/test_afl_fuzz_host/esp_netif_mock.c @@ -12,47 +12,31 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "esp_netif.h" -#include "sys/queue.h" -#include "esp_log.h" -#include "esp_netif_private.h" +#include #include +#include +#include +#include +#include "esp32_mock.h" -// -// Purpose of this module is to provide list of esp-netif structures -// - this module has no dependency on a specific network stack (lwip) -// +typedef struct esp_netif_s esp_netif_t; +typedef struct esp_netif_ip_info esp_netif_ip_info_t; +typedef struct esp_netif_dhcp_status esp_netif_dhcp_status_t; -struct slist_netifs_s { - esp_netif_t *netif; - SLIST_ENTRY(slist_netifs_s) next; -}; -SLIST_HEAD(slisthead, slist_netifs_s) s_head = { .slh_first = NULL, }; +const char * IP_EVENT = "IP_EVENT"; -static size_t s_esp_netif_counter = 0; -ESP_EVENT_DEFINE_BASE(IP_EVENT); - -// -// List manipulation functions -// esp_err_t esp_netif_add_to_list(esp_netif_t *netif) { return ESP_OK; } - esp_err_t esp_netif_remove_from_list(esp_netif_t *netif) { return ESP_ERR_NOT_FOUND; } -size_t esp_netif_get_nr_of_ifs(void) -{ - return s_esp_netif_counter; -} - esp_netif_t* esp_netif_next(esp_netif_t* netif) { return NULL; @@ -67,3 +51,13 @@ esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key) { return NULL; } + +esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) +{ + return ESP_ERR_NOT_SUPPORTED; +} + +esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) +{ + return ESP_ERR_NOT_SUPPORTED; +} diff --git a/components/mdns/test_afl_fuzz_host/mdns_mock.h b/components/mdns/test_afl_fuzz_host/mdns_mock.h index 73ae1568a..1898de2c0 100644 --- a/components/mdns/test_afl_fuzz_host/mdns_mock.h +++ b/components/mdns/test_afl_fuzz_host/mdns_mock.h @@ -1,5 +1,21 @@ #pragma once -#define ERR_OK 0 -#define IPADDR_TYPE_V4 0U -#define IPADDR_TYPE_V6 6U -#define IPADDR_TYPE_ANY 46U +#include "esp32_mock.h" +#include "mdns.h" +#include "mdns_private.h" + + +static inline void* _mdns_get_packet_data(mdns_rx_packet_t *packet) +{ + return packet->pb->payload; +} + +static inline size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +{ + return packet->pb->len; +} + +static inline void _mdns_packet_free(mdns_rx_packet_t *packet) +{ + free(packet->pb); + free(packet); +} diff --git a/components/mdns/test_afl_fuzz_host/test.c b/components/mdns/test_afl_fuzz_host/test.c index 58b304e92..e7fe0b20e 100644 --- a/components/mdns/test_afl_fuzz_host/test.c +++ b/components/mdns/test_afl_fuzz_host/test.c @@ -18,6 +18,7 @@ #include #include +#include "esp32_mock.h" #include "mdns.h" #include "mdns_private.h" From 6a92d3253f285eb0f3bf8ffc6b55d98c5b0757e3 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 30 Jun 2021 08:42:09 +0200 Subject: [PATCH 206/289] CI: mdns example test: start responder after valid IP to clean up the test and not to pollute the network unnecessarily. Also keeps sending the delegated query until a response found * Original commit: espressif/esp-idf@042fa1831e986623f510e3c54b42bd316bff61d5 --- examples/protocols/mdns/mdns_example_test.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index 5bbae2111..a3e36dd78 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -71,10 +71,12 @@ def mdns_server(esp_host): while not stop_mdns_server.is_set(): try: current_time = time.time() - if not esp_answered.is_set() and current_time - last_query_timepoint > QUERY_TIMEOUT: - sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT)) - sock.sendto(get_dns_query_for_esp(esp_host + '-delegated'), (MCAST_GRP,UDP_PORT)) + if current_time - last_query_timepoint > QUERY_TIMEOUT: last_query_timepoint = current_time + if not esp_answered.is_set(): + sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT)) + if not esp_delegated_answered.is_set(): + sock.sendto(get_dns_query_for_esp(esp_host + '-delegated'), (MCAST_GRP,UDP_PORT)) timeout = max(0, QUERY_TIMEOUT - (current_time - last_query_timepoint)) read_socks, _, _ = select.select([sock], [], [], timeout) if not read_socks: @@ -119,19 +121,16 @@ def test_examples_protocol_mdns(env, extra_data): # 1. start mdns application dut1.start_app() # 2. get the dut host name (and IP address) - specific_host = dut1.expect(re.compile(r'mdns hostname set to: \[([^\]]+)\]'), timeout=30) - specific_host = str(specific_host[0]) - thread1 = Thread(target=mdns_server, args=(specific_host,)) - thread1.start() + specific_host = dut1.expect(re.compile(r'mdns hostname set to: \[([^\]]+)\]'), timeout=30)[0] + mdns_responder = Thread(target=mdns_server, args=(str(specific_host),)) try: ip_address = dut1.expect(re.compile(r' sta ip: ([^,]+),'), timeout=30)[0] console_log('Connected to AP with IP: {}'.format(ip_address)) except DUT.ExpectTimeout: - stop_mdns_server.set() - thread1.join() raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') try: # 3. check the mdns name is accessible + mdns_responder.start() if not esp_answered.wait(timeout=30): raise ValueError('Test has failed: did not receive mdns answer within timeout') if not esp_delegated_answered.wait(timeout=30): @@ -149,7 +148,7 @@ def test_examples_protocol_mdns(env, extra_data): "Output should've contained DUT's IP address:{}".format(ip_address)) finally: stop_mdns_server.set() - thread1.join() + mdns_responder.join() if __name__ == '__main__': From c2abeff4760ae50f1559df3609e627729eaa7a61 Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Thu, 24 Jun 2021 11:03:11 +0200 Subject: [PATCH 207/289] examples: Update Ethernet examples to use new PHY LAN87xx init function Ethernet examples device usage and Kconfig options synchronized * Original commit: espressif/esp-idf@4e77430107ce187ad61d7ce6c83dc20d2a3ea0d7 --- .../protocol_examples_common/Kconfig.projbuild | 13 ++++++++++--- .../protocol_examples_common/connect.c | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index cd4028d9d..62d6b6077 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -162,11 +162,18 @@ menu "Example Connection Configuration" RTL8201F/SR8201F is a single port 10/100Mb Ethernet Transceiver with auto MDIX. Goto http://www.corechip-sz.com/productsview.asp?id=22 for more information about it. - config EXAMPLE_ETH_PHY_LAN8720 - bool "LAN8720" + config EXAMPLE_ETH_PHY_LAN87XX + bool "LAN87xx" help + Below chips are supported: + LAN8710A is a small footprint MII/RMII 10/100 Ethernet Transceiver with HP Auto-MDIX and + flexPWR® Technology. LAN8720A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX Support. - Goto https://www.microchip.com/LAN8720A for more information about it. + LAN8740A/LAN8741A is a small footprint MII/RMII 10/100 Energy Efficient Ethernet Transceiver + with HP Auto-MDIX and flexPWR® Technology. + LAN8742A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX and + flexPWR® Technology. + Goto https://www.microchip.com for more information about them. config EXAMPLE_ETH_PHY_DP83848 bool "DP83848" diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 40bac5fec..d1063b43a 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -393,8 +393,8 @@ static esp_netif_t *eth_start(void) s_phy = esp_eth_phy_new_ip101(&phy_config); #elif CONFIG_EXAMPLE_ETH_PHY_RTL8201 s_phy = esp_eth_phy_new_rtl8201(&phy_config); -#elif CONFIG_EXAMPLE_ETH_PHY_LAN8720 - s_phy = esp_eth_phy_new_lan8720(&phy_config); +#elif CONFIG_EXAMPLE_ETH_PHY_LAN87XX + s_phy = esp_eth_phy_new_lan87xx(&phy_config); #elif CONFIG_EXAMPLE_ETH_PHY_DP83848 s_phy = esp_eth_phy_new_dp83848(&phy_config); #endif From 4c368c009087258dd18dcccfa1928cce60c842d4 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Tue, 27 Jul 2021 12:06:01 +0800 Subject: [PATCH 208/289] mdns: fix crash when adding services without hostname set * Original commit: espressif/esp-idf@5e98772eaf7e50d96cf2e6ecdfedcd928b61c864 --- components/mdns/mdns.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index ea69afccc..508672d30 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -178,7 +178,7 @@ static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char static mdns_host_item_t * mdns_get_host_item(const char * hostname) { - if (strcasecmp(hostname, _mdns_server->hostname) == 0) { + if (hostname == NULL || strcasecmp(hostname, _mdns_server->hostname) == 0) { return &_mdns_self_host; } mdns_host_item_t * host = _mdns_host_list; @@ -4898,8 +4898,7 @@ esp_err_t mdns_instance_name_set(const char * instance) esp_err_t mdns_service_add_for_host(const char * instance, const char * service, const char * proto, const char * hostname, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(hostname) || - !port) { + if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { return ESP_ERR_INVALID_ARG; } @@ -4959,7 +4958,7 @@ esp_err_t mdns_service_add_for_host(const char * instance, const char * service, esp_err_t mdns_service_add(const char * instance, const char * service, const char * proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!_mdns_server || _str_null_or_empty(_mdns_server->hostname)) { + if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_add_for_host(instance, service, proto, _mdns_server->hostname, port, txt, num_items); From 0c71c7bfe1e14c3ab06dbdc443549c8971f05f98 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 8 Jul 2021 18:08:14 +0200 Subject: [PATCH 209/289] mdns: Implement mdns_networking using BSD sockets And use only if configured. By default we still use lwip raw (low-level) API * Original commit: espressif/esp-idf@73dfe84bf295a850edfad39b6b097a71f15964dc --- ...ns_networking.c => mdns_networking_lwip.c} | 0 components/mdns/mdns_networking_socket.c | 504 ++++++++++++++++++ .../mdns/private_include/mdns_private.h | 1 - 3 files changed, 504 insertions(+), 1 deletion(-) rename components/mdns/{mdns_networking.c => mdns_networking_lwip.c} (100%) create mode 100644 components/mdns/mdns_networking_socket.c diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking_lwip.c similarity index 100% rename from components/mdns/mdns_networking.c rename to components/mdns/mdns_networking_lwip.c diff --git a/components/mdns/mdns_networking_socket.c b/components/mdns/mdns_networking_socket.c new file mode 100644 index 000000000..55533a9f7 --- /dev/null +++ b/components/mdns/mdns_networking_socket.c @@ -0,0 +1,504 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @brief MDNS Server Networking module implemented using BSD sockets + */ + +#include +#include "esp_event.h" +#include "mdns_networking.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "esp_log.h" + +#if defined(CONFIG_IDF_TARGET_LINUX) +#include +#include +#endif + +extern mdns_server_t * _mdns_server; + +static const char *TAG = "MDNS_Networking"; +static bool s_run_sock_recv_task = false; +static int create_socket(esp_netif_t *netif); +static int join_mdns_multicast_group(int sock, esp_netif_t *netif, mdns_ip_protocol_t ip_protocol); + +#if defined(CONFIG_IDF_TARGET_LINUX) +// Need to define packet buffer struct on linux +struct pbuf { + struct pbuf * next; + void * payload; + size_t tot_len; + size_t len; +}; +#else +// Compatibility define to access sock-addr struct the same way for lwip and linux +#define s6_addr32 un.u32_addr +#endif // CONFIG_IDF_TARGET_LINUX + +static void delete_socket(int sock) +{ + close(sock); +} + +static struct udp_pcb* sock_to_pcb(int sock) +{ + if (sock < 0) { + return NULL; + } + // Note: sock=0 is a valid descriptor, so save it as +1 ("1" is a valid pointer) + intptr_t sock_plus_one = sock + 1; + return (struct udp_pcb*)sock_plus_one; +} + +static int pcb_to_sock(struct udp_pcb* pcb) +{ + if (pcb == NULL) { + return -1; + } + intptr_t sock_plus_one = (intptr_t)pcb; + return sock_plus_one - 1; +} + +void* _mdns_get_packet_data(mdns_rx_packet_t *packet) +{ + return packet->pb->payload; +} + +size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +{ + return packet->pb->len; +} + +void _mdns_packet_free(mdns_rx_packet_t *packet) +{ + free(packet->pb->payload); + free(packet->pb); + free(packet); +} + +esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + struct udp_pcb * pcb = _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb; + _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb = NULL; + if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb == NULL && + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb == NULL) { + // if the interface for both protocol uninitialized, close the interface socket + int sock = pcb_to_sock(pcb); + if (sock >= 0) { + delete_socket(sock); + } + } + + for (int i=0; iinterfaces[i].pcbs[j].pcb) + // If any of the interfaces/protocol initialized + return ESP_OK; + } + } + + // no interface alive, stop the rx task + s_run_sock_recv_task = false; + vTaskDelay(pdMS_TO_TICKS(500)); + return ESP_OK; +} + +#if defined(CONFIG_IDF_TARGET_LINUX) +#ifdef CONFIG_LWIP_IPV6 +static char* inet6_ntoa_r(struct in6_addr addr, char* ptr, size_t size) +{ + inet_ntop(AF_INET6, &(addr.s6_addr32[0]), ptr, size); + return ptr; +} +#endif // CONFIG_LWIP_IPV6 +static char* inet_ntoa_r(struct in_addr addr, char* ptr, size_t size) +{ + char * res = inet_ntoa(addr); + if (res && strlen(res) < size) { + strcpy(ptr, res); + } + return res; +} +#endif // CONFIG_IDF_TARGET_LINUX + +static inline char* get_string_address(struct sockaddr_storage *source_addr) +{ + static char address_str[40]; // 40=(8*4+7+term) is the max size of ascii IPv6 addr "XXXX:XX...XX:XXXX" + char *res = NULL; + // Convert ip address to string + if (source_addr->ss_family == PF_INET) { + res = inet_ntoa_r(((struct sockaddr_in *)source_addr)->sin_addr, address_str, sizeof(address_str)); + } +#ifdef CONFIG_LWIP_IPV6 + else if (source_addr->ss_family == PF_INET6) { + res = inet6_ntoa_r(((struct sockaddr_in6 *)source_addr)->sin6_addr, address_str, sizeof(address_str)); + } +#endif + if (!res) { + address_str[0] = '\0'; // Returns empty string if conversion didn't succeed + } + return address_str; +} + + +static inline size_t espaddr_to_inet(const esp_ip_addr_t *addr, const uint16_t port, const mdns_ip_protocol_t ip_protocol, struct sockaddr_storage *in_addr) +{ + size_t ss_addr_len = 0; + memset(in_addr, 0, sizeof(struct sockaddr_storage)); + if (ip_protocol == MDNS_IP_PROTOCOL_V4 && addr->type == ESP_IPADDR_TYPE_V4) { + in_addr->ss_family = PF_INET; +#if !defined(CONFIG_IDF_TARGET_LINUX) + in_addr->s2_len = sizeof(struct sockaddr_in); +#endif + ss_addr_len = sizeof(struct sockaddr_in); + struct sockaddr_in *in_addr_ip4 = (struct sockaddr_in *) in_addr; + in_addr_ip4->sin_port = port; + in_addr_ip4->sin_addr.s_addr = addr->u_addr.ip4.addr; + } +#if CONFIG_LWIP_IPV6 + else if (ip_protocol == MDNS_IP_PROTOCOL_V6 && addr->type == ESP_IPADDR_TYPE_V6) { + memset(in_addr, 0, sizeof(struct sockaddr_storage)); + in_addr->ss_family = PF_INET6; +#if !defined(CONFIG_IDF_TARGET_LINUX) + in_addr->s2_len = sizeof(struct sockaddr_in6); +#endif + ss_addr_len = sizeof(struct sockaddr_in6); + struct sockaddr_in6 * in_addr_ip6 = (struct sockaddr_in6 *)in_addr; + uint32_t *u32_addr = in_addr_ip6->sin6_addr.s6_addr32; + in_addr_ip6->sin6_port = port; + u32_addr[0] = addr->u_addr.ip6.addr[0]; + u32_addr[1] = addr->u_addr.ip6.addr[1]; + u32_addr[2] = addr->u_addr.ip6.addr[2]; + u32_addr[3] = addr->u_addr.ip6.addr[3]; + } +#endif // CONFIG_LWIP_IPV6 + return ss_addr_len; +} + +size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len) +{ + int sock = pcb_to_sock(_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb); + if (sock < 0) { + return 0; + } + struct sockaddr_storage in_addr; + size_t ss_size = espaddr_to_inet(ip, htons(port), ip_protocol, &in_addr); + if (!ss_size) { + ESP_LOGE(TAG, "espaddr_to_inet() failed: Mismatch of IP protocols"); + return 0; + } + ESP_LOGD(TAG, "[sock=%d]: Sending to IP %s port %d", sock, get_string_address(&in_addr), port); + ssize_t actual_len = sendto(sock, data, len, 0, (struct sockaddr *)&in_addr, ss_size); + if (actual_len < 0) { + ESP_LOGE(TAG, "[sock=%d]: _mdns_udp_pcb_write sendto() has failed\n error=%d: %s", sock, errno, strerror(errno)); + } + return actual_len; +} + +static inline void inet_to_espaddr(const struct sockaddr_storage *in_addr, esp_ip_addr_t *addr, uint16_t *port) +{ + if (in_addr->ss_family == PF_INET) { + struct sockaddr_in * in_addr_ip4 = (struct sockaddr_in *)in_addr; + memset(addr, 0, sizeof(esp_ip_addr_t)); + *port = in_addr_ip4->sin_port; + addr->u_addr.ip4.addr = in_addr_ip4->sin_addr.s_addr; + addr->type = ESP_IPADDR_TYPE_V4; + } +#if CONFIG_LWIP_IPV6 + else if (in_addr->ss_family == PF_INET6) { + struct sockaddr_in6 * in_addr_ip6 = (struct sockaddr_in6 *)in_addr; + memset(addr, 0, sizeof(esp_ip_addr_t)); + *port = in_addr_ip6->sin6_port; + uint32_t *u32_addr = in_addr_ip6->sin6_addr.s6_addr32; + if (u32_addr[0] == 0 && u32_addr[1] == 0 && u32_addr[2] == esp_netif_htonl(0x0000FFFFUL)) { + // Mapped IPv4 address, convert directly to IPv4 + addr->type = ESP_IPADDR_TYPE_V4; + addr->u_addr.ip4.addr = u32_addr[3]; + } else { + addr->type = ESP_IPADDR_TYPE_V6; + addr->u_addr.ip6.addr[0] = u32_addr[0]; + addr->u_addr.ip6.addr[1] = u32_addr[1]; + addr->u_addr.ip6.addr[2] = u32_addr[2]; + addr->u_addr.ip6.addr[3] = u32_addr[3]; + } + } +#endif // CONFIG_LWIP_IPV6 +} + +void sock_recv_task(void* arg) +{ + while (s_run_sock_recv_task) { + struct timeval tv = { + .tv_sec = 1, + .tv_usec = 0, + }; + fd_set rfds; + FD_ZERO(&rfds); + int max_sock = -1; + for (int i=0; iinterfaces[i].pcbs[j].pcb); + if (sock >= 0) { + FD_SET(sock, &rfds); + max_sock = MAX(max_sock, sock); + } + } + } + if (max_sock < 0) { + vTaskDelay(pdMS_TO_TICKS(1000)); + ESP_LOGI(TAG, "No sock!"); + continue; + } + + int s = select(max_sock + 1, &rfds, NULL, NULL, &tv); + if (s < 0) { + ESP_LOGE(TAG, "Select failed: errno %d", errno); + break; + } else if (s > 0) { + for (int tcpip_if=0; tcpip_ifinterfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb); + if (sock < 0) { + sock = pcb_to_sock(_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb); + } + if (sock < 0) { + continue; + } + if (FD_ISSET(sock, &rfds)) { + static char recvbuf[MDNS_MAX_PACKET_SIZE]; + uint16_t port = 0; + + struct sockaddr_storage raddr; // Large enough for both IPv4 or IPv6 + socklen_t socklen = sizeof(struct sockaddr_storage); + esp_ip_addr_t addr = {0}; + int len = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, + (struct sockaddr *) &raddr, &socklen); + if (len < 0) { + ESP_LOGE(TAG, "multicast recvfrom failed: errno %d", errno); + break; + } + ESP_LOGD(TAG, "[sock=%d]: Received from IP:%s", sock, get_string_address(&raddr)); + ESP_LOG_BUFFER_HEXDUMP(TAG, recvbuf, len, ESP_LOG_VERBOSE); + inet_to_espaddr(&raddr, &addr, &port); + + // Allocate the packet structure and pass it to the mdns main engine + mdns_rx_packet_t *packet = (mdns_rx_packet_t *) calloc(1, sizeof(mdns_rx_packet_t)); + struct pbuf *packet_pbuf = calloc(1, sizeof(struct pbuf)); + uint8_t *buf = malloc(len); + if (packet == NULL || packet_pbuf == NULL || buf == NULL ) { + free(buf); + free(packet_pbuf); + free(packet); + HOOK_MALLOC_FAILED; + ESP_LOGE(TAG, "Failed to allocate the mdns packet"); + continue; + } + memcpy(buf, recvbuf, len); + packet_pbuf->next = NULL; + packet_pbuf->payload = buf; + packet_pbuf->tot_len = len; + packet_pbuf->len = len; + packet->tcpip_if = tcpip_if; + packet->pb = packet_pbuf; + packet->src_port = ntohs(port); + memcpy(&packet->src, &addr, sizeof(esp_ip_addr_t)); + // TODO(IDF-3651): Add the correct dest addr -- for mdns to decide multicast/unicast + // Currently it's enough to assume the packet is multicast and mdns to check the source port of the packet + memset(&packet->dest, 0, sizeof(esp_ip_addr_t)); + packet->multicast = 1; + packet->dest.type = packet->src.type; + packet->ip_protocol = + packet->src.type == ESP_IPADDR_TYPE_V4 ? MDNS_IP_PROTOCOL_V4 : MDNS_IP_PROTOCOL_V6; + if (!_mdns_server || !_mdns_server->action_queue || _mdns_send_rx_action(packet) != ESP_OK) { + ESP_LOGE(TAG, "_mdns_send_rx_action failed!"); + free(packet->pb->payload); + free(packet->pb); + free(packet); + } + } + } + } + } + vTaskDelete(NULL); +} + +static void mdns_networking_init(void) +{ + if (s_run_sock_recv_task == false) { + s_run_sock_recv_task = true; + xTaskCreate( sock_recv_task, "mdns recv task", 3*1024, NULL, 5, NULL ); + } +} + +static struct udp_pcb* create_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) { + return _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb; + } + mdns_ip_protocol_t other_ip_proto = ip_protocol==MDNS_IP_PROTOCOL_V4?MDNS_IP_PROTOCOL_V6:MDNS_IP_PROTOCOL_V4; + esp_netif_t *netif = _mdns_get_esp_netif(tcpip_if); + if (_mdns_server->interfaces[tcpip_if].pcbs[other_ip_proto].pcb) { + struct udp_pcb* other_pcb = _mdns_server->interfaces[tcpip_if].pcbs[other_ip_proto].pcb; + int err = join_mdns_multicast_group(pcb_to_sock(other_pcb), netif, ip_protocol); + if (err < 0) { + ESP_LOGE(TAG, "Failed to add ipv6 multicast group for protocol %d", ip_protocol); + return NULL; + } + return other_pcb; + } + int sock = create_socket(netif); + if (sock < 0) { + ESP_LOGE(TAG, "Failed to create the socket!"); + return NULL; + } + int err = join_mdns_multicast_group(sock, netif, ip_protocol); + if (err < 0) { + ESP_LOGE(TAG, "Failed to add ipv6 multicast group for protocol %d", ip_protocol); + } + return sock_to_pcb(sock); +} + +esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + ESP_LOGI(TAG, "_mdns_pcb_init(tcpip_if=%d, ip_protocol=%d)", tcpip_if, ip_protocol); + _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb = create_pcb(tcpip_if, ip_protocol); + _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].failed_probes = 0; + + mdns_networking_init(); + return ESP_OK; +} + +static int create_socket(esp_netif_t *netif) +{ +#if CONFIG_LWIP_IPV6 + int sock = socket(PF_INET6, SOCK_DGRAM, 0); +#else + int sock = socket(PF_INET, SOCK_DGRAM, 0); +#endif + if (sock < 0) { + ESP_LOGE(TAG, "Failed to create socket. Error %d", errno); + return -1; + } + + int on = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) { + ESP_LOGE(TAG, "setsockopt SO_REUSEADDR: %s\n", strerror(errno)); + } + // Bind the socket to any address +#if CONFIG_LWIP_IPV6 + struct sockaddr_in6 saddr = { INADDR_ANY }; + saddr.sin6_family = AF_INET6; + saddr.sin6_port = htons(5353); + bzero(&saddr.sin6_addr.s6_addr, sizeof(saddr.sin6_addr.s6_addr)); + int err = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in6)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to bind socket. Error %d", errno); + goto err; + } +#else + struct sockaddr_in saddr = { 0 }; + saddr.sin_family = AF_INET; + saddr.sin_port = htons(5353); + bzero(&saddr.sin_addr.s_addr, sizeof(saddr.sin_addr.s_addr)); + int err = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to bind socket. Error %d", errno); + goto err; + } +#endif // CONFIG_LWIP_IPV6 + struct ifreq ifr; + esp_netif_get_netif_impl_name(netif, ifr.ifr_name); + int ret = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void*)&ifr, sizeof(struct ifreq)); + if (ret < 0) { + ESP_LOGE(TAG, "\"%s\" Unable to bind socket to specified interface: errno %d", esp_netif_get_desc(netif), errno); + goto err; + } + + return sock; + +err: + close(sock); + return -1; +} + +#if CONFIG_LWIP_IPV6 +static int socket_add_ipv6_multicast_group(int sock, esp_netif_t *netif) +{ + int ifindex = esp_netif_get_netif_impl_index(netif); + int err = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to set IPV6_MULTICAST_IF. Error %d", errno); + return err; + } + + struct ipv6_mreq v6imreq = { 0 }; + esp_ip_addr_t multi_addr = ESP_IP6ADDR_INIT(0x000002ff, 0, 0, 0xfb000000); + memcpy(&v6imreq.ipv6mr_multiaddr, &multi_addr.u_addr.ip6.addr, sizeof(v6imreq.ipv6mr_multiaddr)); + v6imreq.ipv6mr_interface = ifindex; + err = setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &v6imreq, sizeof(struct ipv6_mreq)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to set IPV6_ADD_MEMBERSHIP. Error %d", errno); + return err; + } + return err; +} +#endif // CONFIG_LWIP_IPV6 + +static int socket_add_ipv4_multicast_group(int sock, esp_netif_t *netif) +{ + struct ip_mreq imreq = { 0 }; + int err = 0; + esp_netif_ip_info_t ip_info = { 0 }; + + if (esp_netif_get_ip_info(netif, &ip_info) != ESP_OK) { + ESP_LOGE(TAG, "Failed to esp_netif_get_ip_info()"); + goto err; + } + imreq.imr_interface.s_addr = ip_info.ip.addr; + + esp_ip_addr_t multicast_addr = ESP_IP4ADDR_INIT(224, 0, 0, 251); + imreq.imr_multiaddr.s_addr = multicast_addr.u_addr.ip4.addr; + + err = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imreq, sizeof(struct ip_mreq)); + if (err < 0) { + ESP_LOGE(TAG, "%d %s", sock, strerror(errno)); + ESP_LOGE(TAG, "Failed to set IP_ADD_MEMBERSHIP. Error %d", errno); + goto err; + } + + err: + return err; +} + +static int join_mdns_multicast_group(int sock, esp_netif_t *netif, mdns_ip_protocol_t ip_protocol) +{ + if (ip_protocol == MDNS_IP_PROTOCOL_V4) { + return socket_add_ipv4_multicast_group(sock, netif); + } +#if CONFIG_LWIP_IPV6 + if (ip_protocol == MDNS_IP_PROTOCOL_V6) { + return socket_add_ipv6_multicast_group(sock, netif); + } +#endif // CONFIG_LWIP_IPV6 + return -1; +} diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 6931d4f5a..3d181a1b5 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -248,7 +248,6 @@ typedef struct mdns_parsed_record_s { typedef struct { mdns_if_t tcpip_if; mdns_ip_protocol_t ip_protocol; - //struct udp_pcb *pcb; esp_ip_addr_t src; uint16_t src_port; uint8_t multicast; From 5c55ea6e02a9ffbd6058f110a09ca27b0cf0cd54 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 30 Jun 2021 18:39:29 +0200 Subject: [PATCH 210/289] mdns: Add host test using linux target * Original commit: espressif/esp-idf@fc7e2d9e908f61fb4b852cfae72aa5ff7c662ebc --- components/mdns/CMakeLists.txt | 29 ++- components/mdns/Kconfig | 9 + components/mdns/component.mk | 5 + components/mdns/host_test/CMakeLists.txt | 5 + components/mdns/host_test/README.md | 25 +++ .../components/esp_event_mock/CMakeLists.txt | 3 + .../esp_event_mock/esp_event_mock.c | 29 +++ .../esp_event_mock/include/esp_event.h | 32 +++ .../esp_event_mock/include/esp_event_base.h | 21 ++ .../components/esp_netif_linux/CMakeLists.txt | 3 + .../components/esp_netif_linux/Kconfig | 9 + .../esp_netif_linux/esp_netif_linux.c | 163 +++++++++++++++ .../esp_netif_linux/include/esp_wifi_types.h | 15 ++ .../esp_system_protocols_linux/CMakeLists.txt | 3 + .../esp_system_protocols_linux/esp_log_impl.c | 35 ++++ .../include/bsd_strings.h | 16 ++ .../include/machine/endian.h | 16 ++ .../esp_system_protocols_linux/strlcat.c | 68 +++++++ .../components/esp_timer_linux/CMakeLists.txt | 5 + .../esp_timer_linux/esp_timer_linux.c | 47 +++++ .../esp_timer_linux/include/esp_timer.h | 41 ++++ .../components/esp_timer_linux/timer_task.cpp | 38 ++++ .../components/esp_timer_linux/timer_task.hpp | 61 ++++++ .../components/freertos_linux/CMakeLists.txt | 9 + .../components/freertos_linux/Kconfig | 7 + .../freertos_linux/freertos_linux.c | 192 ++++++++++++++++++ .../freertos_linux/include/esp_task.h | 20 ++ .../include/freertos/FreeRTOS.h | 46 +++++ .../freertos_linux/include/freertos/task.h | 58 ++++++ .../freertos_linux/queue_unique_ptr.cpp | 51 +++++ .../freertos_linux/queue_unique_ptr.hpp | 55 +++++ components/mdns/host_test/main/CMakeLists.txt | 4 + components/mdns/host_test/main/main.c | 59 ++++++ .../mdns/private_include/mdns_private.h | 2 + 34 files changed, 1174 insertions(+), 7 deletions(-) create mode 100644 components/mdns/host_test/CMakeLists.txt create mode 100644 components/mdns/host_test/README.md create mode 100644 components/mdns/host_test/components/esp_event_mock/CMakeLists.txt create mode 100644 components/mdns/host_test/components/esp_event_mock/esp_event_mock.c create mode 100644 components/mdns/host_test/components/esp_event_mock/include/esp_event.h create mode 100644 components/mdns/host_test/components/esp_event_mock/include/esp_event_base.h create mode 100644 components/mdns/host_test/components/esp_netif_linux/CMakeLists.txt create mode 100644 components/mdns/host_test/components/esp_netif_linux/Kconfig create mode 100644 components/mdns/host_test/components/esp_netif_linux/esp_netif_linux.c create mode 100644 components/mdns/host_test/components/esp_netif_linux/include/esp_wifi_types.h create mode 100644 components/mdns/host_test/components/esp_system_protocols_linux/CMakeLists.txt create mode 100644 components/mdns/host_test/components/esp_system_protocols_linux/esp_log_impl.c create mode 100644 components/mdns/host_test/components/esp_system_protocols_linux/include/bsd_strings.h create mode 100644 components/mdns/host_test/components/esp_system_protocols_linux/include/machine/endian.h create mode 100644 components/mdns/host_test/components/esp_system_protocols_linux/strlcat.c create mode 100644 components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt create mode 100644 components/mdns/host_test/components/esp_timer_linux/esp_timer_linux.c create mode 100644 components/mdns/host_test/components/esp_timer_linux/include/esp_timer.h create mode 100644 components/mdns/host_test/components/esp_timer_linux/timer_task.cpp create mode 100644 components/mdns/host_test/components/esp_timer_linux/timer_task.hpp create mode 100644 components/mdns/host_test/components/freertos_linux/CMakeLists.txt create mode 100644 components/mdns/host_test/components/freertos_linux/Kconfig create mode 100644 components/mdns/host_test/components/freertos_linux/freertos_linux.c create mode 100644 components/mdns/host_test/components/freertos_linux/include/esp_task.h create mode 100644 components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h create mode 100644 components/mdns/host_test/components/freertos_linux/include/freertos/task.h create mode 100644 components/mdns/host_test/components/freertos_linux/queue_unique_ptr.cpp create mode 100644 components/mdns/host_test/components/freertos_linux/queue_unique_ptr.hpp create mode 100644 components/mdns/host_test/main/CMakeLists.txt create mode 100644 components/mdns/host_test/main/main.c diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index a8d2cedb3..cb3ed4996 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -1,7 +1,22 @@ -idf_component_register(SRCS "mdns.c" - "mdns_console.c" - "mdns_networking.c" - INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "private_include" - REQUIRES lwip console esp_netif - PRIV_REQUIRES esp_timer) +if(CONFIG_MDNS_NETWORKING_SOCKET) + set(MDNS_NETWORKING "mdns_networking_socket.c") +else() + set(MDNS_NETWORKING "mdns_networking_lwip.c") +endif() + +idf_build_get_property(target IDF_TARGET) +if(${target} STREQUAL "linux") + set(dependencies esp_system_protocols_linux) + set(srcs "mdns.c" ${MDNS_NETWORKING}) +else() + set(dependencies lwip console esp_netif) + set(private_dependencies esp_timer) + set(srcs "mdns.c" ${MDNS_NETWORKING} "mdns_console.c") +endif() + +idf_component_register( + SRCS ${srcs} + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "private_include" + REQUIRES ${dependencies} + PRIV_REQUIRES ${private_dependencies}) diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig index 38dec7628..b49ae703c 100644 --- a/components/mdns/Kconfig +++ b/components/mdns/Kconfig @@ -75,4 +75,13 @@ menu "mDNS" Configures period of mDNS timer, which periodically transmits packets and schedules mDNS searches. + config MDNS_NETWORKING_SOCKET + bool "Use BSD sockets for mdns networking" + default n + help + Enables optional mdns networking implementation using BSD sockets + in UDP multicast mode. + This option creates a new thread to serve receiving packets (TODO). + This option uses additional N sockets, where N is number of interfaces. + endmenu diff --git a/components/mdns/component.mk b/components/mdns/component.mk index 064cc0608..f22f83094 100644 --- a/components/mdns/component.mk +++ b/components/mdns/component.mk @@ -1,2 +1,7 @@ +ifdef CONFIG_MDNS_NETWORKING_SOCKET +COMPONENT_OBJEXCLUDE := mdns_networking_lwip.o +else +COMPONENT_OBJEXCLUDE := mdns_networking_socket.o +endif COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_PRIV_INCLUDEDIRS := private_include diff --git a/components/mdns/host_test/CMakeLists.txt b/components/mdns/host_test/CMakeLists.txt new file mode 100644 index 000000000..132e436ea --- /dev/null +++ b/components/mdns/host_test/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) +project(mdns_host) diff --git a/components/mdns/host_test/README.md b/components/mdns/host_test/README.md new file mode 100644 index 000000000..ab916520d --- /dev/null +++ b/components/mdns/host_test/README.md @@ -0,0 +1,25 @@ +# Setup dummy network interfaces +``` +sudo ip link add eth2 type dummy +sudo ip addr add 192.168.1.200/24 dev eth2 +sudo ip link set eth2 up +sudo ifconfig eth2 multicast +``` + +# Dig on a specified interface + +``` +dig +short -b 192.168.1.200 -p 5353 @224.0.0.251 myesp.local +``` + +# Run avahi to browse services + +Avahi needs the netif to have the "multicast" flag set + +```bash +david@david-comp:~/esp/idf (feature/mdns_networking_socket)$ avahi-browse -a -r -p ++;eth2;IPv6;myesp-service2;Web Site;local ++;eth2;IPv4;myesp-service2;Web Site;local +=;eth2;IPv6;myesp-service2;Web Site;local;myesp.local;192.168.1.200;80;"board=esp32" "u=user" "p=password" +=;eth2;IPv4;myesp-service2;Web Site;local;myesp.local;192.168.1.200;80;"board=esp32" "u=user" "p=password" +``` diff --git a/components/mdns/host_test/components/esp_event_mock/CMakeLists.txt b/components/mdns/host_test/components/esp_event_mock/CMakeLists.txt new file mode 100644 index 000000000..606c16f80 --- /dev/null +++ b/components/mdns/host_test/components/esp_event_mock/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS esp_event_mock.c + INCLUDE_DIRS include + REQUIRES esp_system_protocols_linux) diff --git a/components/mdns/host_test/components/esp_event_mock/esp_event_mock.c b/components/mdns/host_test/components/esp_event_mock/esp_event_mock.c new file mode 100644 index 000000000..cd6b079b3 --- /dev/null +++ b/components/mdns/host_test/components/esp_event_mock/esp_event_mock.c @@ -0,0 +1,29 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_err.h" +#include "esp_event.h" + +const char * WIFI_EVENT = "WIFI_EVENT"; +const char * IP_EVENT = "IP_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; +} diff --git a/components/mdns/host_test/components/esp_event_mock/include/esp_event.h b/components/mdns/host_test/components/esp_event_mock/include/esp_event.h new file mode 100644 index 000000000..18801e4b9 --- /dev/null +++ b/components/mdns/host_test/components/esp_event_mock/include/esp_event.h @@ -0,0 +1,32 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include "stdbool.h" +#include "esp_err.h" +#include "esp_event_base.h" +#include "bsd_strings.h" + +#define ESP_EVENT_DECLARE_BASE(x) +#define ESP_EVENT_ANY_ID (-1) + +typedef void * esp_event_base_t; +typedef void * system_event_t; + +const char* WIFI_EVENT; +const char* IP_EVENT; + +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); diff --git a/components/mdns/host_test/components/esp_event_mock/include/esp_event_base.h b/components/mdns/host_test/components/esp_event_mock/include/esp_event_base.h new file mode 100644 index 000000000..740b71270 --- /dev/null +++ b/components/mdns/host_test/components/esp_event_mock/include/esp_event_base.h @@ -0,0 +1,21 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +typedef enum { + WIFI_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */ + WIFI_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */ + WIFI_EVENT_AP_START, /**< ESP32 soft-AP start */ + WIFI_EVENT_AP_STOP, /**< ESP32 soft-AP stop */ +} mdns_used_event_t; diff --git a/components/mdns/host_test/components/esp_netif_linux/CMakeLists.txt b/components/mdns/host_test/components/esp_netif_linux/CMakeLists.txt new file mode 100644 index 000000000..086034b08 --- /dev/null +++ b/components/mdns/host_test/components/esp_netif_linux/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS esp_netif_linux.c + INCLUDE_DIRS include + REQUIRES esp_system_protocols_linux) diff --git a/components/mdns/host_test/components/esp_netif_linux/Kconfig b/components/mdns/host_test/components/esp_netif_linux/Kconfig new file mode 100644 index 000000000..c903f7ca5 --- /dev/null +++ b/components/mdns/host_test/components/esp_netif_linux/Kconfig @@ -0,0 +1,9 @@ +menu "LWIP-MOCK-CONFIG" + + config LWIP_IPV6 + bool "Enable IPv6" + default true + help + Enable/disable IPv6 + +endmenu diff --git a/components/mdns/host_test/components/esp_netif_linux/esp_netif_linux.c b/components/mdns/host_test/components/esp_netif_linux/esp_netif_linux.c new file mode 100644 index 000000000..bbde59073 --- /dev/null +++ b/components/mdns/host_test/components/esp_netif_linux/esp_netif_linux.c @@ -0,0 +1,163 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include + +#include "esp_netif.h" +#include "esp_err.h" +#include //strlen +#include +#include //inet_addr +#include +#include +#include +#include "esp_netif_types.h" + +#define MAX_NETIFS 4 + +static esp_netif_t* s_netif_list[MAX_NETIFS] = { 0 }; + +struct esp_netif_obj +{ + const char *if_key; + const char *if_desc; +}; + +esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key) +{ + for (int i=0; iif_key, if_key) == 0) { + return s_netif_list[i]; + } + } + return NULL; +} + +esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) +{ + if (esp_netif == NULL) { + return ESP_ERR_INVALID_STATE; + } + struct ifaddrs *addrs, *tmp; + getifaddrs(&addrs); + tmp = addrs; + + while (tmp) { + if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET) { + char addr[20]; + 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) { + printf("AF_INET: %s: %s\n", tmp->ifa_name, addr); + memcpy(&ip_info->ip.addr, &pAddr->sin_addr, 4); + break; + } + } + tmp = tmp->ifa_next; + } + return ESP_OK; +} + +esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) +{ + return ESP_OK; +} + + +esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6) +{ + if (esp_netif == NULL) { + return ESP_ERR_INVALID_STATE; + } + struct ifaddrs *addrs, *tmp; + getifaddrs(&addrs); + tmp = addrs; + + while (tmp) + { + if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET6) { + char addr[64]; + struct sockaddr_in6 *pAddr = (struct sockaddr_in6 *)tmp->ifa_addr; + inet_ntop(AF_INET6, &pAddr->sin6_addr, addr, sizeof(addr) ); + if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) { + printf("AF_INET6: %s: %s\n", tmp->ifa_name, addr); + memcpy(if_ip6->addr, &pAddr->sin6_addr, 4*4); + break; + } + } + tmp = tmp->ifa_next; + } + + freeifaddrs(addrs); + return ESP_OK; +} + + +int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif) +{ + if (esp_netif == NULL) { + return -1; + } + uint32_t interfaceIndex = if_nametoindex(esp_netif->if_desc); + return interfaceIndex; +} + +esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name) +{ + if (esp_netif == NULL) { + return ESP_ERR_INVALID_STATE; + } + strcpy(name, esp_netif->if_desc); + return ESP_OK; +} + +const char *esp_netif_get_desc(esp_netif_t *esp_netif) +{ + if (esp_netif == NULL) { + return NULL; + } + return esp_netif->if_desc; +} + +esp_netif_t *esp_netif_new(const esp_netif_config_t *config) +{ + if (esp_netif_get_handle_from_ifkey(config->base->if_key)) { + return NULL; + } + esp_netif_t* netif = calloc(1, sizeof(struct esp_netif_obj)); + if (netif) { + netif->if_desc = config->base->if_desc; + netif->if_key = config->base->if_key; + } + + for (int i=0; i + +void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) +{ + ESP_LOGE("ESP_ERROR_CHECK", "Failed with esp_err_t: 0x%x", rc); + ESP_LOGE("ESP_ERROR_CHECK", "Expression: %s", expression); + ESP_LOGE("ESP_ERROR_CHECK", "Functions: %s %s(%d)", function, file, line); + abort(); +} + +void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level) +{ + if ( LOG_LOCAL_LEVEL >= log_level ) { + ESP_LOG_LEVEL(log_level, tag, "Buffer:%p length:%d", buffer, buff_len); + for (int i=0; i + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "string.h" + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(dst, src, siz) + char *dst; + const char *src; + size_t siz; +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} diff --git a/components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt b/components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt new file mode 100644 index 000000000..0c598a2e6 --- /dev/null +++ b/components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register(SRCS esp_timer_linux.c timer_task.cpp + INCLUDE_DIRS include + REQUIRES esp_system_protocols_linux freertos_linux) + +target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17) diff --git a/components/mdns/host_test/components/esp_timer_linux/esp_timer_linux.c b/components/mdns/host_test/components/esp_timer_linux/esp_timer_linux.c new file mode 100644 index 000000000..bb2326985 --- /dev/null +++ b/components/mdns/host_test/components/esp_timer_linux/esp_timer_linux.c @@ -0,0 +1,47 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "esp_err.h" +#include "esp_timer.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +void * create_tt(esp_timer_cb_t cb); + +void destroy_tt(void* tt); + +void set_tout(void* tt, uint32_t ms); + +esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, + esp_timer_handle_t* out_handle) +{ + *out_handle = (esp_timer_handle_t)create_tt(create_args->callback); + return ESP_OK; +} + +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) +{ + set_tout(timer, period/1000); + return ESP_OK; +} + +esp_err_t esp_timer_stop(esp_timer_handle_t timer) +{ + return ESP_OK; +} + +esp_err_t esp_timer_delete(esp_timer_handle_t timer) +{ + destroy_tt(timer); + return ESP_OK; +} diff --git a/components/mdns/host_test/components/esp_timer_linux/include/esp_timer.h b/components/mdns/host_test/components/esp_timer_linux/include/esp_timer.h new file mode 100644 index 000000000..669163049 --- /dev/null +++ b/components/mdns/host_test/components/esp_timer_linux/include/esp_timer.h @@ -0,0 +1,41 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include + +typedef struct esp_timer* esp_timer_handle_t; + +typedef void (*esp_timer_cb_t)(void* arg); + +typedef enum { + ESP_TIMER_TASK, +} esp_timer_dispatch_t; + +typedef struct { + esp_timer_cb_t callback; //!< Function to call when timer expires + void* arg; //!< Argument to pass to the callback + esp_timer_dispatch_t dispatch_method; //!< Call the callback from task or from ISR + const char* name; //!< Timer name, used in esp_timer_dump function + bool skip_unhandled_events; //!< Skip unhandled events for periodic timers +} esp_timer_create_args_t; + +esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, + esp_timer_handle_t* out_handle); +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period); + +esp_err_t esp_timer_stop(esp_timer_handle_t timer); + +esp_err_t esp_timer_delete(esp_timer_handle_t timer); diff --git a/components/mdns/host_test/components/esp_timer_linux/timer_task.cpp b/components/mdns/host_test/components/esp_timer_linux/timer_task.cpp new file mode 100644 index 000000000..bd971b3f0 --- /dev/null +++ b/components/mdns/host_test/components/esp_timer_linux/timer_task.cpp @@ -0,0 +1,38 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "timer_task.hpp" +#include +#include +#include +#include + +extern "C" void * create_tt(cb_t cb) +{ + auto * tt = new TimerTaskMock(cb); + return tt; +} + +extern "C" void destroy_tt(void* tt) +{ + auto * timer_task = static_cast(tt); + delete(timer_task); +} + + +extern "C" void set_tout(void* tt, uint32_t ms) +{ + auto * timer_task = static_cast(tt); + timer_task->SetTimeout(ms); +} diff --git a/components/mdns/host_test/components/esp_timer_linux/timer_task.hpp b/components/mdns/host_test/components/esp_timer_linux/timer_task.hpp new file mode 100644 index 000000000..8d32a6bd0 --- /dev/null +++ b/components/mdns/host_test/components/esp_timer_linux/timer_task.hpp @@ -0,0 +1,61 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include +#include +#include +#include +#include + +typedef void (*cb_t)(void* arg); + +class TimerTaskMock +{ +public: + TimerTaskMock(cb_t cb): cb(cb), t(run_static, this), active(false), ms(INT32_MAX) {} + ~TimerTaskMock(void) { active = false; t.join(); } + + void SetTimeout(uint32_t m) + { + ms = m; + active = true; + } + +private: + + static void run_static(TimerTaskMock* timer) + { + timer->run(); + } + + void run(void) + { + while (!active.load()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + while (active.load()) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + cb(nullptr); + } + } + + cb_t cb; + std::thread t; + std::atomic active; + uint32_t ms; + +}; diff --git a/components/mdns/host_test/components/freertos_linux/CMakeLists.txt b/components/mdns/host_test/components/freertos_linux/CMakeLists.txt new file mode 100644 index 000000000..7a84af21a --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/CMakeLists.txt @@ -0,0 +1,9 @@ +idf_component_register(SRCS freertos_linux.c queue_unique_ptr.cpp + INCLUDE_DIRS include + REQUIRES esp_system_protocols_linux) + +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) +target_link_libraries(${COMPONENT_LIB} PRIVATE Threads::Threads) + +target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17) diff --git a/components/mdns/host_test/components/freertos_linux/Kconfig b/components/mdns/host_test/components/freertos_linux/Kconfig new file mode 100644 index 000000000..fa57dab7e --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/Kconfig @@ -0,0 +1,7 @@ +menu "FreeRTOS" + + config FREERTOS_NO_AFFINITY + hex + default 0x7FFFFFFF + +endmenu diff --git a/components/mdns/host_test/components/freertos_linux/freertos_linux.c b/components/mdns/host_test/components/freertos_linux/freertos_linux.c new file mode 100644 index 000000000..763364504 --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/freertos_linux.c @@ -0,0 +1,192 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include +#include +#include +#include + +void * create_q(void); + +void destroy_q(void* q); + +bool send_q(void* q, uint8_t *data, size_t len); + +bool recv_q(void* q, uint8_t *data, size_t len, uint32_t ms); + +static uint64_t s_semaphore_data = 0; + +struct queue_handle { + size_t item_size; + void * q; +}; + +QueueHandle_t xQueueCreate( uint32_t uxQueueLength, uint32_t uxItemSize ) +{ + struct queue_handle * h = calloc(1, sizeof(struct queue_handle)); + h->item_size = uxItemSize; + h->q = create_q(); + return (QueueHandle_t)h; +} + +uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait) +{ + struct queue_handle * h = xQueue; + return send_q(h->q, (uint8_t*)pvItemToQueue, h->item_size) ? pdTRUE : pdFAIL; +} + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait) +{ + struct queue_handle * h = xQueue; + return recv_q(h->q, (uint8_t*)pvBuffer, h->item_size, xTicksToWait) ? pdTRUE : pdFAIL; +} + +BaseType_t xSemaphoreGive( QueueHandle_t xQueue) +{ + return xQueueSend(xQueue, &s_semaphore_data, portMAX_DELAY); +} + +BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask ) +{ + return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY); +} + +void vQueueDelete( QueueHandle_t xQueue ) +{ + struct queue_handle * h = xQueue; + if (h->q) { + destroy_q(h->q); + } + free(xQueue); +} + +QueueHandle_t xSemaphoreCreateBinary(void) +{ + QueueHandle_t sempaphore = xQueueCreate(1, 1); + return sempaphore; +} + +QueueHandle_t xSemaphoreCreateMutex(void) +{ + QueueHandle_t sempaphore = xQueueCreate(1, 1); + if (sempaphore) { + xSemaphoreGive(sempaphore); + } + return sempaphore; +} + +void vTaskDelete(TaskHandle_t *task) +{ + if (task == NULL) { + pthread_exit(0); + } + void *thread_rval = NULL; + pthread_join((pthread_t)task, &thread_rval); +} + +TickType_t xTaskGetTickCount( void ) +{ + struct timespec spec; + clock_gettime(CLOCK_REALTIME, &spec); + return spec.tv_nsec / 1000000 + spec.tv_sec * 1000; +} + +void vTaskDelay( const TickType_t xTicksToDelay ) +{ + usleep(xTicksToDelay*1000); +} + +void * pthread_task(void * 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->started = true; + + task(param); + + return NULL; +} + +BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, + const char * const pcName, + const uint32_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pvCreatedTask, + const BaseType_t xCoreID) +{ + xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask); + return pdTRUE; +} + + +void 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}; + 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); + } +} + +uint32_t esp_get_free_heap_size(void) +{ + return 0; +} + +uint32_t esp_random(void) +{ + return rand(); +} + +void xTaskNotifyGive(TaskHandle_t task) +{ + +} + +BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time ) +{ + return true; +} + +TaskHandle_t xTaskGetCurrentTaskHandle(void) +{ + return NULL; +} diff --git a/components/mdns/host_test/components/freertos_linux/include/esp_task.h b/components/mdns/host_test/components/freertos_linux/include/esp_task.h new file mode 100644 index 000000000..797b416b6 --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/include/esp_task.h @@ -0,0 +1,20 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#define ESP_TASK_PRIO_MAX 25 +#define ESP_TASKD_EVENT_PRIO 5 diff --git a/components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h b/components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h new file mode 100644 index 000000000..ca13d0463 --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h @@ -0,0 +1,46 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include +#include +#include + +#define portTICK_PERIOD_MS 1 +#define portMAX_DELAY ( TickType_t ) 0xffffffffUL + +typedef void * xSemaphoreHandle; +typedef void * SemaphoreHandle_t; +typedef void * xQueueHandle; +typedef void * QueueHandle_t; +typedef void * TaskHandle_t; +typedef uint32_t TickType_t; +typedef uint32_t portTickType; + +typedef void (*TaskFunction_t)( void * ); +typedef unsigned int UBaseType_t; +typedef int BaseType_t; + +#define pdFALSE ( ( BaseType_t ) 0 ) +#define pdTRUE ( ( BaseType_t ) 1 ) + +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) + +#define portTICK_RATE_MS portTICK_PERIOD_MS +#define pdMS_TO_TICKS(tick) (tick) + +uint32_t esp_get_free_heap_size(void); +uint32_t esp_random(void); diff --git a/components/mdns/host_test/components/freertos_linux/include/freertos/task.h b/components/mdns/host_test/components/freertos_linux/include/freertos/task.h new file mode 100644 index 000000000..f6c213ed4 --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/include/freertos/task.h @@ -0,0 +1,58 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include "freertos/FreeRTOS.h" + +#define xTaskHandle TaskHandle_t +#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) + +void vTaskDelay( const TickType_t xTicksToDelay ); + +void xTaskNotifyGive(TaskHandle_t task); + +TaskHandle_t xTaskGetCurrentTaskHandle(void); + +BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time ); + +BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, + const char * const pcName, + const uint32_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pvCreatedTask, + const BaseType_t xCoreID); + +void xTaskCreate(TaskFunction_t pvTaskCode, const char * const pcName, const uint32_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pvCreatedTask); + +TickType_t xTaskGetTickCount( void ); + +void vQueueDelete( QueueHandle_t xQueue ); + +QueueHandle_t xSemaphoreCreateBinary(void); + +QueueHandle_t xSemaphoreCreateMutex(void); + +BaseType_t xSemaphoreGive( QueueHandle_t xQueue); + +BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask ); + +void vTaskDelete(TaskHandle_t *task); + +QueueHandle_t xQueueCreate( uint32_t uxQueueLength, + uint32_t uxItemSize ); + +uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait); + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); diff --git a/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.cpp b/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.cpp new file mode 100644 index 000000000..60c4a8a28 --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.cpp @@ -0,0 +1,51 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "queue_unique_ptr.hpp" +#include +#include +#include +#include + +extern "C" void * create_q(void) +{ + auto * q = new QueueMock>(); + return q; +} + +extern "C" void destroy_q(void* q) +{ + auto * queue = static_cast> *>(q); + delete(queue); +} + +extern "C" bool send_q(void* q, uint8_t *data, size_t len) +{ + auto v = std::make_unique>(len); + v->assign(data, data+len); + auto queue = static_cast> *>(q); + queue->send(std::move(v)); + return true; +} + +extern "C" bool recv_q(void* q, uint8_t *data, size_t len, uint32_t ms) +{ + auto queue = static_cast> *>(q); + auto v = queue->receive(ms); + if (v == nullptr) { + return false; + } + memcpy(data, (void *)v->data(), len); + return true; +} diff --git a/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.hpp b/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.hpp new file mode 100644 index 000000000..fe722b97f --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.hpp @@ -0,0 +1,55 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include +#include +#include + +template +class QueueMock +{ +public: + QueueMock(void): q(), m(), c() {} + ~QueueMock(void) {} + +void send(std::unique_ptr t) +{ + std::lock_guard lock(m); + q.push(std::move(t)); + c.notify_one(); +} + +std::unique_ptr receive(uint32_t ms) +{ + std::unique_lock lock(m); + while(q.empty()) { + if (c.wait_for(lock, std::chrono::milliseconds(ms)) == std::cv_status::timeout) { + return nullptr; + } + } + std::unique_ptr val = std::move(q.front()); + q.pop(); + return val; +} + +private: + std::queue> q; + mutable std::mutex m; + std::condition_variable c; +}; diff --git a/components/mdns/host_test/main/CMakeLists.txt b/components/mdns/host_test/main/CMakeLists.txt new file mode 100644 index 000000000..8d5202d64 --- /dev/null +++ b/components/mdns/host_test/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS + "." + REQUIRES mdns) diff --git a/components/mdns/host_test/main/main.c b/components/mdns/host_test/main/main.c new file mode 100644 index 000000000..f3883b8c3 --- /dev/null +++ b/components/mdns/host_test/main/main.c @@ -0,0 +1,59 @@ +#include +#include "mdns.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +static const char *TAG = "mdns-test"; + +static void query_mdns_host(const char * host_name) +{ + ESP_LOGI(TAG, "Query A: %s.local", host_name); + + struct esp_ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(host_name, 2000, &addr); + if(err){ + if(err == ESP_ERR_NOT_FOUND){ + ESP_LOGW(TAG, "%x: Host was not found!", (err)); + return; + } + ESP_LOGE(TAG, "Query Failed: %x", (err)); + return; + } + + ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr)); +} + +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 = "eth2" }; + esp_netif_config_t cfg = { .base = &base_cg }; + esp_netif_t *sta = esp_netif_new(&cfg); + + mdns_init(); + + mdns_hostname_set("myesp"); + ESP_LOGI(TAG, "mdns hostname set to: [%s]", "myesp"); + //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"} + }; + vTaskDelay(1000); + ESP_ERROR_CHECK(mdns_service_add("myesp-service2", "_http", "_tcp", 80, serviceTxtData, 3)); + vTaskDelay(2000); + + query_mdns_host("david-comp"); + vTaskDelay(2000); + esp_netif_destroy(sta); + mdns_free(); + ESP_LOGI(TAG, "Exit"); + return 0; +} diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 3d181a1b5..5e6deeab5 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -14,8 +14,10 @@ #ifndef MDNS_PRIVATE_H_ #define MDNS_PRIVATE_H_ +#include "sdkconfig.h" #include "mdns.h" #include "esp_task.h" +#include "esp_timer.h" //#define MDNS_ENABLE_DEBUG From 05dcd8f0eeecdbd6f71fc612ced8a4083d4b1066 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sun, 15 Aug 2021 21:58:42 +0500 Subject: [PATCH 211/289] examples/protocols: fix compilation when CONFIG_EXAMPLE_USE_OPENETH=y The code checked CONFIG_ETH_USE_SPI_ETHERNET (which is usually set), but CONFIG_EXAMPLE_ETH_SPI_xxx_GPIO options are only defined if CONFIG_EXAMPLE_USE_SPI_ETHERNET is set. Fix the ifdef accordingly. Regression from abc79de6. * Original commit: espressif/esp-idf@ece73a3e55f482ec9033f94281726a953d83b040 --- examples/common_components/protocol_examples_common/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index d1063b43a..3bf58549a 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -398,7 +398,7 @@ static esp_netif_t *eth_start(void) #elif CONFIG_EXAMPLE_ETH_PHY_DP83848 s_phy = esp_eth_phy_new_dp83848(&phy_config); #endif -#elif CONFIG_ETH_USE_SPI_ETHERNET +#elif CONFIG_EXAMPLE_USE_SPI_ETHERNET gpio_install_isr_service(0); spi_device_handle_t spi_handle = NULL; spi_bus_config_t buscfg = { From d37ab6dd25bd7b4d352f2dbad36e9f73ae400731 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Wed, 21 Apr 2021 15:34:22 +0800 Subject: [PATCH 212/289] mdns: add more mdns result attributes * Original commit: espressif/esp-idf@76ec76c12c871554147343bb7141da1e5de58011 --- components/mdns/include/mdns.h | 3 + components/mdns/mdns.c | 75 ++++++++++++++----- .../protocols/mdns/main/mdns_example_main.c | 30 ++++---- 3 files changed, 75 insertions(+), 33 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 7089eabe6..721592fbc 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -75,10 +75,13 @@ typedef struct mdns_result_s { struct mdns_result_s * next; /*!< next result, or NULL for the last result in the list */ mdns_if_t tcpip_if; /*!< interface index */ + uint32_t ttl; /*!< time to live */ mdns_ip_protocol_t ip_protocol; /*!< ip_protocol type of the interface (v4/v6) */ // PTR char * instance_name; /*!< instance name */ + char * service_type; /*!< service type */ + char * proto; /*!< srevice protocol */ // SRV char * hostname; /*!< hostname */ uint16_t port; /*!< service port */ diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 508672d30..5c03d91e1 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -41,10 +41,16 @@ static SemaphoreHandle_t _mdns_service_semaphore = NULL; static void _mdns_search_finish_done(void); static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * search, mdns_name_t * name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, esp_ip_addr_t * ip, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, esp_ip_addr_t * ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); +static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); +static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, + size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl); +static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, + const char * service_type, const char * proto, mdns_if_t tcpip_if, + mdns_ip_protocol_t ip_protocol, uint32_t ttl); static bool _mdns_append_host_list_in_services(mdns_out_answer_t ** destination, mdns_srv_item_t * services[], size_t services_len, bool flush, bool bye); static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye); static void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); @@ -3162,7 +3168,8 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) continue;//error } if (search_result) { - _mdns_search_result_add_ptr(search_result, name->host, packet->tcpip_if, packet->ip_protocol); + _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { if (discovery) { service = _mdns_get_service_item(name->service, name->proto, NULL); @@ -3189,7 +3196,8 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) result = result->next; } if (!result) { - result = _mdns_search_result_add_ptr(search_result, name->host, packet->tcpip_if, packet->ip_protocol); + result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); if (!result) { continue;//error } @@ -3210,7 +3218,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) result->hostname = strdup(name->host); } } else { - _mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol); + _mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol, ttl); } } else if (ours) { if (parsed_packet->questions && !parsed_packet->probe) { @@ -3285,7 +3293,8 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) result = result->next; } if (!result) { - result = _mdns_search_result_add_ptr(search_result, name->host, packet->tcpip_if, packet->ip_protocol); + result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); if (!result) { continue;//error } @@ -3301,7 +3310,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } else { _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); if (txt_count) { - _mdns_search_result_add_txt(search_result, txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol); + _mdns_search_result_add_txt(search_result, txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, ttl); } } } else if (ours) { @@ -3335,7 +3344,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) if (search_result) { //check for more applicable searches (PTR & A/AAAA at the same time) while (search_result) { - _mdns_search_result_add_ip(search_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol); + _mdns_search_result_add_ip(search_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, ttl); search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); } } else if (ours) { @@ -3385,7 +3394,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) if (search_result) { //check for more applicable searches (PTR & A/AAAA at the same time) while (search_result) { - _mdns_search_result_add_ip(search_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol); + _mdns_search_result_add_ip(search_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, ttl); search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); } } else if (ours) { @@ -3699,6 +3708,11 @@ static mdns_ip_addr_t * _mdns_result_addr_create_ip(esp_ip_addr_t * ip) return a; } +static inline void _mdns_result_update_ttl(mdns_result_t * r, uint32_t ttl) +{ + r->ttl = r->ttl < ttl ? r->ttl : ttl; +} + /** * @brief Chain new IP to search result */ @@ -3727,7 +3741,8 @@ static void _mdns_result_add_ip(mdns_result_t * r, esp_ip_addr_t * ip) /** * @brief Called from parser to add A/AAAA data to search result */ -static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, esp_ip_addr_t * ip, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, esp_ip_addr_t * ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) { mdns_result_t * r = NULL; mdns_ip_addr_t * a = NULL; @@ -3739,6 +3754,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * while (r) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol) { _mdns_result_add_ip(r, ip); + _mdns_result_update_ttl(r, ttl); return; } r = r->next; @@ -3758,18 +3774,21 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * return; } a->next = r->addr; + r->hostname = strdup(hostname); r->addr = a; r->tcpip_if = tcpip_if; r->ip_protocol = ip_protocol; r->next = search->result; + r->ttl = ttl; search->result = r; search->num_results++; } - } else if (search->type == MDNS_TYPE_PTR) { + } else if (search->type == MDNS_TYPE_PTR || search->type == MDNS_TYPE_SRV) { r = search->result; while (r) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { _mdns_result_add_ip(r, ip); + _mdns_result_update_ttl(r, ttl); break; } r = r->next; @@ -3780,11 +3799,14 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * /** * @brief Called from parser to add PTR data to search result */ -static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, + const char * service_type, const char * proto, mdns_if_t tcpip_if, + mdns_ip_protocol_t ip_protocol, uint32_t ttl) { mdns_result_t * r = search->result; while (r) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { + _mdns_result_update_ttl(r, ttl); return r; } r = r->next; @@ -3798,6 +3820,8 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, memset(r, 0 , sizeof(mdns_result_t)); r->instance_name = strdup(instance); + r->service_type = strdup(service_type); + r->proto = strdup(proto); if (!r->instance_name) { free(r); return NULL; @@ -3805,6 +3829,7 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, r->tcpip_if = tcpip_if; r->ip_protocol = ip_protocol; + r->ttl = ttl; r->next = search->result; search->result = r; search->num_results++; @@ -3816,11 +3841,13 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, /** * @brief Called from parser to add SRV data to search result */ -static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) { mdns_result_t * r = search->result; while (r) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + _mdns_result_update_ttl(r, ttl); return; } r = r->next; @@ -3838,9 +3865,15 @@ static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char free(r); return; } + if (search->instance) { + r->instance_name = strdup(search->instance); + } + r->service_type = strdup(search->service); + r->proto = strdup(search->proto); r->port = port; r->tcpip_if = tcpip_if; r->ip_protocol = ip_protocol; + r->ttl = ttl; r->next = search->result; search->result = r; search->num_results++; @@ -3850,7 +3883,9 @@ static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char /** * @brief Called from parser to add TXT data to search result */ -static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, + size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl) { mdns_result_t * r = search->result; while (r) { @@ -3861,6 +3896,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it r->txt = txt; r->txt_value_len = txt_value_len; r->txt_count = txt_count; + _mdns_result_update_ttl(r, ttl); return; } r = r->next; @@ -3878,6 +3914,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it r->txt_count = txt_count; r->tcpip_if = tcpip_if; r->ip_protocol = ip_protocol; + r->ttl = ttl; r->next = search->result; search->result = r; search->num_results++; @@ -3906,12 +3943,12 @@ static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * s, mdns_ if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { if ((s->type == MDNS_TYPE_ANY && s->service != NULL) - || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR)) + || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV)) { s = s->next; continue; } - if (s->type != MDNS_TYPE_PTR) { + if (s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV) { if (!strcasecmp(name->host, s->instance)) { return s; } @@ -5266,6 +5303,8 @@ void mdns_query_results_free(mdns_result_t * results) free((char *)(r->hostname)); free((char *)(r->instance_name)); + free((char *)(r->service_type)); + free((char *)(r->proto)); for (size_t i=0; itxt_count; i++) { free((char *)(r->txt[i].key)); diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index fc5b45037..b0a669d14 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -85,29 +85,30 @@ static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; /* these strings match mdns_ip_protocol_t enumeration */ static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; -static void mdns_print_results(mdns_result_t * results){ - mdns_result_t * r = results; - mdns_ip_addr_t * a = NULL; +static void mdns_print_results(mdns_result_t *results) +{ + mdns_result_t *r = results; + mdns_ip_addr_t *a = NULL; int i = 1, t; - while(r){ - printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]); - if(r->instance_name){ - printf(" PTR : %s\n", r->instance_name); + while (r) { + printf("%d: Interface: %s, Type: %s, TTL: %u\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol], + r->ttl); + if (r->instance_name) { + printf(" PTR : %s.%s.%s\n", r->instance_name, r->service_type, r->proto); } - if(r->hostname){ + if (r->hostname) { printf(" SRV : %s.local:%u\n", r->hostname, r->port); } - if(r->txt_count){ + if (r->txt_count) { printf(" TXT : [%zu] ", r->txt_count); - for(t=0; ttxt_count; t++){ - printf("%s=%s(%d); ", r->txt[t].key, r->txt[t].value?r->txt[t].value:"NULL", - r->txt_value_len[t]); + for (t = 0; t < r->txt_count; t++) { + printf("%s=%s(%d); ", r->txt[t].key, r->txt[t].value ? r->txt[t].value : "NULL", r->txt_value_len[t]); } printf("\n"); } a = r->addr; - while(a){ - if(a->addr.type == ESP_IPADDR_TYPE_V6){ + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); } else { printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); @@ -116,7 +117,6 @@ static void mdns_print_results(mdns_result_t * results){ } r = r->next; } - } static void query_mdns_service(const char * service_name, const char * proto) From 52306e914f308ed085aac2e6824c3f041041eaf1 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Thu, 5 Aug 2021 16:59:04 +0800 Subject: [PATCH 213/289] mdns: add notification callback for async APIs * Original commit: espressif/esp-idf@986603cf07413b46c88c76c324bf500edcfb6171 --- components/mdns/include/mdns.h | 6 +++++- components/mdns/mdns.c | 14 ++++++++++---- components/mdns/private_include/mdns_private.h | 1 + components/mdns/test_afl_fuzz_host/mdns_di.h | 9 ++++++--- examples/protocols/mdns/main/mdns_example_main.c | 4 ++-- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 721592fbc..4bb288d41 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -93,6 +93,8 @@ typedef struct mdns_result_s { mdns_ip_addr_t * addr; /*!< linked list of IP addresses found */ } mdns_result_t; +typedef void (*mdns_query_notify_t)(mdns_search_once_t *search); + /** * @brief Initialize mDNS on given interface * @@ -522,11 +524,13 @@ bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, * @param type type of query (MDNS_TYPE_*) * @param timeout time in milliseconds during which mDNS query is active * @param max_results maximum results to be collected + * @param notifier Notification function to be called when the result is ready, can be NULL * * @return mdns_search_once_s pointer to new search object if query initiated successfully. * NULL otherwise. */ -mdns_search_once_t* mdns_query_async_new(const char * name, const char * service_type, const char * proto, uint16_t type, uint32_t timeout, size_t max_results); +mdns_search_once_t *mdns_query_async_new(const char *name, const char *service_type, const char *proto, uint16_t type, + uint32_t timeout, size_t max_results, mdns_query_notify_t notifier); /** * @brief Query mDNS for host or service diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 5c03d91e1..417b01fe0 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3601,7 +3601,8 @@ static void _mdns_search_free(mdns_search_once_t * search) /** * @brief Allocate new search structure */ -static mdns_search_once_t * _mdns_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) +static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier) { mdns_search_once_t * search = (mdns_search_once_t *)malloc(sizeof(mdns_search_once_t)); if (!search) { @@ -3648,6 +3649,7 @@ static mdns_search_once_t * _mdns_search_init(const char * name, const char * se search->state = SEARCH_INIT; search->sent_at = 0; search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS; + search->notifier = notifier; search->next = NULL; return search; @@ -3660,6 +3662,9 @@ static void _mdns_search_finish(mdns_search_once_t * search) { search->state = SEARCH_OFF; queueDetach(mdns_search_once_t, _mdns_server->search_once, search); + if (search->notifier) { + search->notifier(search); + } xSemaphoreGive(search->done_semaphore); } @@ -5349,7 +5354,8 @@ bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, return false; } -mdns_search_once_t* mdns_query_async_new(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, size_t max_results) +mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, size_t max_results, mdns_query_notify_t notifier) { mdns_search_once_t *search = NULL; @@ -5357,7 +5363,7 @@ mdns_search_once_t* mdns_query_async_new(const char * name, const char * service return NULL; } - search = _mdns_search_init(name, service, proto, type, timeout, max_results); + search = _mdns_search_init(name, service, proto, type, timeout, max_results, notifier); if (!search) { return NULL; } @@ -5384,7 +5390,7 @@ esp_err_t mdns_query(const char * name, const char * service, const char * proto return ESP_ERR_INVALID_ARG; } - search = _mdns_search_init(name, service, proto, type, timeout, max_results); + search = _mdns_search_init(name, service, proto, type, timeout, max_results, NULL); if (!search) { return ESP_ERR_NO_MEM; } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 5e6deeab5..059d1ad25 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -365,6 +365,7 @@ typedef struct mdns_search_once_s { uint32_t started_at; uint32_t sent_at; uint32_t timeout; + mdns_query_notify_t notifier; SemaphoreHandle_t done_semaphore; uint16_t type; uint8_t max_results; diff --git a/components/mdns/test_afl_fuzz_host/mdns_di.h b/components/mdns/test_afl_fuzz_host/mdns_di.h index 4ed0e84cd..12c0c56f7 100644 --- a/components/mdns/test_afl_fuzz_host/mdns_di.h +++ b/components/mdns/test_afl_fuzz_host/mdns_di.h @@ -8,13 +8,16 @@ void (*mdns_test_static_execute_action)(mdns_action_t *) = NULL; mdns_srv_item_t * (*mdns_test_static_mdns_get_service_item)(const char * service, const char * proto, const char *hostname) = NULL; -mdns_search_once_t * (*mdns_test_static_search_init)(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) = NULL; +mdns_search_once_t *(*mdns_test_static_search_init)(const char *name, const char *service, const char *proto, + uint16_t type, uint32_t timeout, uint8_t max_results, + mdns_query_notify_t notifier) = NULL; esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t * search) = NULL; void (*mdns_test_static_search_free)(mdns_search_once_t * search) = NULL; static void _mdns_execute_action(mdns_action_t * action); static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto, const char *hostname); -static mdns_search_once_t * _mdns_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results); +static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier); static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t * search); static void _mdns_search_free(mdns_search_once_t * search); @@ -44,7 +47,7 @@ esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once mdns_search_once_t * mdns_test_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) { - return mdns_test_static_search_init(name, service, proto, type, timeout, max_results); + return mdns_test_static_search_init(name, service, proto, type, timeout, max_results, NULL); } mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index b0a669d14..d442ece4e 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -169,9 +169,9 @@ static void query_mdns_hosts_async(const char * host_name) { ESP_LOGI(TAG, "Query both A and AAA: %s.local", host_name); - mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1); + mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1, NULL); mdns_query_async_delete(s_a); - mdns_search_once_t *s_aaaa = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_AAAA, 1000, 1); + mdns_search_once_t *s_aaaa = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_AAAA, 1000, 1, NULL); while (s_a || s_aaaa) { if (s_a && check_and_print_result(s_a)) { ESP_LOGI(TAG, "Query A %s.local finished", host_name); From cf6ed1cc538d5b20faa0bfe900fda7ff8046892f Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Tue, 3 Aug 2021 13:34:52 +0200 Subject: [PATCH 214/289] esp_eth: add support for multiple Ethernets modules at a time Ethernet driver events properly bounded with ESP NETIF actions to support multiple Ethernet modules used at a time. Components using Ethernet updated to conform with new API. Closes https://github.com/espressif/esp-idf/issues/7318 * Original commit: espressif/esp-idf@ef3038490275d02dee46319f9c596d807163213f --- .../protocol_examples_common/connect.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 3bf58549a..0f2dc3f9c 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -343,7 +343,7 @@ static void on_eth_event(void *esp_netif, esp_event_base_t event_base, switch (event_id) { case ETHERNET_EVENT_CONNECTED: ESP_LOGI(TAG, "Ethernet Link Up"); - esp_netif_create_ip6_linklocal(esp_netif); + ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(esp_netif)); break; default: break; @@ -355,7 +355,7 @@ static void on_eth_event(void *esp_netif, esp_event_base_t event_base, static esp_eth_handle_t s_eth_handle = NULL; static esp_eth_mac_t *s_mac = NULL; static esp_eth_phy_t *s_phy = NULL; -static void *s_eth_glue = NULL; +static esp_eth_netif_glue_handle_t s_eth_glue = NULL; static esp_netif_t *eth_start(void) { @@ -373,14 +373,7 @@ static esp_netif_t *eth_start(void) esp_netif_t *netif = esp_netif_new(&netif_config); assert(netif); free(desc); - // Set default handlers to process TCP/IP stuffs - ESP_ERROR_CHECK(esp_eth_set_default_handlers(netif)); - // Register user defined event handers - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL)); -#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 - ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif)); - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL)); -#endif + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR; @@ -460,6 +453,14 @@ static esp_netif_t *eth_start(void) // combine driver with netif s_eth_glue = esp_eth_new_netif_glue(s_eth_handle); esp_netif_attach(netif, s_eth_glue); + + // Register user defined event handers + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &on_got_ip, NULL)); +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL)); +#endif + esp_eth_start(s_eth_handle); return netif; } @@ -474,7 +475,6 @@ static void eth_stop(void) #endif ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle)); ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue)); - ESP_ERROR_CHECK(esp_eth_clear_default_handlers(eth_netif)); ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle)); ESP_ERROR_CHECK(s_phy->del(s_phy)); ESP_ERROR_CHECK(s_mac->del(s_mac)); From 0611b0cb67b601f53d4348986d7b64a5c5ce3350 Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Fri, 13 Aug 2021 16:50:39 +0200 Subject: [PATCH 215/289] Eth_examples: added support of ESP32-S3 chip Defined SPI modules default GPIO values for ESP32-S3 SPI bus needs to be initialized with SPI_DMA_CH_AUTO option * Original commit: espressif/esp-idf@35454b2bf7164d3dc9bf2c672ec58b091bb75839 --- .../Kconfig.projbuild | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index 62d6b6077..079cbb260 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -1,5 +1,16 @@ menu "Example Connection Configuration" + config EXAMPLE_GPIO_RANGE_MIN + int + default 0 + + config EXAMPLE_GPIO_RANGE_MAX + int + default 33 if IDF_TARGET_ESP32 + default 46 if IDF_TARGET_ESP32S2 + default 19 if IDF_TARGET_ESP32C3 + default 48 if IDF_TARGET_ESP32S3 + config EXAMPLE_CONNECT_WIFI bool "connect using WiFi interface" default y @@ -184,12 +195,14 @@ menu "Example Connection Configuration" config EXAMPLE_ETH_MDC_GPIO int "SMI MDC GPIO number" + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX default 23 help Set the GPIO number used by SMI MDC. config EXAMPLE_ETH_MDIO_GPIO int "SMI MDIO GPIO number" + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX default 18 help Set the GPIO number used by SMI MDIO. @@ -205,41 +218,42 @@ menu "Example Connection Configuration" config EXAMPLE_ETH_SPI_SCLK_GPIO int "SPI SCLK GPIO number" - range 0 33 - default 20 + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + default 14 help Set the GPIO number used by SPI SCLK. config EXAMPLE_ETH_SPI_MOSI_GPIO int "SPI MOSI GPIO number" - range 0 33 - default 19 + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + default 13 help Set the GPIO number used by SPI MOSI. config EXAMPLE_ETH_SPI_MISO_GPIO int "SPI MISO GPIO number" - range 0 33 - default 18 + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + default 12 help Set the GPIO number used by SPI MISO. config EXAMPLE_ETH_SPI_CS_GPIO int "SPI CS GPIO number" - range 0 33 - default 21 + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + default 15 help Set the GPIO number used by SPI CS. config EXAMPLE_ETH_SPI_CLOCK_MHZ int "SPI clock speed (MHz)" - range 20 80 + range 5 80 default 36 help Set the clock speed (MHz) of SPI interface. config EXAMPLE_ETH_SPI_INT_GPIO int "Interrupt GPIO number" + range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX default 4 help Set the GPIO number used by the SPI Ethernet module interrupt line. @@ -247,6 +261,7 @@ menu "Example Connection Configuration" config EXAMPLE_ETH_PHY_RST_GPIO int "PHY Reset GPIO number" + range -1 EXAMPLE_GPIO_RANGE_MAX default 5 help Set the GPIO number used to reset PHY chip. From 6d6dd2b75e91f5cd10ae4eaf6639afb19ceea19b Mon Sep 17 00:00:00 2001 From: baohongde Date: Thu, 16 Sep 2021 15:57:57 +0800 Subject: [PATCH 216/289] components/bt: move config BT_RESERVE_DRAM from bluedroid to ESP32 controller * Original commit: espressif/esp-idf@b310c062cd25f249e00dd03dd27baed783921630 --- components/mdns/test_afl_fuzz_host/sdkconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index 1b5997b64..e09b70b80 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -53,7 +53,7 @@ #define CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF 0 #define CONFIG_BTDM_CTRL_PINNED_TO_CORE 0 #define CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF 1 -#define CONFIG_BT_RESERVE_DRAM 0x0 +#define CONFIG_BTDM_RESERVE_DRAM 0x0 #define CONFIG_COAP_MBEDTLS_PSK 1 #define CONFIG_COAP_LOG_DEFAULT_LEVEL 0 #define CONFIG_ADC_DISABLE_DAC 1 From 91a3d95f965cc7f35f5e8879bccb1662b292e644 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 7 Sep 2021 13:05:38 +0200 Subject: [PATCH 217/289] mdns: Fix potential null dereference identified by fuzzer tests * Original commit: espressif/esp-idf@e7dabb14f7c8fd9bd2bea55d8f1accc65323a1c0 --- components/mdns/mdns.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 417b01fe0..7045c76bc 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2775,7 +2775,8 @@ static bool _mdns_question_matches(mdns_parsed_question_t * question, uint16_t t } } else if (service && (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT)) { const char * name = _mdns_get_service_instance_name(service->service); - if (name && question->host && !strcasecmp(name, question->host) + if (name && question->host && question->service && question->proto && question->domain + && !strcasecmp(name, question->host) && !strcasecmp(service->service->service, question->service) && !strcasecmp(service->service->proto, question->proto) && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { @@ -3237,7 +3238,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } 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)) { + if (service && col && (parsed_packet->probe || parsed_packet->authoritative)) { if (col > 0 || !port) { do_not_reply = true; if (_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { From 5e087d82d675ae4442e1d4e5f2e532a9c5715bd4 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 21 Sep 2021 11:06:59 +0200 Subject: [PATCH 218/289] mdns: Update copyright header * Original commit: espressif/esp-idf@2a2b95b9c22bc5090d87a4f4317288b64b14fcd9 --- components/mdns/mdns.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 7045c76bc..9f5a54554 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1,16 +1,8 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "mdns.h" #include "mdns_private.h" From b26606252fce50265642f0387064654019bb4e4b Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Mon, 13 Sep 2021 19:33:02 +0800 Subject: [PATCH 219/289] mdns: allow mutiple instances with same service type * Original commit: espressif/esp-idf@b7a99f46587a69a2cd07e7616c3bb30b7b1a6edf --- components/mdns/Kconfig | 6 ++ components/mdns/include/mdns.h | 24 +++++- components/mdns/mdns.c | 77 ++++++++++++++++--- .../protocols/mdns/main/mdns_example_main.c | 3 + 4 files changed, 99 insertions(+), 11 deletions(-) diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig index b49ae703c..5607afac8 100644 --- a/components/mdns/Kconfig +++ b/components/mdns/Kconfig @@ -84,4 +84,10 @@ menu "mDNS" This option creates a new thread to serve receiving packets (TODO). This option uses additional N sockets, where N is number of interfaces. + config MDNS_MULTIPLE_INSTANCE + bool "Multiple instances under the same service type" + default y + help + Enables adding multiple service instances under the same service type. + endmenu diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 4bb288d41..35c8d538a 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -187,7 +187,10 @@ esp_err_t mdns_instance_name_set(const char * instance_name); * @note The value length of txt items will be automatically decided by strlen * * @param instance_name instance name to set. If NULL, - * global instance name or hostname will be used + * global instance name or hostname will be used. + * Note that MDNS_MULTIPLE_INSTANCE config option + * needs to be enabled for adding multiple instances + * with the same instance type. * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param port service port @@ -209,6 +212,9 @@ esp_err_t mdns_service_add(const char * instance_name, const char * service_type * * @param instance_name instance name to set. If NULL, * global instance name or hostname will be used + * Note that MDNS_MULTIPLE_INSTANCE config option + * needs to be enabled for adding multiple instances + * with the same instance type. * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param hostname service hostname. If NULL, local hostname will be used. @@ -238,6 +244,22 @@ esp_err_t mdns_service_add_for_host(const char * instance_name, const char * ser */ bool mdns_service_exists(const char * service_type, const char * proto, const char * hostname); + +/** + * @brief Check whether a service has been added. + * + * @param instance instance name + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, checks for the local hostname. + * + * @return + * - true Correspondding service has been added. + * - false Service not found. + */ +bool mdns_service_exists_with_instance(const char *instance, const char *service_type, const char *proto, + const char *hostname); + /** * @brief Remove service from mDNS server * diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 9f5a54554..42e1dd74a 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -223,15 +223,8 @@ esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet) return ESP_OK; } -/** - * @brief Get the service name of a service - */ -static const char * _mdns_get_service_instance_name(mdns_service_t * service) +static const char *_mdns_get_default_instance_name(void) { - if (service && !_str_null_or_empty(service->instance)) { - return service->instance; - } - if (_mdns_server && !_str_null_or_empty(_mdns_server->instance)) { return _mdns_server->instance; } @@ -243,6 +236,49 @@ static const char * _mdns_get_service_instance_name(mdns_service_t * service) return NULL; } +/** + * @brief Get the service name of a service + */ +static const char * _mdns_get_service_instance_name(const mdns_service_t * service) +{ + if (service && !_str_null_or_empty(service->instance)) { + return service->instance; + } + + return _mdns_get_default_instance_name(); +} + +static bool _mdns_instance_name_match(const char *lhs, const char *rhs) +{ + if (lhs == NULL) { + lhs = _mdns_get_default_instance_name(); + } + if (rhs == NULL) { + rhs = _mdns_get_default_instance_name(); + } + return !strcasecmp(lhs, rhs); +} + +static bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instance, const char *service, + const char *proto, const char *hostname) +{ + return !strcasecmp(srv->service, service) && _mdns_instance_name_match(srv->instance, instance) && + !strcasecmp(srv->proto, proto) && (_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); +} + +static mdns_srv_item_t *_mdns_get_service_item_instance(const char *instance, const char *service, const char *proto, + const char *hostname) +{ + mdns_srv_item_t *s = _mdns_server->services; + while (s) { + if (_mdns_service_match_instance(s->service, instance, service, proto, hostname)) { + return s; + } + s = s->next; + } + return NULL; +} + /** * @brief reads MDNS FQDN into mdns_name_t structure * FQDN is in format: [hostname.|[instance.]_service._proto.]local. @@ -1420,7 +1456,13 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_ mdns_parsed_question_t *q = parsed_packet->questions; while (q) { shared = q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_SDPTR || !parsed_packet->probe; - if (q->service && q->proto) { + if (q->type == MDNS_TYPE_SRV || q->type == MDNS_TYPE_TXT) { + mdns_srv_item_t *service = _mdns_get_service_item_instance(q->host, q->service, q->proto, NULL); + if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { + _mdns_free_tx_packet(packet); + return; + } + } else if (q->service && q->proto) { mdns_srv_item_t *service = _mdns_server->services; while (service) { if (_mdns_service_match(service->service, q->service, q->proto, NULL)) { @@ -2659,7 +2701,12 @@ static bool _mdns_name_is_ours(mdns_name_t * name) } //find the service - mdns_srv_item_t * service = _mdns_get_service_item(name->service, name->proto, NULL); + mdns_srv_item_t * service; + if (_str_null_or_empty(name->host)) { + service = _mdns_get_service_item(name->service, name->proto, NULL); + } else { + service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL); + } if (!service) { return false; } @@ -4941,7 +4988,11 @@ esp_err_t mdns_service_add_for_host(const char * instance, const char * service, return ESP_ERR_NO_MEM; } +#if CONFIG_MDNS_MULTIPLE_INSTANCE + mdns_srv_item_t * item = _mdns_get_service_item_instance(instance, service, proto, hostname); +#else mdns_srv_item_t * item = _mdns_get_service_item(service, proto, hostname); +#endif // CONFIG_MDNS_MULTIPLE_INSTANCE if (item) { return ESP_ERR_INVALID_ARG; } @@ -5004,6 +5055,12 @@ bool mdns_service_exists(const char * service_type, const char * proto, const ch return _mdns_get_service_item(service_type, proto, hostname) != NULL; } +bool mdns_service_exists_with_instance(const char *instance, const char *service_type, const char *proto, + const char *hostname) +{ + return _mdns_get_service_item_instance(instance, service_type, proto, hostname) != NULL; +} + esp_err_t mdns_service_port_set_for_host(const char * service, const char * proto, const char * hostname, uint16_t port) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index d442ece4e..ad347ddb2 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -53,6 +53,9 @@ static void initialise_mdns(void) //initialize service ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) ); +#if CONFIG_MDNS_MULTIPLE_INSTANCE + ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer1", "_http", "_tcp", 80, NULL, 0) ); +#endif #if CONFIG_MDNS_PUBLISH_DELEGATE_HOST char *delegated_hostname; From eb7eeb58d301337ff70c8ef2718711f939eefd10 Mon Sep 17 00:00:00 2001 From: Jakob Hasse Date: Mon, 5 Jul 2021 14:33:56 +0800 Subject: [PATCH 220/289] [examples]: removed hyphens Replaced hyphens with underscores in examples project definition for all examples which had hyphens in their project name. dpp-enrollee is an exceptions because the name matches the project directory name while the project directory also contains hyphens. * Original commit: espressif/esp-idf@81e926620498e55beb8eb4bd9c4169e8f3338563 --- examples/protocols/mdns/CMakeLists.txt | 2 +- examples/protocols/mdns/Makefile | 2 +- examples/protocols/mdns/mdns_example_test.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/protocols/mdns/CMakeLists.txt b/examples/protocols/mdns/CMakeLists.txt index ddd7263c5..e624184a2 100644 --- a/examples/protocols/mdns/CMakeLists.txt +++ b/examples/protocols/mdns/CMakeLists.txt @@ -7,4 +7,4 @@ cmake_minimum_required(VERSION 3.5) set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(mdns-test) +project(mdns_test) diff --git a/examples/protocols/mdns/Makefile b/examples/protocols/mdns/Makefile index 5b69ef89c..90408709d 100644 --- a/examples/protocols/mdns/Makefile +++ b/examples/protocols/mdns/Makefile @@ -3,7 +3,7 @@ # project subdirectory. # -PROJECT_NAME := mdns-test +PROJECT_NAME := mdns_test EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index a3e36dd78..68a780687 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -115,7 +115,7 @@ def test_examples_protocol_mdns(env, extra_data): """ dut1 = env.get_dut('mdns-test', 'examples/protocols/mdns', dut_class=ttfw_idf.ESP32DUT) # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, 'mdns-test.bin') + binary_file = os.path.join(dut1.app.binary_path, 'mdns_test.bin') bin_size = os.path.getsize(binary_file) ttfw_idf.log_performance('mdns-test_bin_size', '{}KB'.format(bin_size // 1024)) # 1. start mdns application From 38b4fe2353d275ce124025a2cf106b166f926993 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 19 Oct 2021 16:55:16 +0200 Subject: [PATCH 221/289] mdns: Fix parsing non-standard queries Fix for packets containing unexpected domains, such as openthread.thread.home.arpa. If we find this packet we set the name entry as invalid, but continue with parsing as the packet might contain related queries for us. Closes https://github.com/espressif/esp-idf/issues/7694 * Original commit: espressif/esp-idf@d16f9bade5beab3785677dd5b39ebc4e9c895008 --- components/mdns/mdns.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 42e1dd74a..8e8a86436 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -310,6 +310,7 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s buf[len] = '\0'; if (name->parts == 1 && buf[0] != '_' && (strcasecmp(buf, MDNS_DEFAULT_DOMAIN) != 0) + && (strcasecmp(buf, "arpa") != 0) && (strcasecmp(buf, "ip6") != 0) && (strcasecmp(buf, "in-addr") != 0)) { strlcat(name->host, ".", sizeof(name->host)); @@ -2793,7 +2794,8 @@ static const uint8_t * _mdns_parse_fqdn(const uint8_t * packet, const uint8_t * if (strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN) == 0 || strcasecmp(name->domain, "arpa") == 0) { return next_data; } - return 0; + name->invalid = true; // mark the current name invalid, but continue with other question + return next_data; } /** From fd8499c87457736d570c4db6b4fb3040b16cfb3e Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Thu, 30 Sep 2021 15:18:16 +0800 Subject: [PATCH 222/289] mdns: support service subtype * Closes https://github.com/espressif/esp-idf/issues/5508 * Original commit: espressif/esp-idf@e7e8610f563e0b8532a093ea8b803f0eb132fd0e --- components/mdns/include/mdns.h | 36 ++-- components/mdns/mdns.c | 196 +++++++++++++++++- .../mdns/private_include/mdns_private.h | 30 +-- .../protocols/mdns/main/mdns_example_main.c | 1 + 4 files changed, 226 insertions(+), 37 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 35c8d538a..8c58687b5 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -1,16 +1,8 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef ESP_MDNS_H_ #define ESP_MDNS_H_ @@ -500,6 +492,24 @@ esp_err_t mdns_service_txt_item_remove(const char * service_type, const char * p esp_err_t mdns_service_txt_item_remove_for_host(const char * service_type, const char * proto, const char * hostname, const char * key); +/** + * @brief Add subtype for service. + * + * @param instance_name instance name. If NULL, will find the first service with the same service type and protocol. + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param subtype The subtype to add. + * + * @return + * - 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_subtype_add_for_host(const char *instance_name, const char *service_type, const char *proto, + const char *hostname, const char *subtype); + /** * @brief Remove and free all services from mDNS server * diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 8e8a86436..0ce3af28a 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -15,6 +15,10 @@ void mdns_debug_packet(const uint8_t * data, size_t len); #endif +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +#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) @@ -174,6 +178,24 @@ static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char return NULL; } +static mdns_srv_item_t * _mdns_get_service_item_subtype(const char *subtype, const char * service, const char * proto) +{ + mdns_srv_item_t * s = _mdns_server->services; + while (s) { + if (_mdns_service_match(s->service, service, proto, NULL)) { + mdns_subtype_t *subtype_item = s->service->subtype; + while(subtype_item) { + if (!strcasecmp(subtype_item->subtype, subtype)) { + return s; + } + subtype_item = subtype_item->next; + } + } + s = s->next; + } + return NULL; +} + static mdns_host_item_t * mdns_get_host_item(const char * hostname) { if (hostname == NULL || strcasecmp(hostname, _mdns_server->hostname) == 0) { @@ -605,6 +627,54 @@ static uint16_t _mdns_append_ptr_record(uint8_t * packet, uint16_t * index, cons return record_length; } +/** + * @brief appends PTR record for a subtype to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param instance the service instance name + * @param subtype the service subtype + * @param proto the service protocol + * @param flush whether to set the flush flag + * @param bye whether to set the bye flag + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_subtype_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, + const char *subtype, const char *service, const char *proto, bool flush, + bool bye) +{ + const char *subtype_str[5] = {subtype, MDNS_SUB_STR, service, proto, MDNS_DEFAULT_DOMAIN}; + const char *instance_str[4] = {instance, service, proto, MDNS_DEFAULT_DOMAIN}; + uint16_t record_length = 0; + uint8_t part_length; + + if (service == NULL) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, subtype_str, ARRAY_SIZE(subtype_str)); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + part_length = _mdns_append_fqdn(packet, index, instance_str, ARRAY_SIZE(instance_str)); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} + /** * @brief appends DNS-SD PTR record for service to a packet, incrementing the index * @@ -1010,6 +1080,33 @@ static uint8_t _mdns_append_host_answer(uint8_t * packet, uint16_t * index, mdns return num_records; } +/** + * @brief Append PTR answers to packet + * + * @return number of answers added to the packet + */ +static uint8_t _mdns_append_service_ptr_answers(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, + bool bye) +{ + uint8_t appended_answers = 0; + + if (_mdns_append_ptr_record(packet, index, _mdns_get_service_instance_name(service), service->service, + service->proto, flush, bye) <= 0) { + return appended_answers; + } + + mdns_subtype_t *subtype = service->subtype; + while (subtype) { + appended_answers += + (_mdns_append_subtype_ptr_record(packet, index, _mdns_get_service_instance_name(service), subtype->subtype, + service->service, service->proto, flush, bye) > 0); + subtype = subtype->next; + } + + return appended_answers; +} + + /** * @brief Append answer to packet * @@ -1018,12 +1115,8 @@ static uint8_t _mdns_append_host_answer(uint8_t * packet, uint16_t * index, mdns static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_answer_t * answer, mdns_if_t tcpip_if) { if (answer->type == MDNS_TYPE_PTR) { - if (answer->service) { - return _mdns_append_ptr_record(packet, index, - _mdns_get_service_instance_name(answer->service), - answer->service->service, answer->service->proto, - answer->flush, answer->bye) > 0; + return _mdns_append_service_ptr_answers(packet, index, answer->service, answer->flush, answer->bye); } else { return _mdns_append_ptr_record(packet, index, answer->custom_instance, answer->custom_service, answer->custom_proto, @@ -1435,6 +1528,24 @@ static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t * packet, const c return true; } +static bool _mdns_service_match_ptr_question(const mdns_service_t *service, const mdns_parsed_question_t *question) +{ + if (!_mdns_service_match(service, question->service, question->proto, NULL)) { + return false; + } + if (question->sub) { + mdns_subtype_t *subtype = service->subtype; + while (subtype) { + if (!strcasecmp(subtype->subtype, question->host)) { + return true; + } + subtype = subtype->next; + } + return false; + } + return true; +} + /** * @brief Create answer packet to questions from parsed packet */ @@ -1466,7 +1577,7 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_ } else if (q->service && q->proto) { mdns_srv_item_t *service = _mdns_server->services; while (service) { - if (_mdns_service_match(service->service, q->service, q->proto, NULL)) { + if (_mdns_service_match_ptr_question(service->service, q)) { if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { _mdns_free_tx_packet(packet); return; @@ -2179,6 +2290,7 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * s->instance = instance?strndup(instance, MDNS_NAME_BUF_LEN - 1):NULL; s->txt = new_txt; s->port = port; + s->subtype = NULL; if (hostname) { s->hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); @@ -2338,7 +2450,12 @@ static void _mdns_free_service(mdns_service_t * service) free((char *)s->value); free(s); } - free(service->txt); + while (service->subtype) { + mdns_subtype_t * next = service->subtype->next; + free((char *)service->subtype->subtype); + free(service->subtype); + service->subtype = next; + } free(service); } @@ -2701,9 +2818,12 @@ static bool _mdns_name_is_ours(mdns_name_t * name) return false; } + //find the service mdns_srv_item_t * service; - if (_str_null_or_empty(name->host)) { + if (name->sub) { + service = _mdns_get_service_item_subtype(name->host, name->service, name->proto); + } else if (_str_null_or_empty(name->host)) { service = _mdns_get_service_item(name->service, name->proto, NULL); } else { service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL); @@ -2712,8 +2832,8 @@ static bool _mdns_name_is_ours(mdns_name_t * name) return false; } - //if host is empty and we have service, we have success - if (_str_null_or_empty(name->host)) { + //if query is PTR query and we have service, we have success + if (name->sub || _str_null_or_empty(name->host)) { return true; } @@ -3122,7 +3242,8 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) a = a->next; } continue; - } else if (name->sub || !_mdns_name_is_ours(name)) { + } + if (!_mdns_name_is_ours(name)) { continue; } @@ -3140,6 +3261,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) question->unicast = unicast; question->type = type; + question->sub = name->sub; if (_mdns_strdup_check(&(question->host), name->host) || _mdns_strdup_check(&(question->service), name->service) || _mdns_strdup_check(&(question->proto), name->proto) @@ -4247,6 +4369,9 @@ static void _mdns_free_action(mdns_action_t * action) case ACTION_SERVICE_TXT_DEL: free(action->data.srv_txt_del.key); break; + case ACTION_SERVICE_SUBTYPE_ADD: + free(action->data.srv_subtype_add.subtype); + break; case ACTION_SEARCH_ADD: //fallthrough case ACTION_SEARCH_SEND: @@ -4282,6 +4407,8 @@ static void _mdns_execute_action(mdns_action_t * action) mdns_service_t * service; char * key; char * value; + char *subtype; + mdns_subtype_t *subtype_item; mdns_txt_linked_item_t * txt, * t; switch(action->type) { @@ -4395,6 +4522,19 @@ static void _mdns_execute_action(mdns_action_t * action) _mdns_announce_all_pcbs(&action->data.srv_txt_set.service, 1, false); + break; + case ACTION_SERVICE_SUBTYPE_ADD: + service = action->data.srv_subtype_add.service->service; + subtype = action->data.srv_subtype_add.subtype; + subtype_item = (mdns_subtype_t *)malloc(sizeof(mdns_subtype_t)); + if (!subtype_item) { + HOOK_MALLOC_FAILED; + _mdns_free_action(action); + return; + } + subtype_item->subtype = subtype; + subtype_item->next = service->subtype; + service->subtype = subtype_item; break; case ACTION_SERVICE_DEL: a = _mdns_server->services; @@ -5249,6 +5389,40 @@ esp_err_t mdns_service_txt_item_remove(const char * service, const char * proto, return mdns_service_txt_item_remove_for_host(service, proto, _mdns_server->hostname, key); } +esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const char *service, const char *proto, + const char *hostname, const char *subtype) +{ + if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || + _str_null_or_empty(subtype)) { + return ESP_ERR_INVALID_ARG; + } + mdns_srv_item_t * s = _mdns_get_service_item_instance(instance_name, service, proto, hostname); + + if (!s) { + return ESP_ERR_NOT_FOUND; + } + mdns_action_t * action = (mdns_action_t *)malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + + action->type = ACTION_SERVICE_SUBTYPE_ADD; + action->data.srv_subtype_add.service = s; + action->data.srv_subtype_add.subtype = strdup(subtype); + + if (!action->data.srv_subtype_add.subtype) { + free(action); + return ESP_ERR_NO_MEM; + } + if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + free(action->data.srv_subtype_add.subtype); + free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + esp_err_t mdns_service_instance_name_set_for_host(const char * service, const char * proto, const char * hostname, const char * instance) { diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 059d1ad25..a92fb8dd2 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef MDNS_PRIVATE_H_ #define MDNS_PRIVATE_H_ @@ -176,6 +168,7 @@ typedef enum { 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, @@ -225,6 +218,7 @@ typedef struct { typedef struct mdns_parsed_question_s { struct mdns_parsed_question_s * next; uint16_t type; + bool sub; bool unicast; char * host; char * service; @@ -279,6 +273,11 @@ typedef struct mdns_txt_linked_item_s { struct mdns_txt_linked_item_s * next; /*!< next result, or NULL for the last result in the list */ } mdns_txt_linked_item_t; +typedef struct mdns_subtype_s { + const char *subtype; /*!< subtype */ + struct mdns_subtype_s * next; /*!< next result, or NULL for the last result in the list */ +} mdns_subtype_t; + typedef struct { const char * instance; const char * service; @@ -288,6 +287,7 @@ typedef struct { uint16_t weight; uint16_t port; mdns_txt_linked_item_t * txt; + mdns_subtype_t *subtype; } mdns_service_t; typedef struct mdns_srv_item_s { @@ -431,6 +431,10 @@ typedef 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; diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index ad347ddb2..f53e06031 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -53,6 +53,7 @@ static void initialise_mdns(void) //initialize service ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) ); + ESP_ERROR_CHECK( mdns_service_subtype_add_for_host("ESP32-WebServer", "_http", "_tcp", NULL, "_server") ); #if CONFIG_MDNS_MULTIPLE_INSTANCE ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer1", "_http", "_tcp", 80, NULL, 0) ); #endif From 76fcd4128af130f4045a7727cec4eb7fa8dcb9a6 Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Mon, 20 Sep 2021 11:37:03 +0530 Subject: [PATCH 223/289] freertos: update freertos folder structure to match upstream The following changes have been made: 1. All FreeRTOS kernel source files are now placed in the freertos/FreeRTOS-Kernel folder to match with the upstream folder structure. 2. All kernel include files are now placed in freertos/FreeRTOS-Kernel/include. 3. All port files are now placed in freertos/FreeRTOS-Kernel/portable. 4. All additions/customizations are placed in freertos/esp_additions. 5. All other miscellaneous files (README, License files etc.) are moved to freertos/FreeRTOS-Kernel folder to match with the upstream. 6. Updated esp-cryptoauthlib to latest commit to resolve FreeRTOS include dependencies. Signed-off-by: Sudeep Mohanty * Original commit: espressif/esp-idf@48462221029c7da4b1ea233e9e781cd57ff91c7e --- components/mdns/test_afl_fuzz_host/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 4d6067bb4..a343fe3d6 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -18,9 +18,9 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi -I$(COMPONENTS_DIR)/esp_system/include \ -I$(COMPONENTS_DIR)/esp_timer/include \ -I$(COMPONENTS_DIR)/esp_wifi/include \ - -I$(COMPONENTS_DIR)/freertos \ - -I$(COMPONENTS_DIR)/freertos/include \ - -I$(COMPONENTS_DIR)/freertos/port/xtensa/include \ + -I$(COMPONENTS_DIR)/freertos/FreeRTOS-Kernel \ + -I$(COMPONENTS_DIR)/freertos/FreeRTOS-Kernel/include \ + -I$(COMPONENTS_DIR)/freertos/FreeRTOS-Kernel/portable/xtensa/include \ -I$(COMPONENTS_DIR)/hal/include \ -I$(COMPONENTS_DIR)/hal/esp32/include \ -I$(COMPONENTS_DIR)/heap/include \ From be2a92467432753e1c1229e009fe46f2a5803360 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Thu, 4 Nov 2021 15:28:07 +0100 Subject: [PATCH 224/289] Build & config: Remove the "make" build system The "make" build system was deprecated in v4.0 in favor of idf.py (cmake). The remaining support is removed in v5.0. * Original commit: espressif/esp-idf@9c1d4f5b549d6a7125e5c7c323c80d37361991cb --- components/mdns/test_afl_fuzz_host/sdkconfig.h | 2 -- examples/protocols/mdns/README.md | 1 - 2 files changed, 3 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index e09b70b80..ce264888c 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -3,7 +3,6 @@ * Espressif IoT Development Framework (ESP-IDF) Configuration Header */ #pragma once -#define CONFIG_IDF_CMAKE 1 #define CONFIG_IDF_TARGET "esp32" #define CONFIG_IDF_TARGET_ESP32 1 #define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 @@ -21,7 +20,6 @@ #define CONFIG_BOOTLOADER_WDT_ENABLE 1 #define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 #define CONFIG_BOOTLOADER_RESERVE_RTC_SIZE 0x0 -#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 #define CONFIG_ESPTOOLPY_WITH_STUB 1 #define CONFIG_ESPTOOLPY_FLASHMODE_DIO 1 #define CONFIG_ESPTOOLPY_FLASHMODE "dio" diff --git a/examples/protocols/mdns/README.md b/examples/protocols/mdns/README.md index e6644d5e5..b66cebc57 100644 --- a/examples/protocols/mdns/README.md +++ b/examples/protocols/mdns/README.md @@ -16,7 +16,6 @@ Shows how to use mDNS to advertise lookup services and hosts * Open the project configuration menu (`idf.py menuconfig`) * Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../README.md) for more details. -* When using Make build system, set `Default serial port` under `Serial flasher config`. * Set `mDNS Hostname` as host name prefix for the device and its instance name in `mDNS Instance Name` * Disable `Resolve test services` to prevent the example from querying defined names/services on startup (cause warnings in example logs, as illustrated below) From 4a9d55edf7ce5cea258f28ae59233dc167b2a525 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Fri, 5 Nov 2021 15:38:25 +0100 Subject: [PATCH 225/289] Build & config: Remove leftover files from the unsupported "make" build system * Original commit: espressif/esp-idf@766aa5708443099f3f033b739cda0e1de101cca6 --- components/mdns/component.mk | 7 ------- components/mdns/test/component.mk | 4 ---- .../protocol_examples_common/component.mk | 0 examples/protocols/mdns/Makefile | 10 ---------- examples/protocols/mdns/main/component.mk | 4 ---- 5 files changed, 25 deletions(-) delete mode 100644 components/mdns/component.mk delete mode 100644 components/mdns/test/component.mk delete mode 100644 examples/common_components/protocol_examples_common/component.mk delete mode 100644 examples/protocols/mdns/Makefile delete mode 100644 examples/protocols/mdns/main/component.mk diff --git a/components/mdns/component.mk b/components/mdns/component.mk deleted file mode 100644 index f22f83094..000000000 --- a/components/mdns/component.mk +++ /dev/null @@ -1,7 +0,0 @@ -ifdef CONFIG_MDNS_NETWORKING_SOCKET -COMPONENT_OBJEXCLUDE := mdns_networking_lwip.o -else -COMPONENT_OBJEXCLUDE := mdns_networking_socket.o -endif -COMPONENT_ADD_INCLUDEDIRS := include -COMPONENT_PRIV_INCLUDEDIRS := private_include diff --git a/components/mdns/test/component.mk b/components/mdns/test/component.mk deleted file mode 100644 index 8c6eb513e..000000000 --- a/components/mdns/test/component.mk +++ /dev/null @@ -1,4 +0,0 @@ -# -#Component Makefile -# -COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/examples/common_components/protocol_examples_common/component.mk b/examples/common_components/protocol_examples_common/component.mk deleted file mode 100644 index e69de29bb..000000000 diff --git a/examples/protocols/mdns/Makefile b/examples/protocols/mdns/Makefile deleted file mode 100644 index 90408709d..000000000 --- a/examples/protocols/mdns/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# - -PROJECT_NAME := mdns_test - -EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common - -include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/mdns/main/component.mk b/examples/protocols/mdns/main/component.mk deleted file mode 100644 index a98f634ea..000000000 --- a/examples/protocols/mdns/main/component.mk +++ /dev/null @@ -1,4 +0,0 @@ -# -# "main" pseudo-component makefile. -# -# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) From d0bbe880b6c47b44146587723719ea9a844a22e2 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Wed, 10 Nov 2021 17:29:09 +0800 Subject: [PATCH 226/289] mdns: fix wrong PTR record count * Original commit: espressif/esp-idf@5d3f8157e0e481363ef93d54a29d957fc91cca86 --- components/mdns/mdns.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 0ce3af28a..351b5c169 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1094,6 +1094,7 @@ static uint8_t _mdns_append_service_ptr_answers(uint8_t *packet, uint16_t *index service->proto, flush, bye) <= 0) { return appended_answers; } + appended_answers++; mdns_subtype_t *subtype = service->subtype; while (subtype) { From 145a8d22914b68efb6181b3dc422aaa9a9fd5efe Mon Sep 17 00:00:00 2001 From: Fischerauer Christian Date: Tue, 16 Nov 2021 16:18:43 +0100 Subject: [PATCH 227/289] esp_eth: rework KSZ80xx implementation and add more KSZ80xx PHYs * add support for KSZ8001, KSZ8021, KSZ8031, KSZ8051 and KSZ8061 * remove duplicate code * simplify architecture to make the code base extensible (for future work) * Original commit: espressif/esp-idf@3fb83f2866f266209e3aaed0c80df952b8d82b91 --- .../protocol_examples_common/Kconfig.projbuild | 9 +++++++++ .../common_components/protocol_examples_common/connect.c | 2 ++ 2 files changed, 11 insertions(+) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index 079cbb260..867863e48 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -191,6 +191,15 @@ menu "Example Connection Configuration" help DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver. Goto http://www.ti.com/product/DP83848J for more information about it. + + config EXAMPLE_ETH_PHY_KSZ80XX + bool "KSZ80xx" + help + With the KSZ80xx series, Microchip offers single-chip 10BASE-T/100BASE-TX + Ethernet Physical Layer Tranceivers (PHY). + The following chips are supported: KSZ8001, KSZ8021, KSZ8031, KSZ8041, + KSZ8051, KSZ8061, KSZ8081, KSZ8091 + Goto https://www.microchip.com for more information about them. endchoice config EXAMPLE_ETH_MDC_GPIO diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 0f2dc3f9c..b3b03940f 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -390,6 +390,8 @@ static esp_netif_t *eth_start(void) s_phy = esp_eth_phy_new_lan87xx(&phy_config); #elif CONFIG_EXAMPLE_ETH_PHY_DP83848 s_phy = esp_eth_phy_new_dp83848(&phy_config); +#elif CONFIG_EXAMPLE_ETH_PHY_KSZ80XX + s_phy = esp_eth_phy_new_ksz80xx(&phy_config); #endif #elif CONFIG_EXAMPLE_USE_SPI_ETHERNET gpio_install_isr_service(0); From d5001e894f4cb6a1550ebbfb57efa2facc80236d Mon Sep 17 00:00:00 2001 From: Suren Gabrielyan Date: Tue, 19 Oct 2021 15:53:19 +0400 Subject: [PATCH 228/289] mdns: added test app Closes IDF-4132 * Original commit: espressif/esp-idf@e0d5fca390f084e110261942fbcd00342cd1022a --- tools/test_apps/protocols/mdns/CMakeLists.txt | 11 + tools/test_apps/protocols/mdns/README.md | 48 ++++ tools/test_apps/protocols/mdns/app_test.py | 268 ++++++++++++++++++ .../protocols/mdns/main/CMakeLists.txt | 2 + .../protocols/mdns/main/Kconfig.projbuild | 28 ++ tools/test_apps/protocols/mdns/main/main.c | 117 ++++++++ .../test_apps/protocols/mdns/main/mdns_test.c | 166 +++++++++++ .../protocols/mdns/sdkconfig.defaults | 2 + 8 files changed, 642 insertions(+) create mode 100644 tools/test_apps/protocols/mdns/CMakeLists.txt create mode 100644 tools/test_apps/protocols/mdns/README.md create mode 100644 tools/test_apps/protocols/mdns/app_test.py create mode 100644 tools/test_apps/protocols/mdns/main/CMakeLists.txt create mode 100644 tools/test_apps/protocols/mdns/main/Kconfig.projbuild create mode 100644 tools/test_apps/protocols/mdns/main/main.c create mode 100644 tools/test_apps/protocols/mdns/main/mdns_test.c create mode 100644 tools/test_apps/protocols/mdns/sdkconfig.defaults diff --git a/tools/test_apps/protocols/mdns/CMakeLists.txt b/tools/test_apps/protocols/mdns/CMakeLists.txt new file mode 100644 index 000000000..e756f2b40 --- /dev/null +++ b/tools/test_apps/protocols/mdns/CMakeLists.txt @@ -0,0 +1,11 @@ +# The following four lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(mdns) diff --git a/tools/test_apps/protocols/mdns/README.md b/tools/test_apps/protocols/mdns/README.md new file mode 100644 index 000000000..40ae127fe --- /dev/null +++ b/tools/test_apps/protocols/mdns/README.md @@ -0,0 +1,48 @@ +| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | +| ----------------- | ----- | -------- | -------- | + +# mDNS test project + +Main purpose of this application is to test the mDNS library to correctly advertise, lookup services and hosts. +The "app_test.py" logically separated from two sets of test cases 1. "ESP32 board sends queries -> Host sends answers" and 2. "Host sends queries" -> "ESP32 board sends answers". +Two first sets of test cases are starting by 'test_query_' and the second ones by 'start_case'. + +## Runtime settings + +1. For first sets of test cases python creates and sends dns queries using "dpkt" library +2. For the second sets of test cases this app waits for user input to provide test case(e.g. CONFIG_TEST_QUERY_HOST, CONFIG_TEST_QUERY_HOST_ASYNC or CONFIG_TEST_QUERY_SERVICE) +In order to run both of them just needed to set up the project and run by 'python app_test.py' + +## Test app workflow + +- mDNS is initialized with hostname and instance name defined through the project configuration and `_http._tcp` service is added to be advertised +- A delegated host `esp32-delegated._local` is added and another `_http._tcp` service is added for this host. +- WiFi STA is started and tries to connect to the access point defined through the project configuration + +### Configure the project + +* Open the project configuration menu (`idf.py menuconfig`) + +* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](README.md) for more details. +* Set `mDNS Hostname` as host name prefix for the device and its instance name in `mDNS Instance Name` + +### Build and Flash + +Build the project and flash it to the board, then run the monitor tool to view the serial output: + +``` +idf.py -p PORT flash monitor +``` + +- Wait for WiFi to connect to your access point +- You can now ping the device at `[board-hostname].local`, where `[board-hostname]` is preconfigured hostname, `esp32-mdns` by default. +- You can also browse for `_http._tcp` on the same network to find the advertised service +- Note that for purpose of CI tests, configuration options of `MDNS_RESOLVE_TEST_SERVICES` and `MDNS_ADD_MAC_TO_HOSTNAME` are available, but disabled by default. If enabled, then the hostname suffix of last 3 bytes from device MAC address is added, e.g. `esp32-mdns-80FFFF`, and a query for test service is issued. + + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Hardware Required +This test-app can be executed on any ESP32 board, the only required interface is WiFi and connection to a local network and tls server. diff --git a/tools/test_apps/protocols/mdns/app_test.py b/tools/test_apps/protocols/mdns/app_test.py new file mode 100644 index 000000000..043e4622b --- /dev/null +++ b/tools/test_apps/protocols/mdns/app_test.py @@ -0,0 +1,268 @@ +# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import re +import select +import socket +import struct +import time +from threading import Event, Thread + +import dpkt +import dpkt.dns +import ttfw_idf +from tiny_test_fw.Utility import console_log + +UDP_PORT = 5353 +MCAST_GRP = '224.0.0.251' + +# This service is created from esp board startup +SERVICE_NAME = u'ESP32-WebServer._http._tcp.local' +SUB_SERVICE_NAME = u'_server._sub._http._tcp.local' + +# This host name answer sent by host, when there is query from board +HOST_NAME = u'tinytester.local' + +# This servce answer sent by host, when there is query from board +MDNS_HOST_SERVICE = u'ESP32._http._tcp.local' + +stop_mdns_listener = Event() +start_mdns_listener = Event() +esp_service_answered = Event() +esp_sub_service_answered = Event() +esp_host_answered = Event() +esp_delegated_host_answered = Event() + + +# Get query of ESP32-WebServer._http._tcp.local service +def get_mdns_service_query(service): # type:(str) -> dpkt.dns.Msg + dns = dpkt.dns.DNS() + dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA + dns.rcode = dpkt.dns.DNS_RCODE_NOERR + arr = dpkt.dns.DNS.RR() + arr.cls = dpkt.dns.DNS_IN + arr.type = dpkt.dns.DNS_SRV + arr.name = service + arr.target = socket.inet_aton('127.0.0.1') + arr.srvname = service + dns.qd.append(arr) + console_log('Created mdns service query: {} '.format(dns.__repr__())) + return dns.pack() + + +# Get query of _server_.sub._http._tcp.local sub service +def get_mdns_sub_service_query(sub_service): # type:(str) -> dpkt.dns.Msg + dns = dpkt.dns.DNS() + dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA + dns.rcode = dpkt.dns.DNS_RCODE_NOERR + arr = dpkt.dns.DNS.RR() + arr.cls = dpkt.dns.DNS_IN + arr.type = dpkt.dns.DNS_PTR + arr.name = sub_service + arr.target = socket.inet_aton('127.0.0.1') + arr.ptrname = sub_service + dns.qd.append(arr) + console_log('Created mdns subtype service query: {} '.format(dns.__repr__())) + return dns.pack() + + +# Get query for host resolution +def get_dns_query_for_esp(esp_host): # type:(str) -> dpkt.dns.Msg + dns = dpkt.dns.DNS() + arr = dpkt.dns.DNS.RR() + arr.cls = dpkt.dns.DNS_IN + arr.name = esp_host + u'.local' + dns.qd.append(arr) + console_log('Created query for esp host: {} '.format(dns.__repr__())) + return dns.pack() + + +# Get mdns answer for host resoloution +def get_dns_answer_to_mdns(tester_host): # type:(str) -> dpkt.dns.Msg + dns = dpkt.dns.DNS() + dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA + dns.rcode = dpkt.dns.DNS_RCODE_NOERR + arr = dpkt.dns.DNS.RR() + arr.cls = dpkt.dns.DNS_IN + arr.type = dpkt.dns.DNS_A + arr.name = tester_host + arr.ip = socket.inet_aton('127.0.0.1') + dns. an.append(arr) + console_log('Created answer to mdns query: {} '.format(dns.__repr__())) + return dns.pack() + + +# Get mdns answer for service query +def get_dns_answer_to_service_query(mdns_service): # type:(str) -> dpkt.dns.Msg + dns = dpkt.dns.DNS() + dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA + dns.rcode = dpkt.dns.DNS_RCODE_NOERR + arr = dpkt.dns.DNS.RR() + arr.name = mdns_service + arr.cls = dpkt.dns.DNS_IN + arr.type = dpkt.dns.DNS_SRV + arr.priority = 0 + arr.weight = 0 + arr.port = 100 + arr.srvname = mdns_service + arr.ip = socket.inet_aton('127.0.0.1') + dns. an.append(arr) + console_log('Created answer to mdns query: {} '.format(dns.__repr__())) + return dns.pack() + + +def mdns_listener(esp_host): # type:(str) -> None + print('mdns_listener thread started') + + UDP_IP = '0.0.0.0' + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + sock.setblocking(False) + sock.bind((UDP_IP,UDP_PORT)) + mreq = struct.pack('4sl', socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + last_query_timepoint = time.time() + QUERY_TIMEOUT = 0.2 + while not stop_mdns_listener.is_set(): + try: + start_mdns_listener.set() + current_time = time.time() + if current_time - last_query_timepoint > QUERY_TIMEOUT: + last_query_timepoint = current_time + timeout = max(0, QUERY_TIMEOUT - (current_time - last_query_timepoint)) + read_socks, _, _ = select.select([sock], [], [], timeout) + if not read_socks: + continue + data, _ = sock.recvfrom(1024) + dns = dpkt.dns.DNS(data) + if len(dns.qd) > 0: + if dns.qd[0].name == HOST_NAME: + console_log('Received query: {} '.format(dns.__repr__())) + sock.sendto(get_dns_answer_to_mdns(HOST_NAME), (MCAST_GRP,UDP_PORT)) + if dns.qd[0].name == HOST_NAME: + console_log('Received query: {} '.format(dns.__repr__())) + sock.sendto(get_dns_answer_to_mdns(HOST_NAME), (MCAST_GRP,UDP_PORT)) + if dns.qd[0].name == MDNS_HOST_SERVICE: + print(dns.qd[0].name) + console_log('Received query: {} '.format(dns.__repr__())) + sock.sendto(get_dns_answer_to_service_query(MDNS_HOST_SERVICE), (MCAST_GRP,UDP_PORT)) + if len(dns.an) == 1: + if dns.an[0].name == SERVICE_NAME: + console_log('Received answer to service query: {}'.format(dns.__repr__())) + esp_service_answered.set() + if len(dns.an) > 1: + if dns.an[1].name == SUB_SERVICE_NAME: + console_log('Received answer for sub service query: {}'.format(dns.__repr__())) + esp_sub_service_answered.set() + if len(dns.an) > 0 and dns.an[0].type == dpkt.dns.DNS_A: + if dns.an[0].name == esp_host + u'.local': + console_log('Received answer to esp32-mdns query: {}'.format(dns.__repr__())) + esp_host_answered.set() + if dns.an[0].name == esp_host + u'-delegated.local': + console_log('Received answer to esp32-mdns-delegate query: {}'.format(dns.__repr__())) + esp_delegated_host_answered.set() + except socket.timeout: + break + except dpkt.UnpackError: + continue + + +def create_socket(): # type:() -> socket.socket + UDP_IP = '0.0.0.0' + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + sock.setblocking(False) + sock.bind((UDP_IP,UDP_PORT)) + mreq = struct.pack('4sl', socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + return sock + + +def test_query_dns_http_service(service): # type: (str) -> None + print('SRV: Query {}'.format(service)) + sock = create_socket() + sock.sendto(get_mdns_service_query(service), (MCAST_GRP,UDP_PORT)) + if not esp_service_answered.wait(timeout=25): + raise ValueError('Test has failed: did not receive mdns answer within timeout') + + +def test_query_dns_sub_service(sub_service): # type: (str) -> None + print('PTR: Query {}'.format(sub_service)) + sock = create_socket() + sock.sendto(get_mdns_sub_service_query(sub_service), (MCAST_GRP,UDP_PORT)) + if not esp_sub_service_answered.wait(timeout=25): + raise ValueError('Test has failed: did not receive mdns answer within timeout') + + +def test_query_dns_host(esp_host): # type: (str) -> None + print('A: {}'.format(esp_host)) + sock = create_socket() + sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT)) + if not esp_host_answered.wait(timeout=25): + raise ValueError('Test has failed: did not receive mdns answer within timeout') + + +def test_query_dns_host_delegated(esp_host): # type: (str) -> None + print('A: {}'.format(esp_host)) + sock = create_socket() + sock.sendto(get_dns_query_for_esp(esp_host + '-delegated'), (MCAST_GRP,UDP_PORT)) + if not esp_delegated_host_answered.wait(timeout=25): + raise ValueError('Test has failed: did not receive mdns answer within timeout') + + +@ttfw_idf.idf_custom_test(env_tag='Example_WIFI', group='test-apps') +def test_app_esp_mdns(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None + dut1 = env.get_dut('mdns', 'tools/test_apps/protocols/mdns', dut_class=ttfw_idf.ESP32DUT) + + # 1. start mdns application + dut1.start_app() + # 2. get the dut host name (and IP address) + specific_host = dut1.expect(re.compile(r'mdns hostname set to: \[([^\]]+)\]'), timeout=30)[0] + + esp_ip = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) + print('Got IP={}'.format(esp_ip[0])) + + mdns_responder = Thread(target=mdns_listener, args=(str(specific_host),)) + + def start_case(case, desc, result): # type: (str, str, str) -> None + print('Starting {}: {}'.format(case, desc)) + dut1.write(case) + dut1.expect(re.compile(result), timeout=10) + + try: + # start dns listener thread + mdns_responder.start() + + # wait untill mdns listener thred started + if not start_mdns_listener.wait(timeout=5): + raise ValueError('Test has failed: mdns listener thread did not start') + + # query dns service from host, answer should be received from esp board + test_query_dns_http_service(SERVICE_NAME) + + # query dns sub-service from host, answer should be received from esp board + test_query_dns_sub_service(SUB_SERVICE_NAME) + + # query dns host name, answer should be received from esp board + test_query_dns_host(specific_host) + + # query dns host name delegated, answer should be received from esp board + test_query_dns_host_delegated(specific_host) + + # query dns-host from esp board, answer should be received from host + start_case('CONFIG_TEST_QUERY_HOST', 'Query tinytester.local', 'tinytester.local resolved to: 127.0.0.1') + + # query dns-host aynchrounusely from esp board, answer should be received from host + start_case('CONFIG_TEST_QUERY_HOST_ASYNC', 'Query tinytester.local async', 'Async query resolved to A:127.0.0.1') + + # query service from esp board, answer should be received from host + start_case('CONFIG_TEST_QUERY_SERVICE', 'Query SRV ESP32._http._tcp.local', 'SRV:ESP32') + finally: + stop_mdns_listener.set() + mdns_responder.join() + + +if __name__ == '__main__': + test_app_esp_mdns() diff --git a/tools/test_apps/protocols/mdns/main/CMakeLists.txt b/tools/test_apps/protocols/mdns/main/CMakeLists.txt new file mode 100644 index 000000000..b5902d589 --- /dev/null +++ b/tools/test_apps/protocols/mdns/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" "mdns_test.c" + INCLUDE_DIRS ".") diff --git a/tools/test_apps/protocols/mdns/main/Kconfig.projbuild b/tools/test_apps/protocols/mdns/main/Kconfig.projbuild new file mode 100644 index 000000000..d5d791a70 --- /dev/null +++ b/tools/test_apps/protocols/mdns/main/Kconfig.projbuild @@ -0,0 +1,28 @@ +menu "Example Configuration" + + config TEST_MDNS_HOSTNAME + string "mDNS Hostname" + default "esp32-mdns" + help + mDNS Hostname for example to use + + config TEST_MDNS_INSTANCE + string "mDNS Instance Name" + default "ESP32 with mDNS" + help + mDNS Instance Name for example to use + + config TEST_MDNS_PUBLISH_DELEGATE_HOST + bool "Publish a delegated host" + help + Enable publishing a delegated host other than ESP32. + The example will also add a mock service for this host. + + config TEST_MDNS_ADD_MAC_TO_HOSTNAME + bool "Add mac suffix to hostname" + default n + help + If enabled, a portion of MAC address is added to the hostname, this is used + for evaluation of tests in CI + +endmenu diff --git a/tools/test_apps/protocols/mdns/main/main.c b/tools/test_apps/protocols/mdns/main/main.c new file mode 100644 index 000000000..cb647aa54 --- /dev/null +++ b/tools/test_apps/protocols/mdns/main/main.c @@ -0,0 +1,117 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_system.h" +#include "nvs_flash.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "esp_log.h" +#include "protocol_examples_common.h" +#include "mdns.h" + +static const char *TAG = "MDNS_TEST"; +void mdns_test(char *line); + +static void get_string(char *line, size_t size) +{ + int count = 0; + while (count < size) { + int c = fgetc(stdin); + if (c == '\n') { + line[count] = '\0'; + break; + } else if (c > 0 && c < 127) { + line[count] = c; + ++count; + } + vTaskDelay(50 / portTICK_PERIOD_MS); + } +} + +/** Generate host name based on sdkconfig, optionally adding a portion of MAC address to it. + * @return host name string allocated from the heap + */ +static char* generate_hostname(void) +{ +#ifndef CONFIG_TEST_MDNS_ADD_MAC_TO_HOSTNAME + return strdup(CONFIG_TEST_MDNS_HOSTNAME); +#else + uint8_t mac[6]; + char *hostname; + esp_read_mac(mac, ESP_MAC_WIFI_STA); + if (-1 == asprintf(&hostname, "%s-%02X%02X%02X", CONFIG_TEST_MDNS_HOSTNAME, mac[3], mac[4], mac[5])) { + abort(); + } + return hostname; +#endif +} + +static void initialise_mdns(void) +{ + char * hostname = generate_hostname(); + + //initialize mDNS + ESP_ERROR_CHECK( mdns_init() ); + + //set mDNS hostname (required if you want to advertise services) + ESP_ERROR_CHECK( mdns_hostname_set(hostname) ); + + ESP_LOGI(TAG, "mdns hostname set to: [%s]", hostname); + //set default mDNS instance name + ESP_ERROR_CHECK( mdns_instance_name_set(CONFIG_TEST_MDNS_INSTANCE) ); + + //initialize service + ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, NULL, 0) ); + +#if CONFIG_TEST_MDNS_PUBLISH_DELEGATE_HOST + char *delegated_hostname; + if (-1 == asprintf(&delegated_hostname, "%s-delegated", hostname)) { + abort(); + } + + mdns_ip_addr_t addr4, addr6; + esp_netif_str_to_ip4("10.0.0.1", &addr4.addr.u_addr.ip4); + addr4.addr.type = ESP_IPADDR_TYPE_V4; + esp_netif_str_to_ip6("fd11:22::1", &addr6.addr.u_addr.ip6); + addr6.addr.type = ESP_IPADDR_TYPE_V6; + addr4.next = &addr6; + addr6.next = NULL; + ESP_ERROR_CHECK( mdns_delegate_hostname_add(delegated_hostname, &addr4) ); + ESP_ERROR_CHECK( mdns_service_add_for_host("test0", "_http", "_tcp", delegated_hostname, 1234, NULL, 0) ); + free(delegated_hostname); +#endif // CONFIG_TEST_MDNS_PUBLISH_DELEGATE_HOST + + ESP_ERROR_CHECK( mdns_service_subtype_add_for_host("ESP32-WebServer", "_http", "_tcp", NULL, "_server") ); + + free(hostname); +} + +void app_main(void) +{ + char line[256]; + + ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); + ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); + + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + initialise_mdns(); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + while (1) { + get_string(line, sizeof(line)); + mdns_test(line); + continue; + } +} diff --git a/tools/test_apps/protocols/mdns/main/mdns_test.c b/tools/test_apps/protocols/mdns/main/mdns_test.c new file mode 100644 index 000000000..545988516 --- /dev/null +++ b/tools/test_apps/protocols/mdns/main/mdns_test.c @@ -0,0 +1,166 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "mdns.h" +#include "esp_log.h" +#include "esp_netif.h" + +static const char * TAG = "MDNS_TEST_APP"; + +static void mdns_print_results(mdns_result_t *results) +{ + mdns_result_t *r = results; + mdns_ip_addr_t *a = NULL; + int t; + while (r) { + if (r->instance_name) { + printf("PTR:%s.%s.%s\n", r->instance_name, r->service_type, r->proto); + } + if (r->hostname) { + printf("SRV:%s.local:%u\n", r->hostname, r->port); + } + if (r->txt_count) { + printf("TXT:[%zu] ", r->txt_count); + for (t = 0; t < r->txt_count; t++) { + printf("%s=%s(%d); ", r->txt[t].key, r->txt[t].value ? r->txt[t].value : "NULL", r->txt_value_len[t]); + } + printf("\n"); + } + a = r->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + r = r->next; + } +} + +static bool check_and_print_result(mdns_search_once_t *search) +{ + // Check if any result is available + mdns_result_t * result = NULL; + if (!mdns_query_async_get_results(search, 0, &result)) { + return false; + } + + if (!result) { // search timeout, but no result + return true; + } + + // If yes, print the result + mdns_ip_addr_t * a = result->addr; + while (a) { + if(a->addr.type == ESP_IPADDR_TYPE_V6){ + printf("Async query resolved to AAAA:" IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf("Async query resolved to A:" IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + // and free the result + mdns_query_results_free(result); + return true; +} + +static void query_mdns_hosts_async(const char * host_name) +{ + ESP_LOGI(TAG, "Query both A and AAA: %s.local", host_name); + + mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1, NULL); + mdns_query_async_delete(s_a); + mdns_search_once_t *s_aaaa = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_AAAA, 1000, 1, NULL); + while (s_a || s_aaaa) { + if (s_a && check_and_print_result(s_a)) { + ESP_LOGI(TAG, "Query A %s.local finished", host_name); + mdns_query_async_delete(s_a); + s_a = NULL; + } + if (s_aaaa && check_and_print_result(s_aaaa)) { + ESP_LOGI(TAG, "Query AAAA %s.local finished", host_name); + mdns_query_async_delete(s_aaaa); + s_aaaa = NULL; + } + } +} + +static void query_mdns_host(const char * host_name) +{ + ESP_LOGI(TAG, "Query A: %s.local", host_name); + + struct esp_ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(host_name, 2000, &addr); + if(err){ + if(err == ESP_ERR_NOT_FOUND){ + ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err)); + return; + } + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); + return; + } + + ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr)); +} + +static void query_mdns_service(const char * instance, const char * service_name, const char * proto) +{ + ESP_LOGI(TAG, "Query SRV: %s.%s.local", service_name, proto); + + mdns_result_t * results = NULL; + esp_err_t err = mdns_query_srv(instance, service_name, proto, 3000, &results); + if(err){ + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); + return; + } + if(!results){ + ESP_LOGW(TAG, "No results found!"); + return; + } + + mdns_print_results(results); + mdns_query_results_free(results); +} + +void query_mdns_service_sub_type(const char * subtype, const char * service_name, const char * proto) { + ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); + + mdns_result_t * results = NULL; + esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); + if(err){ + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); + return; + } + if(!results){ + ESP_LOGW(TAG, "No results found!"); + return; + } + + mdns_print_results(results); + mdns_query_results_free(results); +} + +void mdns_test(const char *line) +{ + char test_case[32]; + + sscanf(line, "%s", test_case); + ESP_LOGI(TAG, "test case = %s", test_case); + + if (strcmp(test_case, "CONFIG_TEST_QUERY_HOST") == 0) { + query_mdns_host("tinytester"); + } else if (strcmp(test_case, "CONFIG_TEST_QUERY_HOST_ASYNC") == 0) { + query_mdns_hosts_async("tinytester"); + } else if (strcmp(test_case, "CONFIG_TEST_QUERY_SERVICE") == 0) { + query_mdns_service("ESP32", "_http", "_tcp"); + } else { + ESP_LOGE(TAG, "%s: No such test case", test_case); + } +} diff --git a/tools/test_apps/protocols/mdns/sdkconfig.defaults b/tools/test_apps/protocols/mdns/sdkconfig.defaults new file mode 100644 index 000000000..0c4ffe915 --- /dev/null +++ b/tools/test_apps/protocols/mdns/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_TEST_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_TEST_MDNS_PUBLISH_DELEGATE_HOST=y From 69902ea8e12cbb9c7cb254ee221af68c408ff636 Mon Sep 17 00:00:00 2001 From: zhangwenxu Date: Fri, 26 Nov 2021 17:27:18 +0800 Subject: [PATCH 229/289] mdns: support multiple instance for mdns service txt set * Original commit: espressif/esp-idf@50f6302c5d7c0498fa1baa6fd6129d8233971a81 --- components/mdns/include/mdns.h | 21 ++++++++++----- components/mdns/mdns.c | 49 +++++++++++++++------------------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 8c58687b5..ff0d76b09 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -269,6 +269,7 @@ esp_err_t mdns_service_remove(const char * service_type, const char * proto); /** * @brief Remove service from mDNS server with hostname * + * @param instance instance name * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param hostname service hostname. If NULL, local hostname will be used. @@ -279,7 +280,7 @@ esp_err_t mdns_service_remove(const char * service_type, const char * proto); * - ESP_ERR_NOT_FOUND Service not found * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_service_remove_for_host(const char * service_type, const char * proto, const char *hostname); +esp_err_t mdns_service_remove_for_host(const char *instance, const char * service_type, const char * proto, const char *hostname); /** * @brief Set instance name for service @@ -299,6 +300,7 @@ esp_err_t mdns_service_instance_name_set(const char * service_type, const char * /** * @brief Set instance name for service with hostname * + * @param instance_old original instance name * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param hostname service hostname. If NULL, local hostname will be used. @@ -310,7 +312,7 @@ esp_err_t mdns_service_instance_name_set(const char * service_type, const char * * - ESP_ERR_NOT_FOUND Service not found * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_service_instance_name_set_for_host(const char * service_type, const char * proto, const char * hostname, +esp_err_t mdns_service_instance_name_set_for_host(const char * instance_old, const char * service_type, const char * proto, const char * hostname, const char * instance_name); /** @@ -332,6 +334,7 @@ esp_err_t mdns_service_port_set(const char * service_type, const char * proto, u /** * @brief Set service port with hostname * + * @param instance instance name * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param hostname service hostname. If NULL, local hostname will be used. @@ -343,7 +346,7 @@ esp_err_t mdns_service_port_set(const char * service_type, const char * proto, u * - ESP_ERR_NOT_FOUND Service not found * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_service_port_set_for_host(const char * service_type, const char * proto, const char * hostname, +esp_err_t mdns_service_port_set_for_host(const char * instance, const char * service_type, const char * proto, const char * hostname, uint16_t port); /** @@ -369,6 +372,7 @@ esp_err_t mdns_service_txt_set(const char * service_type, const char * proto, md * * @note The value length of txt items will be automatically decided by strlen * + * @param instance instance name * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param hostname service hostname. If NULL, local hostname will be used. @@ -381,7 +385,7 @@ esp_err_t mdns_service_txt_set(const char * service_type, const char * proto, md * - ESP_ERR_NOT_FOUND Service not found * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_service_txt_set_for_host(const char * service_type, const char * proto, const char * hostname, +esp_err_t mdns_service_txt_set_for_host(const char * instance, const char * service_type, const char * proto, const char * hostname, mdns_txt_item_t txt[], uint8_t num_items); /** @@ -425,6 +429,7 @@ esp_err_t mdns_service_txt_item_set_with_explicit_value_len(const char *service_ * * @note The value length will be automatically decided by strlen * + * @param instance instance name * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param hostname service hostname. If NULL, local hostname will be used. @@ -437,12 +442,13 @@ esp_err_t mdns_service_txt_item_set_with_explicit_value_len(const char *service_ * - ESP_ERR_NOT_FOUND Service not found * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_service_txt_item_set_for_host(const char * service_type, const char * proto, const char * hostname, +esp_err_t mdns_service_txt_item_set_for_host(const char * instance, const char * service_type, const char * proto, const char * hostname, const char * key, const char * value); /** * @brief Set/Add TXT item for service TXT record with hostname and txt value length * + * @param instance instance name * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param hostname service hostname. If NULL, local hostname will be used. @@ -456,7 +462,7 @@ esp_err_t mdns_service_txt_item_set_for_host(const char * service_type, const ch * - ESP_ERR_NOT_FOUND Service not found * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char *service_type, const char *proto, +esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char * instance, const char *service_type, const char *proto, const char *hostname, const char *key, const char *value, uint8_t value_len); @@ -478,6 +484,7 @@ esp_err_t mdns_service_txt_item_remove(const char * service_type, const char * p /** * @brief Remove TXT item for service TXT record with hostname * + * @param instance instance name * @param service_type service type (_http, _ftp, etc) * @param proto service protocol (_tcp, _udp) * @param hostname service hostname. If NULL, local hostname will be used. @@ -489,7 +496,7 @@ esp_err_t mdns_service_txt_item_remove(const char * service_type, const char * p * - ESP_ERR_NOT_FOUND Service not found * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_service_txt_item_remove_for_host(const char * service_type, const char * proto, const char * hostname, +esp_err_t mdns_service_txt_item_remove_for_host(const char * instance, const char * service_type, const char * proto, const char * hostname, const char * key); /** diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 351b5c169..988a15fc4 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -5131,11 +5131,7 @@ esp_err_t mdns_service_add_for_host(const char * instance, const char * service, return ESP_ERR_NO_MEM; } -#if CONFIG_MDNS_MULTIPLE_INSTANCE mdns_srv_item_t * item = _mdns_get_service_item_instance(instance, service, proto, hostname); -#else - mdns_srv_item_t * item = _mdns_get_service_item(service, proto, hostname); -#endif // CONFIG_MDNS_MULTIPLE_INSTANCE if (item) { return ESP_ERR_INVALID_ARG; } @@ -5173,7 +5169,7 @@ esp_err_t mdns_service_add_for_host(const char * instance, const char * service, size_t start = xTaskGetTickCount(); size_t timeout_ticks = pdMS_TO_TICKS(MDNS_SERVICE_ADD_TIMEOUT_MS); - while (_mdns_get_service_item(service, proto, hostname) == NULL) { + while (_mdns_get_service_item_instance(instance, service, proto, hostname) == NULL) { uint32_t expired = xTaskGetTickCount() - start; if (expired >= timeout_ticks) { return ESP_FAIL; // Timeout @@ -5204,12 +5200,12 @@ bool mdns_service_exists_with_instance(const char *instance, const char *service return _mdns_get_service_item_instance(instance, service_type, proto, hostname) != NULL; } -esp_err_t mdns_service_port_set_for_host(const char * service, const char * proto, const char * hostname, uint16_t port) +esp_err_t mdns_service_port_set_for_host(const char *instance, const char * service, const char * proto, const char * hostname, uint16_t port) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); + mdns_srv_item_t * s = _mdns_get_service_item_instance(instance, service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -5234,16 +5230,16 @@ esp_err_t mdns_service_port_set(const char * service, const char * proto, uint16 if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_port_set_for_host(service, proto, _mdns_server->hostname, port); + return mdns_service_port_set_for_host(NULL, service, proto, _mdns_server->hostname, port); } -esp_err_t mdns_service_txt_set_for_host(const char * service, const char * proto, const char * hostname, +esp_err_t mdns_service_txt_set_for_host(const char * instance, const char * service, const char * proto, const char * hostname, mdns_txt_item_t txt[], uint8_t num_items) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || (num_items && txt == NULL)) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); + mdns_srv_item_t * s = _mdns_get_service_item_instance(instance, service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -5279,10 +5275,10 @@ esp_err_t mdns_service_txt_set(const char * service, const char * proto, mdns_tx if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_txt_set_for_host(service, proto, _mdns_server->hostname, txt, num_items); + return mdns_service_txt_set_for_host(NULL, service, proto, _mdns_server->hostname, txt, num_items); } -esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char *service, const char *proto, +esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char * instance, const char *service, const char *proto, const char *hostname, const char *key, const char *value, uint8_t value_len) { @@ -5290,7 +5286,7 @@ esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char _str_null_or_empty(key) || !value) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t *s = _mdns_get_service_item(service, proto, hostname); + mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -5324,10 +5320,10 @@ esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char return ESP_OK; } -esp_err_t mdns_service_txt_item_set_for_host(const char *service, const char *proto, const char *hostname, +esp_err_t mdns_service_txt_item_set_for_host(const char * instance, const char *service, const char *proto, const char *hostname, const char *key, const char *value) { - return mdns_service_txt_item_set_for_host_with_explicit_value_len(service, proto, hostname, key, value, + return mdns_service_txt_item_set_for_host_with_explicit_value_len(instance, service, proto, hostname, key, value, strlen(value)); } @@ -5337,7 +5333,7 @@ esp_err_t mdns_service_txt_item_set(const char *service, const char *proto, cons if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_txt_item_set_for_host_with_explicit_value_len(service, proto, _mdns_server->hostname, key, + return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, _mdns_server->hostname, key, value, strlen(value)); } @@ -5347,17 +5343,17 @@ esp_err_t mdns_service_txt_item_set_with_explicit_value_len(const char *service, if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_txt_item_set_for_host_with_explicit_value_len(service, proto, _mdns_server->hostname, key, + return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, _mdns_server->hostname, key, value, value_len); } -esp_err_t mdns_service_txt_item_remove_for_host(const char * service, const char * proto, const char * hostname, +esp_err_t mdns_service_txt_item_remove_for_host(const char * instance, const char * service, const char * proto, const char * hostname, const char * key) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(key)) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); + mdns_srv_item_t * s = _mdns_get_service_item_instance(instance, service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -5387,7 +5383,7 @@ esp_err_t mdns_service_txt_item_remove(const char * service, const char * proto, if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_txt_item_remove_for_host(service, proto, _mdns_server->hostname, key); + return mdns_service_txt_item_remove_for_host(NULL, service, proto, _mdns_server->hostname, key); } esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const char *service, const char *proto, @@ -5398,7 +5394,6 @@ esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const cha return ESP_ERR_INVALID_ARG; } mdns_srv_item_t * s = _mdns_get_service_item_instance(instance_name, service, proto, hostname); - if (!s) { return ESP_ERR_NOT_FOUND; } @@ -5424,7 +5419,7 @@ esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const cha return ESP_OK; } -esp_err_t mdns_service_instance_name_set_for_host(const char * service, const char * proto, const char * hostname, +esp_err_t mdns_service_instance_name_set_for_host(const char * instance_old, const char * service, const char * proto, const char * hostname, const char * instance) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { @@ -5433,7 +5428,7 @@ esp_err_t mdns_service_instance_name_set_for_host(const char * service, const ch if (_str_null_or_empty(instance) || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); + mdns_srv_item_t * s = _mdns_get_service_item_instance(instance_old, service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -5464,15 +5459,15 @@ esp_err_t mdns_service_instance_name_set(const char * service, const char * prot if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_instance_name_set_for_host(service, proto, _mdns_server->hostname, instance); + return mdns_service_instance_name_set_for_host(NULL, service, proto, _mdns_server->hostname, instance); } -esp_err_t mdns_service_remove_for_host(const char * service, const char * proto, const char * hostname) +esp_err_t mdns_service_remove_for_host(const char * instance, const char * service, const char * proto, const char * hostname) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto)) { return ESP_ERR_INVALID_ARG; } - mdns_srv_item_t * s = _mdns_get_service_item(service, proto, hostname); + mdns_srv_item_t * s = _mdns_get_service_item_instance(instance, service, proto, hostname); if (!s) { return ESP_ERR_NOT_FOUND; } @@ -5496,7 +5491,7 @@ esp_err_t mdns_service_remove(const char * service_type, const char * proto) if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } - return mdns_service_remove_for_host(service_type, proto, _mdns_server->hostname); + return mdns_service_remove_for_host(NULL, service_type, proto, _mdns_server->hostname); } esp_err_t mdns_service_remove_all(void) From f0839d909b34bed863b56e0914b1ed3534ba046e Mon Sep 17 00:00:00 2001 From: zhangwenxu Date: Thu, 16 Dec 2021 16:52:05 +0800 Subject: [PATCH 230/289] mdns: fix mdns server instance mismatch * Original commit: espressif/esp-idf@6173dd78097216261277c20ebd92a53c68c47f89 --- components/mdns/mdns.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 988a15fc4..bcea61117 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -293,8 +293,14 @@ static mdns_srv_item_t *_mdns_get_service_item_instance(const char *instance, co { mdns_srv_item_t *s = _mdns_server->services; while (s) { - if (_mdns_service_match_instance(s->service, instance, service, proto, hostname)) { - return s; + if (instance) { + if (_mdns_service_match_instance(s->service, instance, service, proto, hostname)) { + return s; + } + } else { + if (_mdns_service_match(s->service, service, proto, hostname)) { + return s; + } } s = s->next; } From 525c64915e9bdc83570807be554f0ae4546c588b Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Thu, 2 Dec 2021 12:33:10 +0100 Subject: [PATCH 231/289] Added results count to MDNS * Original commit: espressif/esp-idf@f391d610e8185631b5361dc6c844c4c04aac30b1 --- components/mdns/include/mdns.h | 2 +- components/mdns/mdns.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index ff0d76b09..4037fda6c 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -551,7 +551,7 @@ esp_err_t mdns_query_async_delete(mdns_search_once_t* search); * True if search has finished before or at timeout * False if search timeout is over */ -bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, mdns_result_t ** results); +bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, mdns_result_t ** results, uint8_t * num_results); /** * @brief Query mDNS for host or service asynchronousely. diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index bcea61117..cb150ebee 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -5573,10 +5573,15 @@ esp_err_t mdns_query_async_delete(mdns_search_once_t* search) return ESP_OK; } -bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, mdns_result_t ** results) +bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, mdns_result_t ** results, uint8_t * num_results) { if (xSemaphoreTake(search->done_semaphore, pdMS_TO_TICKS(timeout)) == pdTRUE) { - *results = search->result; + if (results) { + *results = search->result; + } + if (num_results) { + *num_results = search->num_results; + } return true; } return false; From 941dc5c42fff4a884febff13505b191d93e75c42 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 10 Dec 2021 10:30:13 +0100 Subject: [PATCH 232/289] mdns: Minor fix of API description and API usage * Original commit: espressif/esp-idf@c297301ecc350f8315d7eaf78c72b4aba68d422a --- components/mdns/include/mdns.h | 1 + examples/protocols/mdns/main/mdns_example_main.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 4037fda6c..40ad12673 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -546,6 +546,7 @@ esp_err_t mdns_query_async_delete(mdns_search_once_t* search); * @param search pointer to search object * @param timeout time in milliseconds to wait for answers * @param results pointer to the results of the query + * @param num_results pointer to the number of the actual result items (set to NULL to ignore this return value) * * @return * True if search has finished before or at timeout diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index f53e06031..94e9140ea 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -146,7 +146,7 @@ static bool check_and_print_result(mdns_search_once_t *search) { // Check if any result is available mdns_result_t * result = NULL; - if (!mdns_query_async_get_results(search, 0, &result)) { + if (!mdns_query_async_get_results(search, 0, &result, NULL)) { return false; } From d0f4e68c7a33bb51fbe3513c2f0fb6a07214a2ea Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 16 Dec 2021 22:46:53 +0100 Subject: [PATCH 233/289] mdns: Unbreak test app cauased by async API change Regression from 81d496ace9080fcd97df3cc7e9ce279531d67a48 * Original commit: espressif/esp-idf@c0d08faf918a08bd54524115e64966c3106e0e1d --- tools/test_apps/protocols/mdns/main/mdns_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/test_apps/protocols/mdns/main/mdns_test.c b/tools/test_apps/protocols/mdns/main/mdns_test.c index 545988516..effff0a3c 100644 --- a/tools/test_apps/protocols/mdns/main/mdns_test.c +++ b/tools/test_apps/protocols/mdns/main/mdns_test.c @@ -46,7 +46,7 @@ static bool check_and_print_result(mdns_search_once_t *search) { // Check if any result is available mdns_result_t * result = NULL; - if (!mdns_query_async_get_results(search, 0, &result)) { + if (!mdns_query_async_get_results(search, 0, &result, NULL)) { return false; } From ae381b779f0680af96a033cb06a915b0075be2c2 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 7 Dec 2021 16:17:53 +0100 Subject: [PATCH 234/289] mdns: Fix potential null deref reported by fuzzer test * Original commit: espressif/esp-idf@cb5653fd940a9cd41e8554a6d753fab46e0459d7 --- components/mdns/mdns.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index cb150ebee..18c23d3fd 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2936,7 +2936,8 @@ static bool _mdns_question_matches(mdns_parsed_question_t * question, uint16_t t if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { return true; } else if (type == MDNS_TYPE_PTR || type == MDNS_TYPE_SDPTR) { - if (!strcasecmp(service->service->service, question->service) + if (question->service && question->proto && question->domain + && !strcasecmp(service->service->service, question->service) && !strcasecmp(service->service->proto, question->proto) && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { return true; From 7e82a7cef786121e03fe504b467ce8994576bd4e Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Fri, 3 Dec 2021 17:59:04 +0800 Subject: [PATCH 235/289] mdns: filter instance name for ANY queries The instance name in ANY quries was ignored. The MR fixes the issue. * Original commit: espressif/esp-idf@5d0c47303dd9ead0f2ad291dca1d4b7ce4e23b2b --- components/mdns/mdns.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 18c23d3fd..d793a1ffc 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1540,6 +1540,8 @@ static bool _mdns_service_match_ptr_question(const mdns_service_t *service, cons if (!_mdns_service_match(service, question->service, question->proto, NULL)) { return false; } + // The question parser stores anything before _type._proto in question->host + // So the question->host can be subtype or instance name based on its content if (question->sub) { mdns_subtype_t *subtype = service->subtype; while (subtype) { @@ -1550,6 +1552,11 @@ static bool _mdns_service_match_ptr_question(const mdns_service_t *service, cons } return false; } + if (question->host) { + if (strcasecmp(service->instance, question->host) != 0) { + return false; + } + } return true; } From 7dd0bc1fff618778ee1f008f31ca859051510ea6 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Fri, 3 Dec 2021 17:50:57 +0800 Subject: [PATCH 236/289] mdns: always send A/AAAA records in announcements * Original commit: espressif/esp-idf@456f80b754ebd0bd74e02c7febdf461c6b573b7a --- components/mdns/mdns.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index d793a1ffc..fc31e6726 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1850,7 +1850,6 @@ static mdns_tx_packet_t * _mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ */ static mdns_tx_packet_t * _mdns_create_announce_from_probe(mdns_tx_packet_t * probe) { - mdns_tx_packet_t * packet = _mdns_alloc_packet_default(probe->tcpip_if, probe->ip_protocol); if (!packet) { return NULL; @@ -1867,6 +1866,12 @@ static mdns_tx_packet_t * _mdns_create_announce_from_probe(mdns_tx_packet_t * pr _mdns_free_tx_packet(packet); return NULL; } + mdns_host_item_t *host = mdns_get_host_item(s->service->hostname); + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } } else if (s->type == MDNS_TYPE_A || s->type == MDNS_TYPE_AAAA) { if (!_mdns_alloc_answer(&packet->answers, s->type, NULL, s->host, true, false)) { From 076c095aec367ccc926177b33882985480f0cd65 Mon Sep 17 00:00:00 2001 From: caffreyfans Date: Thu, 16 Dec 2021 14:10:52 +0800 Subject: [PATCH 237/289] unified errno format * Original commit: espressif/esp-idf@87506f46e2922710f48a6b96ca75e53543ff45c4 --- components/mdns/mdns_networking_socket.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/components/mdns/mdns_networking_socket.c b/components/mdns/mdns_networking_socket.c index 55533a9f7..af07c912e 100644 --- a/components/mdns/mdns_networking_socket.c +++ b/components/mdns/mdns_networking_socket.c @@ -210,7 +210,7 @@ size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, c ESP_LOGD(TAG, "[sock=%d]: Sending to IP %s port %d", sock, get_string_address(&in_addr), port); ssize_t actual_len = sendto(sock, data, len, 0, (struct sockaddr *)&in_addr, ss_size); if (actual_len < 0) { - ESP_LOGE(TAG, "[sock=%d]: _mdns_udp_pcb_write sendto() has failed\n error=%d: %s", sock, errno, strerror(errno)); + ESP_LOGE(TAG, "[sock=%d]: _mdns_udp_pcb_write sendto() has failed\n errno=%d: %s", sock, errno, strerror(errno)); } return actual_len; } @@ -396,7 +396,7 @@ static int create_socket(esp_netif_t *netif) int sock = socket(PF_INET, SOCK_DGRAM, 0); #endif if (sock < 0) { - ESP_LOGE(TAG, "Failed to create socket. Error %d", errno); + ESP_LOGE(TAG, "Failed to create socket. errno %d", errno); return -1; } @@ -412,7 +412,7 @@ static int create_socket(esp_netif_t *netif) bzero(&saddr.sin6_addr.s6_addr, sizeof(saddr.sin6_addr.s6_addr)); int err = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in6)); if (err < 0) { - ESP_LOGE(TAG, "Failed to bind socket. Error %d", errno); + ESP_LOGE(TAG, "Failed to bind socket. errno %d", errno); goto err; } #else @@ -422,7 +422,7 @@ static int create_socket(esp_netif_t *netif) bzero(&saddr.sin_addr.s_addr, sizeof(saddr.sin_addr.s_addr)); int err = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)); if (err < 0) { - ESP_LOGE(TAG, "Failed to bind socket. Error %d", errno); + ESP_LOGE(TAG, "Failed to bind socket. errno %d", errno); goto err; } #endif // CONFIG_LWIP_IPV6 @@ -447,7 +447,7 @@ static int socket_add_ipv6_multicast_group(int sock, esp_netif_t *netif) int ifindex = esp_netif_get_netif_impl_index(netif); int err = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)); if (err < 0) { - ESP_LOGE(TAG, "Failed to set IPV6_MULTICAST_IF. Error %d", errno); + ESP_LOGE(TAG, "Failed to set IPV6_MULTICAST_IF. errno %d", errno); return err; } @@ -457,7 +457,7 @@ static int socket_add_ipv6_multicast_group(int sock, esp_netif_t *netif) v6imreq.ipv6mr_interface = ifindex; err = setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &v6imreq, sizeof(struct ipv6_mreq)); if (err < 0) { - ESP_LOGE(TAG, "Failed to set IPV6_ADD_MEMBERSHIP. Error %d", errno); + ESP_LOGE(TAG, "Failed to set IPV6_ADD_MEMBERSHIP. errno %d", errno); return err; } return err; @@ -482,7 +482,7 @@ static int socket_add_ipv4_multicast_group(int sock, esp_netif_t *netif) err = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imreq, sizeof(struct ip_mreq)); if (err < 0) { ESP_LOGE(TAG, "%d %s", sock, strerror(errno)); - ESP_LOGE(TAG, "Failed to set IP_ADD_MEMBERSHIP. Error %d", errno); + ESP_LOGE(TAG, "Failed to set IP_ADD_MEMBERSHIP. errno %d", errno); goto err; } From dfb27b39cc6d066bf12face3eaf7c14e0ed5114d Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 16 Dec 2021 16:00:44 +0100 Subject: [PATCH 238/289] mdns: Minor err print fix in socket-networking layer * Original commit: espressif/esp-idf@f1b8f5c1023df7d649161bc76f2bcc9a8f8f4d8b --- components/mdns/mdns_networking_socket.c | 39 +++++++++--------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/components/mdns/mdns_networking_socket.c b/components/mdns/mdns_networking_socket.c index af07c912e..45ad83dec 100644 --- a/components/mdns/mdns_networking_socket.c +++ b/components/mdns/mdns_networking_socket.c @@ -1,16 +1,8 @@ -// Copyright 2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /** * @brief MDNS Server Networking module implemented using BSD sockets @@ -272,7 +264,7 @@ void sock_recv_task(void* arg) int s = select(max_sock + 1, &rfds, NULL, NULL, &tv); if (s < 0) { - ESP_LOGE(TAG, "Select failed: errno %d", errno); + ESP_LOGE(TAG, "Select failed. errno=%d: %s", errno, strerror(errno)); break; } else if (s > 0) { for (int tcpip_if=0; tcpip_if Date: Tue, 28 Dec 2021 12:54:31 +0800 Subject: [PATCH 239/289] freertos: remove FREERTOS_ASSERT option Freertos asserts are now configured the same way as all other asserts in IDF, i.e. by configuring COMPILER_OPTIMIZATION_ASSERTION_LEVEL. * Original commit: espressif/esp-idf@72554971467a5edc9bd6e390cf8fe7b05e6ade81 --- components/mdns/test_afl_fuzz_host/sdkconfig.h | 1 - 1 file changed, 1 deletion(-) diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index ce264888c..6f24c6166 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -180,7 +180,6 @@ #define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 #define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 #define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 -#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 #define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 #define CONFIG_FREERTOS_ISR_STACKSIZE 1536 #define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 From 9de3f534e2581c48414fca0642ff635959754aaa Mon Sep 17 00:00:00 2001 From: caffreyfans Date: Fri, 17 Dec 2021 16:39:43 +0800 Subject: [PATCH 240/289] Add mDNS miss comment * Original commit: espressif/esp-idf@08e081340d9d76d1244e9f2dc527e5ae370b1fbe --- components/mdns/mdns.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index fc31e6726..590866bad 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2281,6 +2281,7 @@ static void _mdns_free_linked_txt(mdns_txt_linked_item_t *txt) * @brief creates/allocates new service * @param service service type * @param proto service proto + * @param hostname service hostname * @param port service port * @param instance service instance * @param num_items service number of txt items or 0 From 5a2d4eab6dd5865ecc1c6fd0944d0b041b0947b8 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 7 Jan 2022 16:16:31 +0100 Subject: [PATCH 241/289] mdns: Fix copyright * Original commit: espressif/esp-idf@c83678f64fe27844fc28050bde6433ccb04a0704 --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 590866bad..0faa0b509 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ From 01256d3e34dd06d8882172e2a1917e7ea4fe3ffa Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 4 Jan 2022 13:50:02 +0100 Subject: [PATCH 242/289] mdns: Make fuzzer layers compatible with llvm>=6 * Original commit: espressif/esp-idf@1882cbe44e6140bebb2d27dc18af06dfcb0157f5 --- .../mdns/test_afl_fuzz_host/esp32_mock.h | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h index 5acf53842..c1163e9b6 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.h @@ -1,16 +1,8 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP32_COMPAT_H_ #define _ESP32_COMPAT_H_ @@ -20,6 +12,7 @@ #define _ESP_TASK_H_ #ifdef USE_BSD_STRING +#include #include #endif #include From 7af91ec49050d3129cccb216898c16af459e661d Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 17 Dec 2021 15:17:58 +0100 Subject: [PATCH 243/289] mdns: Fix potential null deref for ANY query type * Original commit: espressif/esp-idf@99dd8eedb1a0e957f5f74344e3e4172e61c29ef8 --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 0faa0b509..f63037fe9 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4170,7 +4170,7 @@ static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * s, mdns_ continue; } if (s->type != MDNS_TYPE_PTR) { - if (!strcasecmp(name->host, s->instance)) { + if (s->instance && strcasecmp(name->host, s->instance) == 0) { return s; } s = s->next; From 4e11cc86fed167297c8f3dcb222d4ad6639641a3 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 17 Dec 2021 15:40:52 +0100 Subject: [PATCH 244/289] mdns: Allow for unicast PTR queries Adresses https://github.com/espressif/esp-idf/issues/7932 * Original commit: espressif/esp-idf@7eeeb01ea705745b027bd8bc11d2b142418e9927 --- components/mdns/include/mdns.h | 27 +++++++++++++++++-- components/mdns/mdns.c | 16 +++++++---- .../mdns/private_include/mdns_private.h | 3 ++- components/mdns/test_afl_fuzz_host/mdns_di.h | 8 +++--- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 40ad12673..959fab0ce 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -573,13 +573,36 @@ mdns_search_once_t *mdns_query_async_new(const char *name, const char *service_t uint32_t timeout, size_t max_results, mdns_query_notify_t notifier); /** - * @brief Query mDNS for host or service + * @brief Generic mDNS query * All following query methods are derived from this one * * @param name service instance or host name (NULL for PTR queries) * @param service_type service type (_http, _arduino, _ftp etc.) (NULL for host queries) * @param proto service protocol (_tcp, _udp, etc.) (NULL for host queries) * @param type type of query (MDNS_TYPE_*) + * @param unicast true for Unicast query, false for Multicast query + * @param timeout time in milliseconds to wait for answers. + * @param max_results maximum results to be collected + * @param results pointer to the results of the query + * results must be freed using mdns_query_results_free below + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG timeout was not given + */ +esp_err_t mdns_query_generic(const char * name, const char * service_type, const char * proto, uint16_t type, bool unicast, uint32_t timeout, size_t max_results, mdns_result_t ** results); + +/** + * @brief Query mDNS for host or service + * + * Note that querying PTR types sends Multicast query, all other types send Unicast queries + * + * @param name service instance or host name (NULL for PTR queries) + * @param service_type service type (_http, _arduino, _ftp etc.) (NULL for host queries) + * @param proto service protocol (_tcp, _udp, etc.) (NULL for host queries) + * @param type type of query (MDNS_TYPE_*) * @param timeout time in milliseconds to wait for answers. * @param max_results maximum results to be collected * @param results pointer to the results of the query diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index f63037fe9..0f027c5bb 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3786,7 +3786,7 @@ static void _mdns_search_free(mdns_search_once_t * search) /** * @brief Allocate new search structure */ -static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, +static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier) { mdns_search_once_t * search = (mdns_search_once_t *)malloc(sizeof(mdns_search_once_t)); @@ -3827,6 +3827,7 @@ static mdns_search_once_t *_mdns_search_init(const char *name, const char *servi } search->type = type; + search->unicast = unicast; search->timeout = timeout; search->num_results = 0; search->max_results = max_results; @@ -4207,7 +4208,7 @@ static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search return NULL; } q->next = NULL; - q->unicast = search->type != MDNS_TYPE_PTR; + q->unicast = search->unicast; q->type = search->type; q->host = search->instance; q->service = search->service; @@ -5610,7 +5611,7 @@ mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, return NULL; } - search = _mdns_search_init(name, service, proto, type, timeout, max_results, notifier); + search = _mdns_search_init(name, service, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, notifier); if (!search) { return NULL; } @@ -5623,7 +5624,7 @@ mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, return search; } -esp_err_t mdns_query(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t ** results) +esp_err_t mdns_query_generic(const char * name, const char * service, const char * proto, uint16_t type, bool unicast, uint32_t timeout, size_t max_results, mdns_result_t ** results) { mdns_search_once_t * search = NULL; @@ -5637,7 +5638,7 @@ esp_err_t mdns_query(const char * name, const char * service, const char * proto return ESP_ERR_INVALID_ARG; } - search = _mdns_search_init(name, service, proto, type, timeout, max_results, NULL); + search = _mdns_search_init(name, service, proto, type, unicast, timeout, max_results, NULL); if (!search) { return ESP_ERR_NO_MEM; } @@ -5654,6 +5655,11 @@ esp_err_t mdns_query(const char * name, const char * service, const char * proto return ESP_OK; } +esp_err_t mdns_query(const char * name, const char * service_type, const char * proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t ** results) +{ + return mdns_query_generic(name, service_type, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, results); +} + esp_err_t mdns_query_ptr(const char * service, const char * proto, uint32_t timeout, size_t max_results, mdns_result_t ** results) { if (_str_null_or_empty(service) || _str_null_or_empty(proto)) { diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index a92fb8dd2..e8af394b3 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -368,6 +368,7 @@ typedef struct mdns_search_once_s { mdns_query_notify_t notifier; SemaphoreHandle_t done_semaphore; uint16_t type; + bool unicast; uint8_t max_results; uint8_t num_results; char * instance; diff --git a/components/mdns/test_afl_fuzz_host/mdns_di.h b/components/mdns/test_afl_fuzz_host/mdns_di.h index 12c0c56f7..79dc00f33 100644 --- a/components/mdns/test_afl_fuzz_host/mdns_di.h +++ b/components/mdns/test_afl_fuzz_host/mdns_di.h @@ -8,15 +8,15 @@ void (*mdns_test_static_execute_action)(mdns_action_t *) = NULL; mdns_srv_item_t * (*mdns_test_static_mdns_get_service_item)(const char * service, const char * proto, const char *hostname) = NULL; -mdns_search_once_t *(*mdns_test_static_search_init)(const char *name, const char *service, const char *proto, - uint16_t type, uint32_t timeout, uint8_t max_results, +mdns_search_once_t *(*mdns_test_static_search_init)(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, + uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier) = NULL; esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t * search) = NULL; void (*mdns_test_static_search_free)(mdns_search_once_t * search) = NULL; static void _mdns_execute_action(mdns_action_t * action); static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto, const char *hostname); -static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, +static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier); static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t * search); static void _mdns_search_free(mdns_search_once_t * search); @@ -47,7 +47,7 @@ esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once mdns_search_once_t * mdns_test_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) { - return mdns_test_static_search_init(name, service, proto, type, timeout, max_results, NULL); + return mdns_test_static_search_init(name, service, proto, type, timeout, type != MDNS_TYPE_PTR, max_results, NULL); } mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto) From 5252b1d80165c67ecaa7f95d76a55a9260423de5 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 10 Jan 2022 09:16:10 +0100 Subject: [PATCH 245/289] mdns: Use multi/uni-cast types in API * Original commit: espressif/esp-idf@125c3125524c71f4f48f635eda12e22fa3bca500 --- components/mdns/include/mdns.h | 13 +++++++++++-- components/mdns/mdns.c | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 959fab0ce..cfbdadcbf 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -60,6 +60,14 @@ typedef enum mdns_if_internal { MDNS_IF_MAX } mdns_if_t; +/** + * @brief mDNS query type to be explicitly set to either Unicast or Multicast + */ +typedef enum { + MDNS_QUERY_UNICAST, + MDNS_QUERY_MULTICAST, +} mdns_query_transmission_type_t; + /** * @brief mDNS query result structure */ @@ -580,7 +588,7 @@ mdns_search_once_t *mdns_query_async_new(const char *name, const char *service_t * @param service_type service type (_http, _arduino, _ftp etc.) (NULL for host queries) * @param proto service protocol (_tcp, _udp, etc.) (NULL for host queries) * @param type type of query (MDNS_TYPE_*) - * @param unicast true for Unicast query, false for Multicast query + * @param transmission_type either Unicast query, or Multicast query * @param timeout time in milliseconds to wait for answers. * @param max_results maximum results to be collected * @param results pointer to the results of the query @@ -592,7 +600,8 @@ mdns_search_once_t *mdns_query_async_new(const char *name, const char *service_t * - ESP_ERR_NO_MEM memory error * - ESP_ERR_INVALID_ARG timeout was not given */ -esp_err_t mdns_query_generic(const char * name, const char * service_type, const char * proto, uint16_t type, bool unicast, uint32_t timeout, size_t max_results, mdns_result_t ** results); +esp_err_t mdns_query_generic(const char * name, const char * service_type, const char * proto, uint16_t type, + mdns_query_transmission_type_t transmission_type, uint32_t timeout, size_t max_results, mdns_result_t ** results); /** * @brief Query mDNS for host or service diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 0f027c5bb..d3e2f82e9 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -5624,7 +5624,7 @@ mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, return search; } -esp_err_t mdns_query_generic(const char * name, const char * service, const char * proto, uint16_t type, bool unicast, uint32_t timeout, size_t max_results, mdns_result_t ** results) +esp_err_t mdns_query_generic(const char * name, const char * service, const char * proto, uint16_t type, mdns_query_transmission_type_t transmission_type, uint32_t timeout, size_t max_results, mdns_result_t ** results) { mdns_search_once_t * search = NULL; @@ -5638,7 +5638,7 @@ esp_err_t mdns_query_generic(const char * name, const char * service, const char return ESP_ERR_INVALID_ARG; } - search = _mdns_search_init(name, service, proto, type, unicast, timeout, max_results, NULL); + search = _mdns_search_init(name, service, proto, type, transmission_type == MDNS_QUERY_UNICAST, timeout, max_results, NULL); if (!search) { return ESP_ERR_NO_MEM; } From c8b0d5ea9d75d5a4f34a9b19f30f2c9278b26631 Mon Sep 17 00:00:00 2001 From: caffreyfans Date: Fri, 17 Dec 2021 16:05:38 +0800 Subject: [PATCH 246/289] Fix mDNS memory leak * Original commit: espressif/esp-idf@f5ffd53aeb402afc1333a98168bb2fa35d7cdc77 --- components/mdns/mdns.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index d3e2f82e9..c052a1ae1 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2315,6 +2315,7 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * if (hostname) { s->hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); if (!s->hostname) { + free((char *)s->instance); free(s); return NULL; } @@ -2324,12 +2325,14 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * s->service = strndup(service, MDNS_NAME_BUF_LEN - 1); if (!s->service) { + free((char *)s->instance); free(s); return NULL; } s->proto = strndup(proto, MDNS_NAME_BUF_LEN - 1); if (!s->proto) { + free((char *)s->instance); free((char *)s->service); free(s); return NULL; From 6258edf23bf6d6e9bbd501a113b95f1e4eb0a4c8 Mon Sep 17 00:00:00 2001 From: caffreyfans Date: Fri, 17 Dec 2021 16:21:21 +0800 Subject: [PATCH 247/289] Fix mDNS memory leak * Original commit: espressif/esp-idf@119b4a9dd12cf89cc5eaf63f8aa19730607ef30b --- components/mdns/mdns.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index c052a1ae1..0c2b0b6f3 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2315,9 +2315,7 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * if (hostname) { s->hostname = strndup(hostname, MDNS_NAME_BUF_LEN - 1); if (!s->hostname) { - free((char *)s->instance); - free(s); - return NULL; + goto fail; } } else { s->hostname = NULL; @@ -2325,20 +2323,27 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * s->service = strndup(service, MDNS_NAME_BUF_LEN - 1); if (!s->service) { - free((char *)s->instance); - free(s); - return NULL; + goto fail; } s->proto = strndup(proto, MDNS_NAME_BUF_LEN - 1); if (!s->proto) { - free((char *)s->instance); free((char *)s->service); - free(s); - return NULL; + goto fail; } return s; + +fail: + if (s->instance) { + free(s->instance); + } + if (s->hostname) { + free(s->hostname); + } + free(s); + + return NULL; } /** From c588263b45a4de67dd41a6eea0b32a92009ed29e Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 17 Jan 2022 08:31:16 +0100 Subject: [PATCH 248/289] mdns: Fix minor memory leaks when creating services * Original commit: espressif/esp-idf@fad62cc1ed3dce63b58297172a72a489d7af2d9d --- components/mdns/mdns.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 0c2b0b6f3..67946d8b9 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2265,6 +2265,11 @@ static mdns_txt_linked_item_t * _mdns_allocate_txt(size_t num_items, mdns_txt_it } return new_txt; } + +/** + * @brief Deallocate the txt linked list + * @param txt pointer to the txt pointer to free, noop if txt==NULL + */ static void _mdns_free_linked_txt(mdns_txt_linked_item_t *txt) { mdns_txt_linked_item_t *t; @@ -2293,7 +2298,7 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * uint16_t port, const char * instance, size_t num_items, mdns_txt_item_t txt[]) { - mdns_service_t * s = (mdns_service_t *)malloc(sizeof(mdns_service_t)); + mdns_service_t * s = (mdns_service_t *)calloc(1, sizeof(mdns_service_t)); if (!s) { HOOK_MALLOC_FAILED; return NULL; @@ -2301,8 +2306,7 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * mdns_txt_linked_item_t * new_txt = _mdns_allocate_txt(num_items, txt); if (num_items && new_txt == NULL) { - free(s); - return NULL; + goto fail; } s->priority = 0; @@ -2328,19 +2332,16 @@ static mdns_service_t * _mdns_create_service(const char * service, const char * s->proto = strndup(proto, MDNS_NAME_BUF_LEN - 1); if (!s->proto) { - free((char *)s->service); goto fail; } - return s; fail: - if (s->instance) { - free(s->instance); - } - if (s->hostname) { - free(s->hostname); - } + _mdns_free_linked_txt(s->txt); + free((char *)s->instance); + free((char *)s->service); + free((char *)s->proto); + free((char *)s->hostname); free(s); return NULL; From 3c5b13ea0dba022347f458504051beb8b93ddeb8 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 14 Jan 2022 14:33:13 +0100 Subject: [PATCH 249/289] ci/mdns: Run mdns test on ethernet runners * Original commit: espressif/esp-idf@96616b60565ac8add646800e0f5b1f0ebac1d253 --- examples/protocols/mdns/mdns_example_test.py | 6 +++--- examples/protocols/mdns/sdkconfig.ci | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index 68a780687..20e6bad04 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -103,12 +103,12 @@ def mdns_server(esp_host): continue -@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') +@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') def test_examples_protocol_mdns(env, extra_data): global stop_mdns_server """ steps: | - 1. join AP + init mdns example + 1. obtain IP address + init mdns example 2. get the dut host name (and IP address) 3. check the mdns name is accessible 4. check DUT output if mdns advertized host is resolved @@ -124,7 +124,7 @@ def test_examples_protocol_mdns(env, extra_data): specific_host = dut1.expect(re.compile(r'mdns hostname set to: \[([^\]]+)\]'), timeout=30)[0] mdns_responder = Thread(target=mdns_server, args=(str(specific_host),)) try: - ip_address = dut1.expect(re.compile(r' sta ip: ([^,]+),'), timeout=30)[0] + ip_address = dut1.expect(re.compile(r' eth ip: ([^,]+),'), timeout=30)[0] console_log('Connected to AP with IP: {}'.format(ip_address)) except DUT.ExpectTimeout: raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') diff --git a/examples/protocols/mdns/sdkconfig.ci b/examples/protocols/mdns/sdkconfig.ci index 0587c0624..65d9a2fdc 100644 --- a/examples/protocols/mdns/sdkconfig.ci +++ b/examples/protocols/mdns/sdkconfig.ci @@ -2,3 +2,12 @@ CONFIG_MDNS_RESOLVE_TEST_SERVICES=y CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y From 20e6e9e7fef353de6f75d1e69736a510ba6db263 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 18 Jan 2022 17:15:35 +0100 Subject: [PATCH 250/289] mdns: Fix random crash when defalt service instance queried Merges https://github.com/espressif/esp-idf/pull/8248 * Original commit: espressif/esp-idf@f46dffca627e9578e49a510580f9754ec1e27e2e --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 67946d8b9..588883fcf 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1553,7 +1553,7 @@ static bool _mdns_service_match_ptr_question(const mdns_service_t *service, cons return false; } if (question->host) { - if (strcasecmp(service->instance, question->host) != 0) { + if (strcasecmp(_mdns_get_service_instance_name(service), question->host) != 0) { return false; } } From 9fdbe5f130f2d8941adaa44c543ebbf0dc29ec38 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 21 Jan 2022 14:18:22 +0100 Subject: [PATCH 251/289] mdns: Fix alloc issue if TXT has empty value * Original commit: espressif/esp-idf@205f6ba8541e12d958c7c56af5a7136090f12a0e --- components/mdns/mdns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 588883fcf..52a7cd65e 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -778,8 +778,8 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns char * tmp; mdns_txt_linked_item_t * txt = service->txt; while (txt) { - uint8_t txt_data_len = strlen(txt->key) + txt->value_len + 1; - tmp = (char *)malloc(txt_data_len); + uint8_t txt_data_len = strlen(txt->key) + txt->value_len + 1 /* + '=' char */; + tmp = (char *)malloc(txt_data_len + 1 /* + '\0' term-char in sprintf() */); if (tmp) { int offset = sprintf(tmp, "%s=", txt->key); memcpy(tmp + offset, txt->value, txt->value_len); From fcb5515f1e574ee5c4d0dda00064ef0f41dd56f5 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 21 Jan 2022 11:55:08 +0100 Subject: [PATCH 252/289] mdns: Support for null-value TXT records Closes https://github.com/espressif/esp-idf/issues/8267 * Original commit: espressif/esp-idf@23c2db406dee8df09dbdba21cb7eef9fbca8bf27 --- components/mdns/mdns.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 52a7cd65e..fc9b5394d 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -778,12 +778,8 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns char * tmp; mdns_txt_linked_item_t * txt = service->txt; while (txt) { - uint8_t txt_data_len = strlen(txt->key) + txt->value_len + 1 /* + '=' char */; - tmp = (char *)malloc(txt_data_len + 1 /* + '\0' term-char in sprintf() */); - if (tmp) { - int offset = sprintf(tmp, "%s=", txt->key); - memcpy(tmp + offset, txt->value, txt->value_len); - uint8_t l = _mdns_append_string_with_len(packet, index, tmp, txt_data_len); + if (asprintf(&tmp, "%s%s%.*s", txt->key, txt->value ? "=" : "", txt->value_len, txt->value) > 0) { + uint8_t l = _mdns_append_string(packet, index, tmp); free(tmp); if (!l) { return 0; @@ -2566,7 +2562,7 @@ static int _mdns_check_txt_collision(mdns_service_t * service, const uint8_t * d mdns_txt_linked_item_t * txt = service->txt; while (txt) { - data_len += 2 + strlen(txt->key) + strlen(txt->value); + data_len += 1 /* record-len */ + strlen(txt->key) + txt->value_len + (txt->value ? 1 : 0 /* "=" */); txt = txt->next; } @@ -2582,9 +2578,7 @@ static int _mdns_check_txt_collision(mdns_service_t * service, const uint8_t * d txt = service->txt; while (txt) { - tmp = (char *)malloc(2 + strlen(txt->key) + strlen(txt->value)); - if (tmp) { - sprintf(tmp, "%s=%s", txt->key, txt->value); + if (asprintf(&tmp, "%s%s%.*s", txt->key, txt->value ? "=" : "", txt->value_len, txt->value) > 0) { _mdns_append_string(ours, &index, tmp); free(tmp); } else { @@ -5313,7 +5307,7 @@ esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char const char *value, uint8_t value_len) { if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || - _str_null_or_empty(key) || !value) { + _str_null_or_empty(key) || (!value && value_len)) { return ESP_ERR_INVALID_ARG; } mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); @@ -5333,14 +5327,19 @@ esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char free(action); return ESP_ERR_NO_MEM; } - action->data.srv_txt_set.value = (char *)malloc(value_len); - if (!action->data.srv_txt_set.value) { - free(action->data.srv_txt_set.key); - free(action); - return ESP_ERR_NO_MEM; + if (value_len > 0) { + action->data.srv_txt_set.value = (char *)malloc(value_len); + if (!action->data.srv_txt_set.value) { + free(action->data.srv_txt_set.key); + free(action); + return ESP_ERR_NO_MEM; + } + memcpy(action->data.srv_txt_set.value, value, value_len); + action->data.srv_txt_set.value_len = value_len; + } else { + action->data.srv_txt_set.value = NULL; + action->data.srv_txt_set.value_len = 0; } - memcpy(action->data.srv_txt_set.value, value, value_len); - action->data.srv_txt_set.value_len = value_len; if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { free(action->data.srv_txt_set.key); free(action->data.srv_txt_set.value); From 6cdf5ee0748cab47c752b8cee19770089b17c4b6 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 21 Jan 2022 15:27:45 +0100 Subject: [PATCH 253/289] mdns: Use memcpy() for copy to support non-text TXTs * Original commit: espressif/esp-idf@6aefe9c18563ed567d384a956cf02b6f57d6894c --- components/mdns/mdns.c | 54 ++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index fc9b5394d..766877fb3 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -513,6 +513,37 @@ static inline uint8_t _mdns_append_string(uint8_t * packet, uint16_t * index, co return len + 1; } +/** + * @brief appends one TXT record ("key=value" or "key") + * + * @param packet MDNS packet + * @param index offset in the packet + * @param txt one txt record + * + * @return length of added data: length of the added txt value + 1 on success + * 0 if data won't fit the packet + * -1 if invalid TXT entry + */ +static inline int append_one_txt_record_entry(uint8_t * packet, uint16_t * index, mdns_txt_linked_item_t * txt) +{ + if (txt == NULL || txt->key == NULL) { + return -1; + } + size_t key_len = strlen(txt->key); + size_t len = key_len + txt->value_len + (txt->value ? 1 : 0); + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, txt->key, key_len); + if (txt->value) { + packet[*index + key_len] = '='; + memcpy(packet + *index + key_len + 1, txt->value, txt->value_len); + } + *index += len; + return len + 1; +} + /** * @brief appends FQDN to a packet, incrementing the index and * compressing the output if previous occurrence of the string (or part of it) has been found @@ -775,19 +806,13 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns uint16_t data_len_location = *index - 2; uint16_t data_len = 0; - char * tmp; mdns_txt_linked_item_t * txt = service->txt; while (txt) { - if (asprintf(&tmp, "%s%s%.*s", txt->key, txt->value ? "=" : "", txt->value_len, txt->value) > 0) { - uint8_t l = _mdns_append_string(packet, index, tmp); - free(tmp); - if (!l) { - return 0; - } + int l = append_one_txt_record_entry(packet, index, txt); + if (l > 0) { data_len += l; - } else { - HOOK_MALLOC_FAILED; - // continue + } else if (l == 0) { // TXT entry won't fit into the mdns packet + return 0; } txt = txt->next; } @@ -2574,17 +2599,10 @@ static int _mdns_check_txt_collision(mdns_service_t * service, const uint8_t * d uint8_t ours[len]; uint16_t index = 0; - char * tmp; txt = service->txt; while (txt) { - if (asprintf(&tmp, "%s%s%.*s", txt->key, txt->value ? "=" : "", txt->value_len, txt->value) > 0) { - _mdns_append_string(ours, &index, tmp); - free(tmp); - } else { - HOOK_MALLOC_FAILED; - // continue - } + append_one_txt_record_entry(ours, &index, txt); txt = txt->next; } From f78e8cfce8c384bd89d59ffec5ecda5b5acb7fad Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Mon, 24 Jan 2022 17:54:04 +0100 Subject: [PATCH 254/289] Tools: Custom baud-rate setup is not possible for IDF Monitor from menuconfig anymore IDF Monitor follows the console baud rate by default. Other baud rate can be set from command line by "idf.py monitor -B " or through environment variables. Run "idf.py monitor --help" for more information. * Original commit: espressif/esp-idf@36a4011ff8985bfbae08ba0272194e6c3ef93bbf --- components/mdns/test_afl_fuzz_host/sdkconfig.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index 6f24c6166..4a0e2c54c 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -32,9 +32,6 @@ #define CONFIG_ESPTOOLPY_BEFORE "default_reset" #define CONFIG_ESPTOOLPY_AFTER_RESET 1 #define CONFIG_ESPTOOLPY_AFTER "hard_reset" -#define CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B 1 -#define CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL 115200 -#define CONFIG_ESPTOOLPY_MONITOR_BAUD 115200 #define CONFIG_PARTITION_TABLE_SINGLE_APP 1 #define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" #define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" @@ -384,7 +381,6 @@ #define CONFIG_MB_TIMER_GROUP CONFIG_FMB_TIMER_GROUP #define CONFIG_MB_TIMER_INDEX CONFIG_FMB_TIMER_INDEX #define CONFIG_MB_TIMER_PORT_ENABLED CONFIG_FMB_TIMER_PORT_ENABLED -#define CONFIG_MONITOR_BAUD_115200B CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B #define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE #define CONFIG_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT #define CONFIG_POST_EVENTS_FROM_IRAM_ISR CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR From 085dbd8c4e2069aa0a303f7d92447080bff960a0 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 8 Feb 2022 17:39:38 +0800 Subject: [PATCH 255/289] freertos: Remove legacy data types This commit removes the usage of all legacy FreeRTOS data types that are exposed via configENABLE_BACKWARD_COMPATIBILITY. Legacy types can still be used by enabling CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY. * Original commit: espressif/esp-idf@57fd78f5baf93a368a82cf4b2e00ca17ffc09115 --- .../include/freertos/FreeRTOS.h | 22 +++-------- .../freertos_linux/include/freertos/task.h | 20 +++------- components/mdns/mdns.c | 38 +++++++++---------- .../mdns/private_include/mdns_private.h | 2 +- .../mdns/test_afl_fuzz_host/esp32_mock.h | 7 +--- .../protocol_examples_common/connect.c | 2 +- 6 files changed, 34 insertions(+), 57 deletions(-) diff --git a/components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h b/components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h index ca13d0463..2c4bcbfca 100644 --- a/components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h +++ b/components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h @@ -1,16 +1,8 @@ -// Copyright 2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include @@ -21,13 +13,10 @@ #define portTICK_PERIOD_MS 1 #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -typedef void * xSemaphoreHandle; typedef void * SemaphoreHandle_t; -typedef void * xQueueHandle; typedef void * QueueHandle_t; typedef void * TaskHandle_t; typedef uint32_t TickType_t; -typedef uint32_t portTickType; typedef void (*TaskFunction_t)( void * ); typedef unsigned int UBaseType_t; @@ -39,7 +28,6 @@ typedef int BaseType_t; #define pdPASS ( pdTRUE ) #define pdFAIL ( pdFALSE ) -#define portTICK_RATE_MS portTICK_PERIOD_MS #define pdMS_TO_TICKS(tick) (tick) uint32_t esp_get_free_heap_size(void); diff --git a/components/mdns/host_test/components/freertos_linux/include/freertos/task.h b/components/mdns/host_test/components/freertos_linux/include/freertos/task.h index f6c213ed4..39b7e19c4 100644 --- a/components/mdns/host_test/components/freertos_linux/include/freertos/task.h +++ b/components/mdns/host_test/components/freertos_linux/include/freertos/task.h @@ -1,21 +1,13 @@ -// Copyright 2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include "freertos/FreeRTOS.h" -#define xTaskHandle TaskHandle_t +#define TaskHandle_t TaskHandle_t #define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) void vTaskDelay( const TickType_t xTicksToDelay ); diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 766877fb3..7aaffb78d 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -238,7 +238,7 @@ esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet) action->type = ACTION_RX_HANDLE; action->data.rx_handle.packet = packet; - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(action); return ESP_ERR_NO_MEM; } @@ -4672,7 +4672,7 @@ static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_o action->type = type; action->data.search_add.search = search; - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(action); return ESP_ERR_NO_MEM; } @@ -4706,7 +4706,7 @@ static void _mdns_scheduler_run(void) action->type = ACTION_TX_HANDLE; action->data.tx_handle.packet = p; p->queued = true; - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(action); p->queued = false; } @@ -4854,7 +4854,7 @@ static esp_err_t _mdns_service_task_stop(void) mdns_action_t action; mdns_action_t * a = &action; action.type = ACTION_TASK_STOP; - if (xQueueSend(_mdns_server->action_queue, &a, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &a, (TickType_t)0) != pdPASS) { vTaskDelete(_mdns_service_task_handle); _mdns_service_task_handle = NULL; } @@ -4897,7 +4897,7 @@ static void event_handler(void* arg, esp_event_base_t event_base, action->data.sys_event.interface = event->esp_netif; } - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(action); } } @@ -5056,7 +5056,7 @@ esp_err_t mdns_hostname_set(const char * hostname) action->type = ACTION_HOSTNAME_SET; action->data.hostname_set.hostname = new_hostname; action->data.hostname_set.calling_task = xTaskGetCurrentTaskHandle(); - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(new_hostname); free(action); return ESP_ERR_NO_MEM; @@ -5087,7 +5087,7 @@ esp_err_t mdns_delegate_hostname_add(const char * hostname, const mdns_ip_addr_t action->type = ACTION_DELEGATE_HOSTNAME_ADD; action->data.delegate_hostname.hostname = new_hostname; action->data.delegate_hostname.address_list = copy_address_list(address_list); - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(new_hostname); free(action); return ESP_ERR_NO_MEM; @@ -5116,7 +5116,7 @@ esp_err_t mdns_delegate_hostname_remove(const char * hostname) } action->type = ACTION_DELEGATE_HOSTNAME_REMOVE; action->data.delegate_hostname.hostname = new_hostname; - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(new_hostname); free(action); return ESP_ERR_NO_MEM; @@ -5150,7 +5150,7 @@ esp_err_t mdns_instance_name_set(const char * instance) } action->type = ACTION_INSTANCE_SET; action->data.instance = new_instance; - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(new_instance); free(action); return ESP_ERR_NO_MEM; @@ -5202,7 +5202,7 @@ esp_err_t mdns_service_add_for_host(const char * instance, const char * service, } action->type = ACTION_SERVICE_ADD; action->data.srv_add.service = item; - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { _mdns_free_service(s); free(item); free(action); @@ -5216,7 +5216,7 @@ esp_err_t mdns_service_add_for_host(const char * instance, const char * service, if (expired >= timeout_ticks) { return ESP_FAIL; // Timeout } - vTaskDelay(MIN(10 / portTICK_RATE_MS, timeout_ticks - expired)); + vTaskDelay(MIN(10 / portTICK_PERIOD_MS, timeout_ticks - expired)); } return ESP_OK; @@ -5260,7 +5260,7 @@ esp_err_t mdns_service_port_set_for_host(const char *instance, const char * serv action->type = ACTION_SERVICE_PORT_SET; action->data.srv_port.service = s; action->data.srv_port.port = port; - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(action); return ESP_ERR_NO_MEM; } @@ -5304,7 +5304,7 @@ esp_err_t mdns_service_txt_set_for_host(const char * instance, const char * serv action->data.srv_txt_replace.service = s; action->data.srv_txt_replace.txt = new_txt; - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { _mdns_free_linked_txt(new_txt); free(action); return ESP_ERR_NO_MEM; @@ -5358,7 +5358,7 @@ esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char action->data.srv_txt_set.value = NULL; action->data.srv_txt_set.value_len = 0; } - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(action->data.srv_txt_set.key); free(action->data.srv_txt_set.value); free(action); @@ -5417,7 +5417,7 @@ esp_err_t mdns_service_txt_item_remove_for_host(const char * instance, const cha free(action); return ESP_ERR_NO_MEM; } - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(action->data.srv_txt_del.key); free(action); return ESP_ERR_NO_MEM; @@ -5458,7 +5458,7 @@ esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const cha free(action); return ESP_ERR_NO_MEM; } - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(action->data.srv_subtype_add.subtype); free(action); return ESP_ERR_NO_MEM; @@ -5493,7 +5493,7 @@ esp_err_t mdns_service_instance_name_set_for_host(const char * instance_old, con action->type = ACTION_SERVICE_INSTANCE_SET; action->data.srv_instance.service = s; action->data.srv_instance.instance = new_instance; - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(new_instance); free(action); return ESP_ERR_NO_MEM; @@ -5526,7 +5526,7 @@ esp_err_t mdns_service_remove_for_host(const char * instance, const char * servi } action->type = ACTION_SERVICE_DEL; action->data.srv_del.service = s; - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(action); return ESP_ERR_NO_MEM; } @@ -5556,7 +5556,7 @@ esp_err_t mdns_service_remove_all(void) return ESP_ERR_NO_MEM; } action->type = ACTION_SERVICES_CLEAR; - if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(action); return ESP_ERR_NO_MEM; } diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index e8af394b3..92a0efaa6 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -396,7 +396,7 @@ typedef struct { union { struct { char * hostname; - xTaskHandle calling_task; + TaskHandle_t calling_task; } hostname_set; char * instance; struct { diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h index c1163e9b6..2c268b6b5 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.h @@ -53,7 +53,7 @@ #define INC_TASK_H #define pdMS_TO_TICKS(a) a -#define portTICK_RATE_MS 10 +#define portTICK_PERIOD_MS 10 #define xSemaphoreTake(s,d) true #define xTaskDelete(a) #define vTaskDelete(a) free(a) @@ -73,19 +73,16 @@ #define ESP_TASK_PRIO_MAX 25 #define ESP_TASKD_EVENT_PRIO 5 #define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len -#define xTaskHandle TaskHandle_t +#define TaskHandle_t TaskHandle_t typedef int32_t esp_err_t; -typedef void * xSemaphoreHandle; typedef void * SemaphoreHandle_t; -typedef void * xQueueHandle; typedef void * QueueHandle_t; typedef void * TaskHandle_t; typedef int BaseType_t; typedef uint32_t TickType_t; -typedef uint32_t portTickType; extern const char * WIFI_EVENT; diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index b3b03940f..50925b76a 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -81,7 +81,7 @@ #endif static int s_active_interfaces = 0; -static xSemaphoreHandle s_semph_get_ip_addrs; +static SemaphoreHandle_t s_semph_get_ip_addrs; static esp_netif_t *s_example_esp_netif = NULL; #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 From ac6dcb6830b637894789829a0081d5c7a3f7d35b Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Tue, 14 Dec 2021 19:01:19 +0800 Subject: [PATCH 256/289] esp_timer: remove legacy ESP32 FRC timer implementation. * Original commit: espressif/esp-idf@edb76f14d6b3e925568ff04a87befe733ecc4517 --- components/mdns/test_afl_fuzz_host/sdkconfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index 4a0e2c54c..e210526a9 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -71,7 +71,7 @@ #define CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 1 #define CONFIG_ESP32_BROWNOUT_DET_LVL 0 #define CONFIG_ESP32_REDUCE_PHY_TX_POWER 1 -#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_HRT 1 #define CONFIG_ESP32_RTC_CLK_SRC_INT_RC 1 #define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 #define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 From 869f5b75af758a6170df3e7861b3c9e4193f0d06 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 15 Dec 2021 16:30:29 +0100 Subject: [PATCH 257/289] esp_eth: Make EMAC DMA burst size configurable Merges https://github.com/espressif/esp-idf/pull/7874 Closes https://github.com/espressif/esp-idf/issues/7380 * Original commit: espressif/esp-idf@2553fb5845efbc8cb3ad2d6d4b72cf57fb86c4fc --- examples/common_components/protocol_examples_common/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 50925b76a..fb357dea6 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -379,8 +379,8 @@ static esp_netif_t *eth_start(void) phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR; phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO; #if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET - mac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; - mac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; + mac_config.esp32_emac.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; + mac_config.esp32_emac.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; s_mac = esp_eth_mac_new_esp32(&mac_config); #if CONFIG_EXAMPLE_ETH_PHY_IP101 s_phy = esp_eth_phy_new_ip101(&phy_config); From ba3fa24a96576021ce33e442ed97efe1902811b6 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 24 Jan 2022 15:40:11 +0100 Subject: [PATCH 258/289] esp_eth: Update esp32's EMAC API to decouple driver and vendor config * Original commit: espressif/esp-idf@8da2e4088c5de96c435ce2cd335f756a296927b5 --- .../common_components/protocol_examples_common/connect.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index fb357dea6..c54deae67 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -379,9 +379,10 @@ static esp_netif_t *eth_start(void) phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR; phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO; #if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET - mac_config.esp32_emac.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; - mac_config.esp32_emac.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; - s_mac = esp_eth_mac_new_esp32(&mac_config); + eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); + esp32_emac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; + esp32_emac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; + s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); #if CONFIG_EXAMPLE_ETH_PHY_IP101 s_phy = esp_eth_phy_new_ip101(&phy_config); #elif CONFIG_EXAMPLE_ETH_PHY_RTL8201 From 48e4d4035c89de101d2f6e1ddf60b6bbd76c8b03 Mon Sep 17 00:00:00 2001 From: h2zero Date: Mon, 24 Jan 2022 20:55:45 -0700 Subject: [PATCH 259/289] mdns: Clear notification value in mdns_hostname_set Merges https://github.com/espressif/esp-idf/pull/8284 * Original commit: espressif/esp-idf@83a4ddbd250e2b386bccabb4705d4c58c1a22bcb --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 7aaffb78d..66b62fba8 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -5061,7 +5061,7 @@ esp_err_t mdns_hostname_set(const char * hostname) free(action); return ESP_ERR_NO_MEM; } - xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); + xTaskNotifyWait(0, 0x01, NULL, portMAX_DELAY); return ESP_OK; } From 82e2a5dcc1a3015b50556ba3ca89a4c2d7935825 Mon Sep 17 00:00:00 2001 From: Jakob Hasse Date: Wed, 16 Feb 2022 16:43:04 +0800 Subject: [PATCH 260/289] mdns: added missing includes * Original commit: espressif/esp-idf@28d09c7dbe145ffa6a7dd90531062d4f7669a9c8 --- components/mdns/mdns.c | 4 ++++ components/mdns/private_include/mdns_private.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 66b62fba8..20c9a4505 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -8,6 +8,10 @@ #include "mdns_private.h" #include "mdns_networking.h" #include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" #include #include diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 92a0efaa6..44535747f 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -9,6 +9,10 @@ #include "sdkconfig.h" #include "mdns.h" #include "esp_task.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" #include "esp_timer.h" //#define MDNS_ENABLE_DEBUG From 5909e9e54ce896225a142f8dc68da02972d5f668 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 17 Feb 2022 10:40:32 +0100 Subject: [PATCH 261/289] mdns: Remove legacy esp_event API * Original commit: espressif/esp-idf@e46aa515bdf5606a3d868f1034774d5fc96904b8 --- components/mdns/include/mdns.h | 13 ------------- components/mdns/mdns.c | 19 +++++++------------ components/mdns/test/test_mdns.c | 1 + components/mdns/test_afl_fuzz_host/Makefile | 2 +- components/mdns/test_afl_fuzz_host/README.md | 7 +++++-- .../mdns/test_afl_fuzz_host/esp32_mock.h | 3 +++ 6 files changed, 17 insertions(+), 28 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index cfbdadcbf..55de0dbab 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -11,7 +11,6 @@ extern "C" { #endif #include -#include "esp_event.h" #define MDNS_TYPE_A 0x0001 #define MDNS_TYPE_PTR 0x000C @@ -717,18 +716,6 @@ esp_err_t mdns_query_a(const char * host_name, uint32_t timeout, esp_ip4_addr_t esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, esp_ip6_addr_t * addr); #endif -/** - * @brief System event handler - * This method controls the service state on all active interfaces and applications are required - * to call it from the system event handler for normal operation of mDNS service. - * - * Please note that hostname must not contain domain name, as mDNS uses '.local' domain. - * - * @param ctx The system event context - * @param event The system event - */ -esp_err_t mdns_handle_system_event(void *ctx, system_event_t *event) __attribute__((deprecated)); - #ifdef __cplusplus } #endif diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 20c9a4505..67fa442e7 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4,16 +4,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "mdns.h" -#include "mdns_private.h" -#include "mdns_networking.h" -#include "esp_log.h" +#include +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "freertos/semphr.h" -#include -#include +#include "esp_log.h" +#include "esp_event.h" +#include "mdns.h" +#include "mdns_private.h" +#include "mdns_networking.h" #ifdef MDNS_ENABLE_DEBUG void mdns_debug_packet(const uint8_t * data, size_t len); @@ -4875,12 +4876,6 @@ static esp_err_t _mdns_service_task_stop(void) * Public Methods * */ -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) { diff --git a/components/mdns/test/test_mdns.c b/components/mdns/test/test_mdns.c index abdad0e63..88bc49dbc 100644 --- a/components/mdns/test/test_mdns.c +++ b/components/mdns/test/test_mdns.c @@ -1,5 +1,6 @@ #include "test_utils.h" #include "mdns.h" +#include "esp_event.h" #include "unity.h" diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index a343fe3d6..096e122e6 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -20,7 +20,7 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi -I$(COMPONENTS_DIR)/esp_wifi/include \ -I$(COMPONENTS_DIR)/freertos/FreeRTOS-Kernel \ -I$(COMPONENTS_DIR)/freertos/FreeRTOS-Kernel/include \ - -I$(COMPONENTS_DIR)/freertos/FreeRTOS-Kernel/portable/xtensa/include \ + -I$(COMPONENTS_DIR)/freertos/esp_additions/include/freertos \ -I$(COMPONENTS_DIR)/hal/include \ -I$(COMPONENTS_DIR)/hal/esp32/include \ -I$(COMPONENTS_DIR)/heap/include \ diff --git a/components/mdns/test_afl_fuzz_host/README.md b/components/mdns/test_afl_fuzz_host/README.md index 4a9e68200..11f9c5e6d 100644 --- a/components/mdns/test_afl_fuzz_host/README.md +++ b/components/mdns/test_afl_fuzz_host/README.md @@ -1,7 +1,7 @@ ## Introduction This test uses [american fuzzy lop](http://lcamtuf.coredump.cx/afl/) to mangle real mdns packets and look for exceptions caused by the parser. -A few actual packets are collected and exported as bins in the ```in``` folder, which is then passed as input to AFL when testing. The setup procedure for the test includes all possible services and scenarios that could be used with the given input packets.The output of the parser before fuzzing can be found in [input_packets.txt](input_packets.txt) +A few actual packets are collected and exported as bins in the `in` folder, which is then passed as input to AFL when testing. The setup procedure for the test includes all possible services and scenarios that could be used with the given input packets.The output of the parser before fuzzing can be found in [input_packets.txt](input_packets.txt) ## Building and running the tests using AFL To build and run the tests using AFL(afl-clang-fast) instrumentation @@ -14,6 +14,7 @@ make fuzz (Please note you have to install AFL instrumentation first, check `Installing AFL` section) ## Building the tests using GCC INSTR(off) + To build the tests without AFL instrumentations and instead of that use GCC compiler(In this case it will only check for compilation issues and will not run AFL tests). ```bash @@ -21,8 +22,10 @@ cd $IDF_PATH/components/mdns/test_afl_host make INSTR=off ``` +Note, that this setup is useful if we want to reproduce issues reported by fuzzer tests executed in the CI, or to simulate how the packet parser treats the input packets on the host machine. + ## Installing AFL -To run the test yourself, you need to dounload the [latest afl archive](http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz) and extract it to a folder on your computer. +To run the test yourself, you need to download the [latest afl archive](http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz) and extract it to a folder on your computer. The rest of the document will refer to that folder as ```PATH_TO_AFL```. diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h index 2c268b6b5..b5187cb0c 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.h @@ -8,6 +8,9 @@ // Skip these include files #define ESP_MDNS_NETWORKING_H_ +#define INC_FREERTOS_H +#define QUEUE_H +#define SEMAPHORE_H #define _TCPIP_ADAPTER_H_ #define _ESP_TASK_H_ From ec03fec3d3c33ec07d6dbffe7b4b7d823ed7dba3 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 1 Feb 2022 09:56:32 +0100 Subject: [PATCH 262/289] mdns: Update fuzzer test (add delegation, check memory) * Add new config with no services * Add new test packets and more queries * Allocate packet to check for mem issues * Original commit: espressif/esp-idf@2c1007156e01b4707b5c89d73cad05c0eef0264f --- components/mdns/test_afl_fuzz_host/Makefile | 4 + .../mdns/test_afl_fuzz_host/in/file2.bin | Bin 0 -> 33 bytes .../test_afl_fuzz_host/in/minif_4a_txt.bin | Bin 0 -> 39 bytes .../mdns/test_afl_fuzz_host/in/minif_aaaa.bin | Bin 0 -> 33 bytes .../mdns/test_afl_fuzz_host/in/minif_any.bin | Bin 0 -> 109 bytes .../mdns/test_afl_fuzz_host/in/minif_disc.bin | Bin 0 -> 65 bytes .../mdns/test_afl_fuzz_host/in/minif_ptr.bin | Bin 0 -> 36 bytes .../test_afl_fuzz_host/in/minif_query.bin | Bin 0 -> 77 bytes .../test_afl_fuzz_host/in/minif_query2.bin | Bin 0 -> 64 bytes .../test_afl_fuzz_host/in/sub_fritz_m.bin | Bin 0 -> 72 bytes .../mdns/test_afl_fuzz_host/in/telnet_ptr.bin | Bin 0 -> 72 bytes components/mdns/test_afl_fuzz_host/test.c | 86 ++++++++++++++---- 12 files changed, 72 insertions(+), 18 deletions(-) create mode 100644 components/mdns/test_afl_fuzz_host/in/file2.bin create mode 100644 components/mdns/test_afl_fuzz_host/in/minif_4a_txt.bin create mode 100644 components/mdns/test_afl_fuzz_host/in/minif_aaaa.bin create mode 100644 components/mdns/test_afl_fuzz_host/in/minif_any.bin create mode 100644 components/mdns/test_afl_fuzz_host/in/minif_disc.bin create mode 100644 components/mdns/test_afl_fuzz_host/in/minif_ptr.bin create mode 100644 components/mdns/test_afl_fuzz_host/in/minif_query.bin create mode 100644 components/mdns/test_afl_fuzz_host/in/minif_query2.bin create mode 100644 components/mdns/test_afl_fuzz_host/in/sub_fritz_m.bin create mode 100644 components/mdns/test_afl_fuzz_host/in/telnet_ptr.bin diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 096e122e6..b700bf4f5 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -40,6 +40,10 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h +ifeq ($(MDNS_NO_SERVICES),on) + CFLAGS+=-DMDNS_NO_SERVICES +endif + ifeq ($(INSTR),off) CC=gcc CFLAGS+=-DINSTR_IS_OFF diff --git a/components/mdns/test_afl_fuzz_host/in/file2.bin b/components/mdns/test_afl_fuzz_host/in/file2.bin new file mode 100644 index 0000000000000000000000000000000000000000..a7ce859cc0fdf7cef7985d51d480e03cef0bde7e GIT binary patch literal 33 jcmZPo0Y(tPz`&WCnU|SXlvz^6nvx`oc!d(90rE}4U7mCNP-9S kKvD;I7!(;885kHU7&t&?GB6&{JD|tF2o+;Fu!1WK02L@3p8x;= literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/in/minif_disc.bin b/components/mdns/test_afl_fuzz_host/in/minif_disc.bin new file mode 100644 index 0000000000000000000000000000000000000000..5f3ba62e20a974fdc95cd51411cc49361e1550b0 GIT binary patch literal 65 zcmZPo0VWW^z`z+_oLW?tnVee89-op|tXrJI5?`89z?zevoS4JFz{9}E9$%80lb2e; N5?_*Ba6lO(1OU#z57Phu literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/in/minif_ptr.bin b/components/mdns/test_afl_fuzz_host/in/minif_ptr.bin new file mode 100644 index 0000000000000000000000000000000000000000..67da5edb0797228e7302300904cc6dadbbcaecbc GIT binary patch literal 36 mcmZPo0Y(tPz`!0~lA4p3TEY@vl3c)=lb@WJ!@$79zz6_hPX@aH literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/in/minif_query.bin b/components/mdns/test_afl_fuzz_host/in/minif_query.bin new file mode 100644 index 0000000000000000000000000000000000000000..d21c0d29e1ad0557810e6de355c3a5827bdf3f26 GIT binary patch literal 77 zcmZPo0Y(tPz{nn7oLW?tTEr4xT$;odpH`GvQpFNql3c)=lb@WJ!@$79z{tR$$-01n cL2wF#5CaPXAA{AJdmapeN_SSW%>3L00B#ZzbpQYW literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/in/minif_query2.bin b/components/mdns/test_afl_fuzz_host/in/minif_query2.bin new file mode 100644 index 0000000000000000000000000000000000000000..986118d3c549d01a85a461eca8d73c834f174868 GIT binary patch literal 64 zcmZPo0Y(tPz{nP#R+L#%#S&kVT)>)>pPZP(z`)bM$iSe>Vi5l#RA literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/in/telnet_ptr.bin b/components/mdns/test_afl_fuzz_host/in/telnet_ptr.bin new file mode 100644 index 0000000000000000000000000000000000000000..1cd8e85d8021f55039566cdd619235aeb952ffa6 GIT binary patch literal 72 zcmZQzXklPrU|<9hobkn}MP-@Esm1K^DS5@Z#VIWDr6~ohIr+(nISdRuAXS1>7)03P QOHy<4QcGCkOOj!-08+maF8}}l literal 0 HcmV?d00001 diff --git a/components/mdns/test_afl_fuzz_host/test.c b/components/mdns/test_afl_fuzz_host/test.c index e7fe0b20e..b48d904e3 100644 --- a/components/mdns/test_afl_fuzz_host/test.c +++ b/components/mdns/test_afl_fuzz_host/test.c @@ -1,16 +1,8 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -36,11 +28,14 @@ mdns_search_once_t * mdns_test_search_init(const char * name, const char * servi esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t * search); void mdns_test_search_free(mdns_search_once_t * search); void mdns_test_init_di(void); +extern mdns_server_t * _mdns_server; // // mdns function wrappers for mdns setup in test mode static int mdns_test_hostname_set(const char * mdns_hostname) { + _mdns_server->interfaces[MDNS_IF_STA].pcbs[MDNS_IP_PROTOCOL_V4].state = PCB_RUNNING; // mark the PCB running to exercise mdns in fully operational mode + _mdns_server->interfaces[MDNS_IF_STA].pcbs[MDNS_IP_PROTOCOL_V6].state = PCB_RUNNING; int ret = mdns_hostname_set(mdns_hostname); mdns_action_t * a = NULL; GetLastItem(&a); @@ -48,6 +43,18 @@ static int mdns_test_hostname_set(const char * mdns_hostname) return ret; } +static int mdns_test_add_delegated_host(const char * mdns_hostname) +{ + mdns_ip_addr_t addr = { .addr = { .u_addr = ESP_IPADDR_TYPE_V4 } }; + addr.addr.u_addr.ip4.addr = 0x11111111; + int ret = mdns_delegate_hostname_add(mdns_hostname, &addr); + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + + static int mdns_test_service_instance_name_set(const char * service, const char * proto, const char * instance) { int ret = mdns_service_instance_name_set(service, proto, instance); @@ -66,6 +73,25 @@ static int mdns_test_service_txt_set(const char * service, const char * proto, return ret; } +static int mdns_test_sub_service_add(const char * sub_name, const char * service_name, const char * proto, uint32_t port) +{ + if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { + // This is expected failure as the service thread is not running + } + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + + if (mdns_test_mdns_get_service_item(service_name, proto)==NULL) { + return ESP_FAIL; + } + int ret = mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name); + a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + static int mdns_test_service_add(const char * service_name, const char * proto, uint32_t port) { if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { @@ -81,9 +107,9 @@ static int mdns_test_service_add(const char * service_name, const char * proto, return ESP_OK; } -static mdns_result_t* mdns_test_query(const char * service_name, const char * proto) +static mdns_result_t* mdns_test_query(const char * name, const char * service, const char * proto, uint16_t type) { - search = mdns_test_search_init(NULL, service_name, proto, MDNS_TYPE_PTR, 3000, 20); + search = mdns_test_search_init(name, service, proto, type, 3000, 20); if (!search) { abort(); } @@ -142,6 +168,20 @@ int main(int argc, char** argv) abort(); } + if (mdns_test_add_delegated_host(mdns_hostname) || mdns_test_add_delegated_host("megafritz")) { + abort(); + } + +#ifndef MDNS_NO_SERVICES + + if (mdns_test_sub_service_add("_server", "_fritz", "_tcp", 22)) { + abort(); + } + + if (mdns_test_service_add("_telnet", "_tcp", 22)) { + abort(); + } + if (mdns_test_service_add("_workstation", "_tcp", 9)) { abort(); } @@ -186,7 +226,7 @@ int main(int argc, char** argv) { abort(); } - +#endif mdns_result_t * results = NULL; FILE *file; size_t nread; @@ -216,12 +256,22 @@ int main(int argc, char** argv) memset(buf, 0, 1460); size_t len = read(0, buf, 1460); #endif - mypbuf.payload = buf; + mypbuf.payload = malloc(len); + memcpy(mypbuf.payload, buf, len); mypbuf.len = len; g_packet.pb = &mypbuf; - mdns_test_query("_afpovertcp", "_tcp"); + mdns_test_query("minifritz", "_fritz", "_tcp", MDNS_TYPE_ANY); + mdns_test_query(NULL, "_fritz", "_tcp", MDNS_TYPE_PTR); + mdns_test_query(NULL, "_afpovertcp", "_tcp", MDNS_TYPE_PTR); mdns_parse_packet(&g_packet); + free(mypbuf.payload); } +#ifndef MDNS_NO_SERVICES + mdns_service_remove_all(); + mdns_action_t *a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); +#endif ForceTaskDelete(); mdns_free(); return 0; From 034c55e18a9cc55c9535fd49d6a2d6d3ec9fd84b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 1 Feb 2022 09:58:20 +0100 Subject: [PATCH 263/289] mdns: Fix null-service issue when parsing packets Closes https://github.com/espressif/esp-idf/issues/8307 * Original commit: espressif/esp-idf@a57be7b7d1135ddb29f9da636e9ad315f7fa1fa7 --- components/mdns/mdns.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 67fa442e7..2afc58d47 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -158,6 +158,9 @@ static char * _mdns_mangle_name(char* in) { static bool _mdns_service_match(const mdns_service_t * srv, const char * service, const char * proto, const char * hostname) { + if (!service || !proto) { + return false; + } return !strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && (_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); } @@ -289,6 +292,12 @@ static bool _mdns_instance_name_match(const char *lhs, const char *rhs) static bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instance, const char *service, const char *proto, const char *hostname) { + // service and proto must be supplied, if not this instance won't match + if (!service || !proto) { + return false; + } + // instance==NULL -> _mdns_instance_name_match() will check the default instance + // hostname==NULL -> matches if instance, service and proto matches return !strcasecmp(srv->service, service) && _mdns_instance_name_match(srv->instance, instance) && !strcasecmp(srv->proto, proto) && (_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); } @@ -1610,7 +1619,7 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_ shared = q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_SDPTR || !parsed_packet->probe; if (q->type == MDNS_TYPE_SRV || q->type == MDNS_TYPE_TXT) { mdns_srv_item_t *service = _mdns_get_service_item_instance(q->host, q->service, q->proto, NULL); - if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { + if (service == NULL || !_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { _mdns_free_tx_packet(packet); return; } @@ -3382,8 +3391,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, packet->tcpip_if, packet->ip_protocol, ttl); } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { - if (discovery) { - service = _mdns_get_service_item(name->service, name->proto, NULL); + if (discovery && (service = _mdns_get_service_item(name->service, name->proto, NULL))) { _mdns_remove_parsed_question(parsed_packet, MDNS_TYPE_SDPTR, service); } else if (service && parsed_packet->questions && !parsed_packet->probe) { _mdns_remove_parsed_question(parsed_packet, type, service); From 7710ea9a111b3e2b29b1f0ffad8e55c93de4aadf Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 2 Feb 2022 08:35:04 +0100 Subject: [PATCH 264/289] mdns: Fix memleak when adding delegated host * Original commit: espressif/esp-idf@9cbdb8767bdf6e9745e895b2c5af74d0376965e7 --- components/mdns/mdns.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 2afc58d47..cd9f997c1 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2738,10 +2738,17 @@ static bool _hostname_is_ours(const char * hostname) return false; } +/** + * @brief Adds a delegated hostname to the linked list + * @param hostname Host name pointer + * @param address_list Address list + * @return true on success + * false if the host wasn't attached (this is our hostname, or alloc failure) so we have to free the structs + */ static bool _mdns_delegate_hostname_add(const char * hostname, mdns_ip_addr_t * address_list) { if (_hostname_is_ours(hostname)) { - return true; + return false; } mdns_host_item_t * host = (mdns_host_item_t *)malloc(sizeof(mdns_host_item_t)); @@ -2789,6 +2796,18 @@ static mdns_ip_addr_t * copy_address_list(const mdns_ip_addr_t * address_list) return head; } +static void free_delegated_hostnames(void) +{ + mdns_host_item_t * host = _mdns_host_list; + while (host != NULL) { + free_address_list(host->address_list); + free((char *)host->hostname); + mdns_host_item_t *item = host; + host = host->next; + free(item); + } +} + static bool _mdns_delegate_hostname_remove(const char * hostname) { mdns_srv_item_t * srv = _mdns_server->services; @@ -4657,8 +4676,11 @@ static void _mdns_execute_action(mdns_action_t * action) _mdns_packet_free(action->data.rx_handle.packet); break; case ACTION_DELEGATE_HOSTNAME_ADD: - _mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, - action->data.delegate_hostname.address_list); + if (!_mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, + action->data.delegate_hostname.address_list)) { + free((char *)action->data.delegate_hostname.hostname); + free_address_list(action->data.delegate_hostname.address_list); + } break; case ACTION_DELEGATE_HOSTNAME_REMOVE: _mdns_delegate_hostname_remove(action->data.delegate_hostname.hostname); @@ -5008,6 +5030,7 @@ void mdns_free(void) #endif mdns_service_remove_all(); + free_delegated_hostnames(); _mdns_service_task_stop(); for (i=0; i Date: Wed, 2 Feb 2022 12:21:12 +0100 Subject: [PATCH 265/289] mdns: Fix potential read behind parsed packet * Original commit: espressif/esp-idf@51a5de2525d0e82adea2e298a0edcc9b2dee5edd --- components/mdns/mdns.c | 77 ++++++++++++-------- examples/protocols/mdns/mdns_example_test.py | 1 + 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index cd9f997c1..5c4fa377a 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -332,10 +332,11 @@ static mdns_srv_item_t *_mdns_get_service_item_instance(const char *instance, co * * @return the address after the parsed FQDN in the packet or NULL on error */ -static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * start, mdns_name_t * name, char * buf) +static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * start, mdns_name_t * name, char * buf, size_t packet_len) { size_t index = 0; - while (start[index]) { + const uint8_t * packet_end = packet + packet_len; + while (start + index < packet_end && start[index]) { if (name->parts == 4) { name->invalid = true; } @@ -347,6 +348,9 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s } uint8_t i; for (i=0; i= packet_end) { + return NULL; + } buf[i] = start[index++]; } buf[len] = '\0'; @@ -369,7 +373,7 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s //reference address can not be after where we are return NULL; } - if (_mdns_read_fqdn(packet, packet + address, name, buf)) { + if (_mdns_read_fqdn(packet, packet + address, name, buf, packet_len)) { return start + index; } return NULL; @@ -569,7 +573,7 @@ static inline int append_one_txt_record_entry(uint8_t * packet, uint16_t * index * * @return length of added data: 0 on error or length on success */ -static uint16_t _mdns_append_fqdn(uint8_t * packet, uint16_t * index, const char * strings[], uint8_t count) +static uint16_t _mdns_append_fqdn(uint8_t * packet, uint16_t * index, const char * strings[], uint8_t count, size_t packet_len) { if (!count) { //empty string so terminate @@ -596,7 +600,7 @@ search_next: name.service[0] = 0; name.proto[0] = 0; name.domain[0] = 0; - const uint8_t * content = _mdns_read_fqdn(packet, len_location, &name, buf); + const uint8_t * content = _mdns_read_fqdn(packet, len_location, &name, buf, packet_len); if (!content) { //not a readable fqdn? return 0; @@ -622,7 +626,7 @@ search_next: return 0; } //run the same for the other strings in the name - return written + _mdns_append_fqdn(packet, index, &strings[1], count - 1); + return written + _mdns_append_fqdn(packet, index, &strings[1], count - 1, packet_len); } //we have found the string so let's insert a pointer to it instead @@ -656,7 +660,7 @@ static uint16_t _mdns_append_ptr_record(uint8_t * packet, uint16_t * index, cons str[2] = proto; str[3] = MDNS_DEFAULT_DOMAIN; - part_length = _mdns_append_fqdn(packet, index, str + 1, 3); + part_length = _mdns_append_fqdn(packet, index, str + 1, 3, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -669,7 +673,7 @@ static uint16_t _mdns_append_ptr_record(uint8_t * packet, uint16_t * index, cons record_length += part_length; uint16_t data_len_location = *index - 2; - part_length = _mdns_append_fqdn(packet, index, str, 4); + part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -704,7 +708,7 @@ static uint16_t _mdns_append_subtype_ptr_record(uint8_t *packet, uint16_t *index return 0; } - part_length = _mdns_append_fqdn(packet, index, subtype_str, ARRAY_SIZE(subtype_str)); + part_length = _mdns_append_fqdn(packet, index, subtype_str, ARRAY_SIZE(subtype_str), MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -717,7 +721,7 @@ static uint16_t _mdns_append_subtype_ptr_record(uint8_t *packet, uint16_t *index record_length += part_length; uint16_t data_len_location = *index - 2; - part_length = _mdns_append_fqdn(packet, index, instance_str, ARRAY_SIZE(instance_str)); + part_length = _mdns_append_fqdn(packet, index, instance_str, ARRAY_SIZE(instance_str), MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -756,7 +760,7 @@ static uint16_t _mdns_append_sdptr_record(uint8_t * packet, uint16_t * index, md str[1] = service->proto; str[2] = MDNS_DEFAULT_DOMAIN; - part_length = _mdns_append_fqdn(packet, index, sd_str, 4); + part_length = _mdns_append_fqdn(packet, index, sd_str, 4, MDNS_MAX_PACKET_SIZE); record_length += part_length; @@ -767,7 +771,7 @@ static uint16_t _mdns_append_sdptr_record(uint8_t * packet, uint16_t * index, md record_length += part_length; uint16_t data_len_location = *index - 2; - part_length = _mdns_append_fqdn(packet, index, str, 3); + part_length = _mdns_append_fqdn(packet, index, str, 3, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -805,7 +809,7 @@ static uint16_t _mdns_append_txt_record(uint8_t * packet, uint16_t * index, mdns return 0; } - part_length = _mdns_append_fqdn(packet, index, str, 4); + part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -869,7 +873,7 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns return 0; } - part_length = _mdns_append_fqdn(packet, index, str, 4); + part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -902,7 +906,7 @@ static uint16_t _mdns_append_srv_record(uint8_t * packet, uint16_t * index, mdns return 0; } - part_length = _mdns_append_fqdn(packet, index, str, 2); + part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -935,7 +939,7 @@ static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, const return 0; } - part_length = _mdns_append_fqdn(packet, index, str, 2); + part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -987,7 +991,7 @@ static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, con } - part_length = _mdns_append_fqdn(packet, index, str, 2); + part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -1035,7 +1039,7 @@ static uint16_t _mdns_append_question(uint8_t * packet, uint16_t * index, mdns_o str[str_index++] = q->domain; } - part_length = _mdns_append_fqdn(packet, index, str, str_index); + part_length = _mdns_append_fqdn(packet, index, str, str_index, MDNS_MAX_PACKET_SIZE); if (!part_length) { return 0; } @@ -2958,7 +2962,7 @@ static inline uint32_t _mdns_read_u32(const uint8_t * packet, uint16_t index) * * @return the address after the parsed FQDN in the packet or NULL on error */ -static const uint8_t * _mdns_parse_fqdn(const uint8_t * packet, const uint8_t * start, mdns_name_t * name) +static const uint8_t * _mdns_parse_fqdn(const uint8_t * packet, const uint8_t * start, mdns_name_t * name, size_t packet_len) { name->parts = 0; name->sub = 0; @@ -2970,7 +2974,7 @@ static const uint8_t * _mdns_parse_fqdn(const uint8_t * packet, const uint8_t * static char buf[MDNS_NAME_BUF_LEN]; - const uint8_t * next_data = (uint8_t*)_mdns_read_fqdn(packet, start, name, buf); + const uint8_t * next_data = (uint8_t*)_mdns_read_fqdn(packet, start, name, buf, packet_len); if (!next_data) { return 0; } @@ -3243,6 +3247,10 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) mdns_name_t * name = &n; memset(name, 0, sizeof(mdns_name_t)); + if (len <= MDNS_HEAD_ADDITIONAL_OFFSET) { + free(parsed_packet); + return; + } header.id = _mdns_read_u16(data, MDNS_HEAD_ID_OFFSET); header.flags.value = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); header.questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); @@ -3274,7 +3282,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) uint8_t qs = header.questions; while (qs--) { - content = _mdns_parse_fqdn(data, content, name); + content = _mdns_parse_fqdn(data, content, name, len); if (!content) { header.answers = 0; header.additional = 0; @@ -3282,6 +3290,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) goto clear_rx_packet;//error } + if (content + MDNS_CLASS_OFFSET + 1 >= data + len) { + goto clear_rx_packet; // malformed packet, won't read behind it + } uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); bool unicast = !!(mdns_class & 0x8000); @@ -3353,11 +3364,14 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) while (content < (data + len)) { - content = _mdns_parse_fqdn(data, content, name); + content = _mdns_parse_fqdn(data, content, name, len); if (!content) { goto clear_rx_packet;//error } + if (content + MDNS_LEN_OFFSET + 1 >= data + len) { + goto clear_rx_packet; // malformed packet, won't read behind it + } uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); uint32_t ttl = _mdns_read_u32(content, MDNS_TTL_OFFSET); @@ -3403,7 +3417,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } if (type == MDNS_TYPE_PTR) { - if (!_mdns_parse_fqdn(data, data_ptr, name)) { + if (!_mdns_parse_fqdn(data, data_ptr, name, len)) { continue;//error } if (search_result) { @@ -3442,9 +3456,12 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } } - if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name)) { + if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { continue;//error } + if (data_ptr + MDNS_SRV_PORT_OFFSET + 1 >= data + len) { + goto clear_rx_packet; // malformed packet, won't read behind it + } uint16_t priority = _mdns_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); uint16_t weight = _mdns_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); uint16_t port = _mdns_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); @@ -5852,8 +5869,8 @@ void mdns_debug_packet(const uint8_t * data, size_t len) uint8_t qs = header.questions; while (qs--) { - content = _mdns_parse_fqdn(data, content, name); - if (!content) { + content = _mdns_parse_fqdn(data, content, name, len); + if (!content || content + MDNS_CLASS_OFFSET + 1 >= data + len) { header.answers = 0; header.additional = 0; header.servers = 0; @@ -5903,7 +5920,7 @@ void mdns_debug_packet(const uint8_t * data, size_t len) while (content < (data + len)) { - content = _mdns_parse_fqdn(data, content, name); + content = _mdns_parse_fqdn(data, content, name, len); if (!content) { _mdns_dbg_printf("ERROR: parse mdns records\n"); break; @@ -5971,13 +5988,13 @@ void mdns_debug_packet(const uint8_t * data, size_t len) _mdns_dbg_printf("%u ", ttl); _mdns_dbg_printf("[%u] ", data_len); if (type == MDNS_TYPE_PTR) { - if (!_mdns_parse_fqdn(data, data_ptr, name)) { + if (!_mdns_parse_fqdn(data, data_ptr, name, len)) { _mdns_dbg_printf("ERROR: parse PTR\n"); continue; } _mdns_dbg_printf("%s.%s.%s.%s.\n", name->host, name->service, name->proto, name->domain); } else if (type == MDNS_TYPE_SRV) { - if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name)) { + if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { _mdns_dbg_printf("ERROR: parse SRV\n"); continue; } @@ -6015,7 +6032,7 @@ void mdns_debug_packet(const uint8_t * data, size_t len) _mdns_dbg_printf(IPSTR "\n", IP2STR(&ip)); } else if (type == MDNS_TYPE_NSEC) { const uint8_t * old_ptr = data_ptr; - const uint8_t * new_ptr = _mdns_parse_fqdn(data, data_ptr, name); + const uint8_t * new_ptr = _mdns_parse_fqdn(data, data_ptr, name, len); if (new_ptr) { _mdns_dbg_printf("%s.%s.%s.%s. ", name->host, name->service, name->proto, name->domain); size_t diff = new_ptr - old_ptr; diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index 20e6bad04..fbd062a43 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -91,6 +91,7 @@ def mdns_server(esp_host): console_log('Received query: {} '.format(dns.__repr__())) sock.sendto(get_dns_answer_to_mdns_lwip(TESTER_NAME_LWIP, dns.id), addr) if len(dns.an) > 0 and dns.an[0].type == dpkt.dns.DNS_A: + console_log('Received answer from {}'.format(dns.an[0].name)) if dns.an[0].name == esp_host + u'.local': console_log('Received answer to esp32-mdns query: {}'.format(dns.__repr__())) esp_answered.set() From 94ae672041451ba3e3908ba07da8d1852ed855e6 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 4 Feb 2022 18:18:49 +0100 Subject: [PATCH 266/289] mdns: Update to drop our own packet if bounced back * Original commit: espressif/esp-idf@b5149e3ee73728f790798e6757d732fe426e21c7 --- components/mdns/mdns.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 5c4fa377a..44df1db97 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3237,6 +3237,28 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) mdns_debug_packet(data, len); #endif + // Check if the packet wasn't sent by us + if (packet->ip_protocol == MDNS_IP_PROTOCOL_V4) { + esp_netif_ip_info_t if_ip_info; + if (esp_netif_get_ip_info(_mdns_get_esp_netif(packet->tcpip_if), &if_ip_info) == ESP_OK && + memcmp(&if_ip_info.ip.addr, &packet->src.u_addr.ip4.addr, sizeof(esp_ip4_addr_t)) == 0) { + return; + } +#if CONFIG_LWIP_IPV6 + } else { + struct esp_ip6_addr if_ip6; + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(packet->tcpip_if), &if_ip6) == ESP_OK && + memcmp(&if_ip6, &packet->src.u_addr.ip6, sizeof(esp_ip6_addr_t)) == 0) { + return; + } +#endif + } + + // Check for the minimum size of mdns packet + if (len <= MDNS_HEAD_ADDITIONAL_OFFSET) { + return; + } + mdns_parsed_packet_t * parsed_packet = (mdns_parsed_packet_t *)malloc(sizeof(mdns_parsed_packet_t)); if (!parsed_packet) { HOOK_MALLOC_FAILED; @@ -3247,10 +3269,6 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) mdns_name_t * name = &n; memset(name, 0, sizeof(mdns_name_t)); - if (len <= MDNS_HEAD_ADDITIONAL_OFFSET) { - free(parsed_packet); - return; - } header.id = _mdns_read_u16(data, MDNS_HEAD_ID_OFFSET); header.flags.value = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); header.questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); From 7f42c31252949e28736b36760957eb7d764418dd Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 4 Feb 2022 18:40:21 +0100 Subject: [PATCH 267/289] ci/mdsn: Fix example test on ethernet runners * Ethernet kit uses GPIO0 for ref-clock, so the test button hits constantly * Add a freeRTOS delay when checking result on assync queries * Original commit: espressif/esp-idf@afe7ab3b2c1e8ddc8196abb1009d5a2b43a78a4d --- examples/protocols/mdns/main/Kconfig.projbuild | 14 ++++++++++++++ examples/protocols/mdns/main/mdns_example_main.c | 4 ++-- examples/protocols/mdns/mdns_example_test.py | 2 +- .../mdns/{sdkconfig.ci => sdkconfig.ci.eth_kit} | 2 ++ 4 files changed, 19 insertions(+), 3 deletions(-) rename examples/protocols/mdns/{sdkconfig.ci => sdkconfig.ci.eth_kit} (89%) diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index ca2f2bbf3..bc4b1a055 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -1,5 +1,12 @@ menu "Example Configuration" + config MDNS_GPIO_RANGE_MAX + int + default 33 if IDF_TARGET_ESP32 + default 46 if IDF_TARGET_ESP32S2 + default 19 if IDF_TARGET_ESP32C3 + default 48 if IDF_TARGET_ESP32S3 + config MDNS_HOSTNAME string "mDNS Hostname" default "esp32-mdns" @@ -34,4 +41,11 @@ menu "Example Configuration" If enabled, a portion of MAC address is added to the hostname, this is used for evaluation of tests in CI + config MDNS_BUTTON_GPIO + int "Button GPIO to trigger querries" + range 0 MDNS_GPIO_RANGE_MAX + default 0 + help + Set the GPIO number used as mDNS test button + endmenu diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 94e9140ea..0b5e96245 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -22,7 +22,7 @@ #define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE -#define EXAMPLE_BUTTON_GPIO 0 +#define EXAMPLE_BUTTON_GPIO CONFIG_MDNS_BUTTON_GPIO static const char * TAG = "mdns-test"; static char * generate_hostname(void); @@ -174,7 +174,6 @@ static void query_mdns_hosts_async(const char * host_name) ESP_LOGI(TAG, "Query both A and AAA: %s.local", host_name); mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1, NULL); - mdns_query_async_delete(s_a); mdns_search_once_t *s_aaaa = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_AAAA, 1000, 1, NULL); while (s_a || s_aaaa) { if (s_a && check_and_print_result(s_a)) { @@ -187,6 +186,7 @@ static void query_mdns_hosts_async(const char * host_name) mdns_query_async_delete(s_aaaa); s_aaaa = NULL; } + vTaskDelay(50 / portTICK_PERIOD_MS); } } diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index fbd062a43..f06707718 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -114,7 +114,7 @@ def test_examples_protocol_mdns(env, extra_data): 3. check the mdns name is accessible 4. check DUT output if mdns advertized host is resolved """ - dut1 = env.get_dut('mdns-test', 'examples/protocols/mdns', dut_class=ttfw_idf.ESP32DUT) + dut1 = env.get_dut('mdns-test', 'examples/protocols/mdns', dut_class=ttfw_idf.ESP32DUT, app_config_name='eth_kit') # check and log bin size binary_file = os.path.join(dut1.app.binary_path, 'mdns_test.bin') bin_size = os.path.getsize(binary_file) diff --git a/examples/protocols/mdns/sdkconfig.ci b/examples/protocols/mdns/sdkconfig.ci.eth_kit similarity index 89% rename from examples/protocols/mdns/sdkconfig.ci rename to examples/protocols/mdns/sdkconfig.ci.eth_kit index 65d9a2fdc..703b4543e 100644 --- a/examples/protocols/mdns/sdkconfig.ci +++ b/examples/protocols/mdns/sdkconfig.ci.eth_kit @@ -1,3 +1,4 @@ +CONFIG_IDF_TARGET="esp32" CONFIG_MDNS_RESOLVE_TEST_SERVICES=y CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y @@ -11,3 +12,4 @@ CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 CONFIG_EXAMPLE_ETH_PHY_ADDR=1 CONFIG_EXAMPLE_CONNECT_IPV6=y +CONFIG_MDNS_BUTTON_GPIO=32 From defdfd59b67e9e729a91b9c0110745bdc5621aca Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 28 Jan 2022 19:47:04 +0800 Subject: [PATCH 268/289] G0: target component (components/esp32*) doesn't depend on driver anymore * Original commit: espressif/esp-idf@2571aaf3c998f128787554cd5db2933126cc555f --- .../common_components/protocol_examples_common/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/common_components/protocol_examples_common/CMakeLists.txt b/examples/common_components/protocol_examples_common/CMakeLists.txt index 5c19957ba..5f9317e17 100644 --- a/examples/common_components/protocol_examples_common/CMakeLists.txt +++ b/examples/common_components/protocol_examples_common/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register(SRCS "connect.c" "stdin_out.c" "addr_from_stdin.c" INCLUDE_DIRS "include" - PRIV_REQUIRES esp_netif + PRIV_REQUIRES esp_netif driver ) From ec491ec536796372441773dfd0bbd553d59749ed Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Fri, 7 Jan 2022 12:22:56 +0800 Subject: [PATCH 269/289] system: move kconfig options out of target component Moved the following kconfig options out of the target component: * ESP32_X_BROWNOUT_* -> esp_system * ESP32_X_DEBUG_OCDAWARE -> esp_system * APP_NO_BLOBS -> build type (main kconfig) * Original commit: espressif/esp-idf@bb88338118957c2214a4c0a33cd4a152e2e1f8ba --- components/mdns/test_afl_fuzz_host/sdkconfig.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index e210526a9..d17d4f5e8 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -66,10 +66,10 @@ #define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR 1 #define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES 4 #define CONFIG_ESP32_ULP_COPROC_RESERVE_MEM 0 -#define CONFIG_ESP32_DEBUG_OCDAWARE 1 -#define CONFIG_ESP32_BROWNOUT_DET 1 -#define CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 1 -#define CONFIG_ESP32_BROWNOUT_DET_LVL 0 +#define CONFIG_ESP_DEBUG_OCDAWARE 1 +#define CONFIG_ESP_BROWNOUT_DET 1 +#define CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP_BROWNOUT_DET_LVL 0 #define CONFIG_ESP32_REDUCE_PHY_TX_POWER 1 #define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_HRT 1 #define CONFIG_ESP32_RTC_CLK_SRC_INT_RC 1 @@ -342,8 +342,8 @@ /* List of deprecated options */ #define CONFIG_ADC2_DISABLE_DAC CONFIG_ADC_DISABLE_DAC -#define CONFIG_BROWNOUT_DET CONFIG_ESP32_BROWNOUT_DET -#define CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 +#define CONFIG_BROWNOUT_DET CONFIG_ESP_BROWNOUT_DET +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0 #define CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT #define CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE #define CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT From d39a4c744e6685bbbe2f8a73b2ff593b6d0f23e3 Mon Sep 17 00:00:00 2001 From: gabsuren Date: Fri, 17 Dec 2021 17:49:48 +0400 Subject: [PATCH 270/289] mdns: Stabilization of mdns test app * Original commit: espressif/esp-idf@93a902ba80a88b19e94658db301af828bb4c16e3 --- tools/test_apps/protocols/mdns/app_test.py | 58 +++++++++++++------ tools/test_apps/protocols/mdns/main/main.c | 8 +-- .../test_apps/protocols/mdns/main/mdns_test.c | 48 ++++++++++----- 3 files changed, 78 insertions(+), 36 deletions(-) diff --git a/tools/test_apps/protocols/mdns/app_test.py b/tools/test_apps/protocols/mdns/app_test.py index 043e4622b..efd98feda 100644 --- a/tools/test_apps/protocols/mdns/app_test.py +++ b/tools/test_apps/protocols/mdns/app_test.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import re @@ -26,6 +26,9 @@ HOST_NAME = u'tinytester.local' # This servce answer sent by host, when there is query from board MDNS_HOST_SERVICE = u'ESP32._http._tcp.local' +# Number of retries to receive mdns answear +RETRY_COUNT = 10 + stop_mdns_listener = Event() start_mdns_listener = Event() esp_service_answered = Event() @@ -136,6 +139,7 @@ def mdns_listener(esp_host): # type:(str) -> None continue data, _ = sock.recvfrom(1024) dns = dpkt.dns.DNS(data) + # Receives queries from esp board and sends answers if len(dns.qd) > 0: if dns.qd[0].name == HOST_NAME: console_log('Received query: {} '.format(dns.__repr__())) @@ -147,12 +151,13 @@ def mdns_listener(esp_host): # type:(str) -> None print(dns.qd[0].name) console_log('Received query: {} '.format(dns.__repr__())) sock.sendto(get_dns_answer_to_service_query(MDNS_HOST_SERVICE), (MCAST_GRP,UDP_PORT)) + # Receives answers from esp board and sets event flags for python test cases if len(dns.an) == 1: - if dns.an[0].name == SERVICE_NAME: + if dns.an[0].name.startswith(SERVICE_NAME): console_log('Received answer to service query: {}'.format(dns.__repr__())) esp_service_answered.set() if len(dns.an) > 1: - if dns.an[1].name == SUB_SERVICE_NAME: + if dns.an[1].name.startswith(SUB_SERVICE_NAME): console_log('Received answer for sub service query: {}'.format(dns.__repr__())) esp_sub_service_answered.set() if len(dns.an) > 0 and dns.an[0].type == dpkt.dns.DNS_A: @@ -183,33 +188,49 @@ def create_socket(): # type:() -> socket.socket def test_query_dns_http_service(service): # type: (str) -> None print('SRV: Query {}'.format(service)) sock = create_socket() - sock.sendto(get_mdns_service_query(service), (MCAST_GRP,UDP_PORT)) - if not esp_service_answered.wait(timeout=25): - raise ValueError('Test has failed: did not receive mdns answer within timeout') + packet = get_mdns_service_query(service) + for _ in range(RETRY_COUNT): + if esp_service_answered.wait(timeout=25): + break + sock.sendto(packet, (MCAST_GRP,UDP_PORT)) + else: + raise RuntimeError('Test has failed: did not receive mdns answer within timeout') def test_query_dns_sub_service(sub_service): # type: (str) -> None print('PTR: Query {}'.format(sub_service)) sock = create_socket() - sock.sendto(get_mdns_sub_service_query(sub_service), (MCAST_GRP,UDP_PORT)) - if not esp_sub_service_answered.wait(timeout=25): - raise ValueError('Test has failed: did not receive mdns answer within timeout') + packet = get_mdns_sub_service_query(sub_service) + for _ in range(RETRY_COUNT): + if esp_sub_service_answered.wait(timeout=25): + break + sock.sendto(packet, (MCAST_GRP,UDP_PORT)) + else: + raise RuntimeError('Test has failed: did not receive mdns answer within timeout') def test_query_dns_host(esp_host): # type: (str) -> None print('A: {}'.format(esp_host)) sock = create_socket() - sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT)) - if not esp_host_answered.wait(timeout=25): - raise ValueError('Test has failed: did not receive mdns answer within timeout') + packet = get_dns_query_for_esp(esp_host) + for _ in range(RETRY_COUNT): + if esp_host_answered.wait(timeout=25): + break + sock.sendto(packet, (MCAST_GRP,UDP_PORT)) + else: + raise RuntimeError('Test has failed: did not receive mdns answer within timeout') def test_query_dns_host_delegated(esp_host): # type: (str) -> None print('A: {}'.format(esp_host)) sock = create_socket() - sock.sendto(get_dns_query_for_esp(esp_host + '-delegated'), (MCAST_GRP,UDP_PORT)) - if not esp_delegated_host_answered.wait(timeout=25): - raise ValueError('Test has failed: did not receive mdns answer within timeout') + packet = get_dns_query_for_esp(esp_host + '-delegated') + for _ in range(RETRY_COUNT): + if esp_delegated_host_answered.wait(timeout=25): + break + sock.sendto(packet, (MCAST_GRP,UDP_PORT)) + else: + raise RuntimeError('Test has failed: did not receive mdns answer within timeout') @ttfw_idf.idf_custom_test(env_tag='Example_WIFI', group='test-apps') @@ -229,7 +250,7 @@ def test_app_esp_mdns(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None def start_case(case, desc, result): # type: (str, str, str) -> None print('Starting {}: {}'.format(case, desc)) dut1.write(case) - dut1.expect(re.compile(result), timeout=10) + dut1.expect(re.compile(result), timeout=30) try: # start dns listener thread @@ -251,14 +272,15 @@ def test_app_esp_mdns(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None # query dns host name delegated, answer should be received from esp board test_query_dns_host_delegated(specific_host) + # query service from esp board, answer should be received from host + start_case('CONFIG_TEST_QUERY_SERVICE', 'Query SRV ESP32._http._tcp.local', 'SRV:ESP32') + # query dns-host from esp board, answer should be received from host start_case('CONFIG_TEST_QUERY_HOST', 'Query tinytester.local', 'tinytester.local resolved to: 127.0.0.1') # query dns-host aynchrounusely from esp board, answer should be received from host start_case('CONFIG_TEST_QUERY_HOST_ASYNC', 'Query tinytester.local async', 'Async query resolved to A:127.0.0.1') - # query service from esp board, answer should be received from host - start_case('CONFIG_TEST_QUERY_SERVICE', 'Query SRV ESP32._http._tcp.local', 'SRV:ESP32') finally: stop_mdns_listener.set() mdns_responder.join() diff --git a/tools/test_apps/protocols/mdns/main/main.c b/tools/test_apps/protocols/mdns/main/main.c index cb647aa54..4be8ec494 100644 --- a/tools/test_apps/protocols/mdns/main/main.c +++ b/tools/test_apps/protocols/mdns/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -28,7 +28,7 @@ static void get_string(char *line, size_t size) line[count] = c; ++count; } - vTaskDelay(50 / portTICK_PERIOD_MS); + vTaskDelay(20 / portTICK_PERIOD_MS); } } @@ -92,8 +92,6 @@ static void initialise_mdns(void) void app_main(void) { - char line[256]; - ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); @@ -110,6 +108,8 @@ void app_main(void) ESP_ERROR_CHECK(example_connect()); while (1) { + char line[256]; + get_string(line, sizeof(line)); mdns_test(line); continue; diff --git a/tools/test_apps/protocols/mdns/main/mdns_test.c b/tools/test_apps/protocols/mdns/main/mdns_test.c index effff0a3c..b47e67cc1 100644 --- a/tools/test_apps/protocols/mdns/main/mdns_test.c +++ b/tools/test_apps/protocols/mdns/main/mdns_test.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,7 @@ #include "esp_netif.h" static const char * TAG = "MDNS_TEST_APP"; +static const int RETRY_COUNT = 10; static void mdns_print_results(mdns_result_t *results) { @@ -51,7 +52,7 @@ static bool check_and_print_result(mdns_search_once_t *search) } if (!result) { // search timeout, but no result - return true; + return false; } // If yes, print the result @@ -69,9 +70,10 @@ static bool check_and_print_result(mdns_search_once_t *search) return true; } -static void query_mdns_hosts_async(const char * host_name) +static bool query_mdns_hosts_async(const char * host_name) { ESP_LOGI(TAG, "Query both A and AAA: %s.local", host_name); + bool res = false; mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1, NULL); mdns_query_async_delete(s_a); @@ -81,16 +83,19 @@ static void query_mdns_hosts_async(const char * host_name) ESP_LOGI(TAG, "Query A %s.local finished", host_name); mdns_query_async_delete(s_a); s_a = NULL; + res = true; } if (s_aaaa && check_and_print_result(s_aaaa)) { ESP_LOGI(TAG, "Query AAAA %s.local finished", host_name); mdns_query_async_delete(s_aaaa); s_aaaa = NULL; + res = true; } } + return res; } -static void query_mdns_host(const char * host_name) +static esp_err_t query_mdns_host(const char * host_name) { ESP_LOGI(TAG, "Query A: %s.local", host_name); @@ -101,16 +106,16 @@ static void query_mdns_host(const char * host_name) if(err){ if(err == ESP_ERR_NOT_FOUND){ ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err)); - return; } ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); - return; + return err; } ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr)); + return ESP_OK; } -static void query_mdns_service(const char * instance, const char * service_name, const char * proto) +static esp_err_t query_mdns_service(const char * instance, const char * service_name, const char * proto) { ESP_LOGI(TAG, "Query SRV: %s.%s.local", service_name, proto); @@ -118,15 +123,15 @@ static void query_mdns_service(const char * instance, const char * service_name, esp_err_t err = mdns_query_srv(instance, service_name, proto, 3000, &results); if(err){ ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); - return; + return err; } if(!results){ ESP_LOGW(TAG, "No results found!"); - return; } mdns_print_results(results); mdns_query_results_free(results); + return ESP_OK; } void query_mdns_service_sub_type(const char * subtype, const char * service_name, const char * proto) { @@ -136,11 +141,9 @@ void query_mdns_service_sub_type(const char * subtype, const char * service_name esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); if(err){ ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); - return; } if(!results){ ESP_LOGW(TAG, "No results found!"); - return; } mdns_print_results(results); @@ -150,16 +153,33 @@ void query_mdns_service_sub_type(const char * subtype, const char * service_name void mdns_test(const char *line) { char test_case[32]; + int i = 0; + const TickType_t xDelay = 1000 / portTICK_PERIOD_MS; sscanf(line, "%s", test_case); ESP_LOGI(TAG, "test case = %s", test_case); if (strcmp(test_case, "CONFIG_TEST_QUERY_HOST") == 0) { - query_mdns_host("tinytester"); + i = 0; + while (query_mdns_host("tinytester") != ESP_OK && i != RETRY_COUNT) { + query_mdns_host("tinytester"); + i++; + vTaskDelay(xDelay); + } } else if (strcmp(test_case, "CONFIG_TEST_QUERY_HOST_ASYNC") == 0) { - query_mdns_hosts_async("tinytester"); + i = 0; + while (query_mdns_hosts_async("tinytester") == false && i != RETRY_COUNT) { + query_mdns_hosts_async("tinytester"); + i++; + vTaskDelay(xDelay); + } } else if (strcmp(test_case, "CONFIG_TEST_QUERY_SERVICE") == 0) { - query_mdns_service("ESP32", "_http", "_tcp"); + i = 0; + while (query_mdns_service("ESP32", "_http", "_tcp") != ESP_OK && i != RETRY_COUNT) { + query_mdns_service("ESP32", "_http", "_tcp"); + i++; + vTaskDelay(xDelay); + } } else { ESP_LOGE(TAG, "%s: No such test case", test_case); } From 58bf2186f72410b78e6ea376184817bd631604de Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Wed, 12 Jan 2022 12:23:47 +0530 Subject: [PATCH 271/289] esp_hw_support/esp_system: Re-evaluate header inclusions and include directories This commit updates the visibility of various header files and cleans up some unnecessary inclusions. Also, this commit removes certain header include paths which were maintained for backward compatibility. * Original commit: espressif/esp-idf@a9fda54d39d1321005c3bc9b3cc268d0b7e9f052 --- components/mdns/mdns.c | 2 ++ components/mdns/test_afl_fuzz_host/esp32_mock.h | 2 +- examples/protocols/mdns/main/mdns_example_main.c | 2 +- tools/test_apps/protocols/mdns/main/main.c | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 44df1db97..8b47b3c35 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -15,6 +15,8 @@ #include "mdns.h" #include "mdns_private.h" #include "mdns_networking.h" +#include "esp_log.h" +#include "esp_random.h" #ifdef MDNS_ENABLE_DEBUG void mdns_debug_packet(const uint8_t * data, size_t len); diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h index b5187cb0c..8afe01fba 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.h @@ -52,7 +52,7 @@ #define ESP_LOGV(a,b,c,d) #define LWIP_HDR_PBUF_H -#define __ESP_SYSTEM_H__ +#define __ESP_RANDOM_H__ #define INC_TASK_H #define pdMS_TO_TICKS(a) a diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 0b5e96245..c1db88ba0 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -10,7 +10,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_netif_ip_addr.h" -#include "esp_system.h" +#include "esp_mac.h" #include "esp_event.h" #include "esp_log.h" #include "nvs_flash.h" diff --git a/tools/test_apps/protocols/mdns/main/main.c b/tools/test_apps/protocols/mdns/main/main.c index 4be8ec494..0a160aee2 100644 --- a/tools/test_apps/protocols/mdns/main/main.c +++ b/tools/test_apps/protocols/mdns/main/main.c @@ -5,7 +5,7 @@ */ #include #include -#include "esp_system.h" +#include "esp_mac.h" #include "nvs_flash.h" #include "esp_event.h" #include "esp_netif.h" From 605d1fab7371ce807a3a05777904c4bbc6f70165 Mon Sep 17 00:00:00 2001 From: Suren Gabrielyan Date: Thu, 19 Aug 2021 15:47:28 +0400 Subject: [PATCH 272/289] mdns: Prepare for dynamic esp-netif support * Original commit: espressif/esp-idf@f9892f77b88ba77dc6608ba746175f6dc64a7607 --- components/mdns/include/mdns.h | 13 +- components/mdns/mdns.c | 115 +++- .../mdns/main/mdns_example_wifi_main.c | 495 ++++++++++++++++++ 3 files changed, 599 insertions(+), 24 deletions(-) create mode 100644 examples/protocols/mdns/main/mdns_example_wifi_main.c diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 55de0dbab..758010c7f 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -21,6 +21,13 @@ extern "C" { #define MDNS_TYPE_NSEC 0x002F #define MDNS_TYPE_ANY 0x00FF +#define CONFIG_MDNS_IF_MAX 4 +#define ACTION_ENABLE 1 +#define ACTION_ENABLE_WITH_DHCP_CHECK 2 +#define ACTION_ANNOUNCE 3 +#define ACTION_ENABLE_ANNOUNCE 4 +#define ACTION_DISABLE 5 + /** * @brief Asynchronous query handle */ @@ -53,10 +60,8 @@ typedef struct mdns_ip_addr_s { } mdns_ip_addr_t; typedef enum mdns_if_internal { - MDNS_IF_STA = 0, - MDNS_IF_AP = 1, - MDNS_IF_ETH = 2, - MDNS_IF_MAX + MDNS_IF_INVALID = -1, + MDNS_IF_MAX = CONFIG_MDNS_IF_MAX } mdns_if_t; /** diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 8b47b3c35..28d054563 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -58,31 +58,43 @@ static bool _mdns_append_host_list_in_services(mdns_out_answer_t ** destination, static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye); static void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); + +typedef struct mdns_event_action { + esp_event_base_t event_base; + int32_t event_id; + uint32_t action; +} mdns_event_action_t; + +typedef struct mdns_interfaces { + esp_netif_t * netif; + mdns_event_action_t actions[5]; +} mdns_interfaces_t; + /* * @brief Internal collection of mdns supported interfaces * */ -static esp_netif_t * s_esp_netifs[MDNS_IF_MAX] = {}; +static mdns_interfaces_t s_esp_netifs[MDNS_IF_MAX] = {}; /* * @brief Convert mdns if to esp-netif handle */ esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) { - if (tcpip_if < MDNS_IF_MAX) { - if (s_esp_netifs[tcpip_if] == NULL) { + if (tcpip_if > MDNS_IF_INVALID && tcpip_if < MDNS_IF_MAX) { + if (s_esp_netifs[tcpip_if].netif == NULL) { // if local netif copy is NULL, try to search for the default interface key - if (tcpip_if == MDNS_IF_STA) { - s_esp_netifs[MDNS_IF_STA] = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); - } else if (tcpip_if == MDNS_IF_AP) { - s_esp_netifs[MDNS_IF_AP] = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); -#if CONFIG_ETH_ENABLED - } else if (tcpip_if == MDNS_IF_ETH) { - s_esp_netifs[MDNS_IF_ETH] = esp_netif_get_handle_from_ifkey("ETH_DEF"); -#endif - } +// if (tcpip_if == MDNS_IF_STA) { +// s_esp_netifs[MDNS_IF_STA] = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); +// } else if (tcpip_if == MDNS_IF_AP) { +// s_esp_netifs[MDNS_IF_AP] = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); +//#if CONFIG_ETH_ENABLED +// } else if (tcpip_if == MDNS_IF_ETH) { +// s_esp_netifs[MDNS_IF_ETH] = esp_netif_get_handle_from_ifkey("ETH_DEF"); +//#endif +// } } - return s_esp_netifs[tcpip_if]; + return s_esp_netifs[tcpip_if].netif; } return NULL; } @@ -93,7 +105,7 @@ esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) */ static inline void _mdns_clean_netif_ptr(mdns_if_t tcpip_if) { if (tcpip_if < MDNS_IF_MAX) { - s_esp_netifs[tcpip_if] = NULL; + s_esp_netifs[tcpip_if].netif = NULL; } } @@ -104,7 +116,7 @@ static inline void _mdns_clean_netif_ptr(mdns_if_t tcpip_if) { static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *interface) { for (int i=0; i MDNS_IF_MAX) { + return; + } + + for (int i = 0; i < CONFIG_MDNS_EVENT_ACTIONS; ++i) { // TO-DO + if (s_esp_netifs[mdns_if].actions[i].event_id == event_id) { + if (s_esp_netifs[mdns_if].actions[i].action == ACTION_ENABLE) { + _action_enable_pcb(mdns_if); + } + if (s_esp_netifs[mdns_if].actions[i].action == ACTION_ENABLE_WITH_DHCP_CHECK) { + _action_enable_pcb_dhcps_status_check(interface, mdns_if); + } + if (s_esp_netifs[mdns_if].actions[i].action == ACTION_ENABLE_ANNOUNCE) { + _action_enable_announce_pcb(mdns_if); + } + if (s_esp_netifs[mdns_if].actions[i].action == ACTION_DISABLE) { + _action_disable_pcb(mdns_if); + } + } + } +} +#if 0 static void _mdns_handle_system_event(esp_event_base_t event_base, int32_t event_id, esp_netif_t* interface) { @@ -3856,6 +3930,7 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, } } } +#endif /* * MDNS Search diff --git a/examples/protocols/mdns/main/mdns_example_wifi_main.c b/examples/protocols/mdns/main/mdns_example_wifi_main.c new file mode 100644 index 000000000..64837b195 --- /dev/null +++ b/examples/protocols/mdns/main/mdns_example_wifi_main.c @@ -0,0 +1,495 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* MDNS-SD Query and advertise Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_netif_ip_addr.h" +#include "esp_system.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_netif.h" +#include "protocol_examples_common.h" +#include "mdns.h" +#include "driver/gpio.h" +#include "netdb.h" +#include "esp_wifi.h" + +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sys.h" +// #include "mdns_if_defaults.h" + + +/* FreeRTOS event group to signal when we are connected*/ +// static EventGroupHandle_t s_wifi_event_group; + +#define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE +#define EXAMPLE_BUTTON_GPIO 0 + +static const char * TAG = "mdns-test"; +static char * generate_hostname(void); + +#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 +static void query_mdns_host_with_gethostbyname(char * host); +static void query_mdns_host_with_getaddrinfo(char * host); +#endif + +static int s_retry_num = 0; + +// #define EXAMPLE_ESP_WIFI_SSID "Coworking" +#define EXAMPLE_ESP_WIFI_SSID "Coworking" +#define EXAMPLE_ESP_WIFI_PASS "Coworkers" + +#define EXAMPLE_ESP_MAXIMUM_RETRY 2 + +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 + +static void event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + esp_wifi_connect(); + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, "retry to connect to the AP"); + } else { + // xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); + } + ESP_LOGI(TAG,"connect to the AP fail"); + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; + ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); + s_retry_num = 0; + //xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); + } +} + +static void initialise_mdns(void) +{ + esp_netif_t* netif_wifi = esp_netif_create_default_wifi_sta(); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + esp_event_handler_instance_t instance_any_id; + esp_event_handler_instance_t instance_got_ip; + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &event_handler, + NULL, + &instance_any_id)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, + IP_EVENT_STA_GOT_IP, + &event_handler, + NULL, + &instance_got_ip)); + + wifi_config_t wifi_config = { + .sta = { + .ssid = EXAMPLE_ESP_WIFI_SSID, + .password = EXAMPLE_ESP_WIFI_PASS, + /* Setting a password implies station will connect to all security modes including WEP/WPA. + * However these modes are deprecated and not advisable to be used. Incase your Access point + * doesn't support WPA2, these mode can be enabled by commenting below line */ + .threshold.authmode = WIFI_AUTH_WPA2_PSK, + + .pmf_cfg = { + .capable = true, + .required = false + }, + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + + char * hostname = generate_hostname(); + + //initialize mDNS + // mdns_config_t mdns_config = MDNS_NETIF_DEFAULT_WIFI(netif_wifi); + + //_mdns_action_t _actions[] = { + // { + // .event_base = WIFI_EVENT, + // .event_id = WIFI_EVENT_STA_CONNECTED, + // .action = ACTION_ENABLE_WITH_DHCP_CHECK + // }, + // { + // .event_base = WIFI_EVENT, + // .event_id = WIFI_EVENT_STA_DISCONNECTED, + // .action = ACTION_DISABLE + // }, + // { + // .event_base = IP_EVENT, + // .event_id = IP_EVENT_STA_GOT_IP, + // .action = ACTION_ENABLE_ANNOUNCE + // } + // }; + + //mdns_config_t mdns_config = { + // .netif = netif_wifi, + // .num = 3, + // .next = {NULL}, + // .actions = _actions + //}; + + mdns_config_t * mdns_config = calloc(1, sizeof(struct mdns_config_s)); + mdns_config->netif = netif_wifi; + mdns_config->num = 3; + mdns_config->actions = malloc(sizeof(_mdns_action_t) * 3); + //mdns_config->actions = { { .esp_event_base_t = WIFI_EVENT, .event_id = WIFI_EVENT_STA_CONNECTED, .action = ACTION_ENABLE_WITH_DHCP_CHECK}}; + //mdns_config->actionsesp_event_base_t = WIFI_EVENT; + mdns_config->actions[0].event_base = WIFI_EVENT; + mdns_config->actions[0].event_id = WIFI_EVENT_STA_CONNECTED; + mdns_config->actions[0].action = ACTION_ENABLE_WITH_DHCP_CHECK; + + mdns_config->actions[1].event_base = WIFI_EVENT; + mdns_config->actions[1].event_id = WIFI_EVENT_STA_DISCONNECTED; + mdns_config->actions[1].action = ACTION_DISABLE; + + mdns_config->actions[2].event_base = IP_EVENT; + mdns_config->actions[2].event_id = IP_EVENT_STA_GOT_IP; + mdns_config->actions[2].action = ACTION_ENABLE_ANNOUNCE; + + ESP_ERROR_CHECK( mdns_init_cfg(mdns_config) ); // mdns_add_netif + + esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); + char * desc; + asprintf(&desc, "%s: %s", TAG, esp_netif_config.if_desc); + esp_netif_config.if_desc = desc; + esp_netif_config.route_prio = 64; + esp_netif_config_t netif_config = { + .base = &esp_netif_config, + .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH + }; + + + esp_netif_t * netif_eth = esp_netif_new(&netif_config); + mdns_config_t * mdns_config_eth = calloc(1, sizeof(struct mdns_config_s)); + mdns_config_eth->netif = netif_eth; + mdns_config_eth->num = 2; + mdns_config_eth->actions = malloc(sizeof(_mdns_action_t) * 3); + //mdns_config->actions = { { .esp_event_base_t = WIFI_EVENT, .event_id = WIFI_EVENT_STA_CONNECTED, .action = ACTION_ENABLE_WITH_DHCP_CHECK}}; + mdns_config_eth->actions[0].event_base = ETH_EVENT; + mdns_config_eth->actions[0].event_id = ETHERNET_EVENT_CONNECTED; + mdns_config_eth->actions[0].action = ACTION_ENABLE; + + + mdns_config_eth->actions[1].event_base = ETH_EVENT; + mdns_config_eth->actions[1].event_id = ETHERNET_EVENT_DISCONNECTED; + mdns_config_eth->actions[1].action = ACTION_DISABLE; + + mdns_cfg_add_to_list(mdns_config_eth); + + //set mDNS hostname (required if you want to advertise services) + ESP_ERROR_CHECK( mdns_hostname_set(hostname) ); + ESP_LOGI(TAG, "mdns hostname set to: [%s]", hostname); + //set default mDNS instance name + ESP_ERROR_CHECK( mdns_instance_name_set(EXAMPLE_MDNS_INSTANCE) ); + + //structure with TXT records + mdns_txt_item_t serviceTxtData[3] = { + {"board", "esp32"}, + {"u", "user"}, + {"p", "password"} + }; + + //initialize service + ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) ); + +#if CONFIG_MDNS_PUBLISH_DELEGATE_HOST + char *delegated_hostname; + if (-1 == asprintf(&delegated_hostname, "%s-delegated", hostname)) { + abort(); + } + + mdns_ip_addr_t addr4, addr6; + esp_netif_str_to_ip4("10.0.0.1", &addr4.addr.u_addr.ip4); + addr4.addr.type = ESP_IPADDR_TYPE_V4; + esp_netif_str_to_ip6("fd11:22::1", &addr6.addr.u_addr.ip6); + addr6.addr.type = ESP_IPADDR_TYPE_V6; + addr4.next = &addr6; + addr6.next = NULL; + ESP_ERROR_CHECK( mdns_delegate_hostname_add(delegated_hostname, &addr4) ); + ESP_ERROR_CHECK( mdns_service_add_for_host("test0", "_http", "_tcp", delegated_hostname, 1234, serviceTxtData, 3) ); + free(delegated_hostname); +#endif // CONFIG_MDNS_PUBLISH_DELEGATE_HOST + + //add another TXT item + ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") ); + //change TXT item value + ESP_ERROR_CHECK( mdns_service_txt_item_set_with_explicit_value_len("_http", "_tcp", "u", "admin", strlen("admin")) ); + free(hostname); +} + +/* these strings match tcpip_adapter_if_t enumeration */ +// static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; + +/* these strings match mdns_ip_protocol_t enumeration */ +// static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; + +static void mdns_print_results(mdns_result_t *results) +{ + mdns_result_t *r = results; + mdns_ip_addr_t *a = NULL; + //int i = 1; + int t; + while(r){ + //printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]); + if(r->instance_name){ + printf(" PTR : %s\n", r->instance_name); + } + if (r->hostname) { + printf(" SRV : %s.local:%u\n", r->hostname, r->port); + } + if (r->txt_count) { + printf(" TXT : [%zu] ", r->txt_count); + for (t = 0; t < r->txt_count; t++) { + printf("%s=%s(%d); ", r->txt[t].key, r->txt[t].value ? r->txt[t].value : "NULL", r->txt_value_len[t]); + } + printf("\n"); + } + a = r->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + r = r->next; + } +} + +static void query_mdns_service(const char * service_name, const char * proto) +{ + ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); + + mdns_result_t * results = NULL; + esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); + if(err){ + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); + return; + } + if(!results){ + ESP_LOGW(TAG, "No results found!"); + return; + } + + mdns_print_results(results); + mdns_query_results_free(results); +} + +static bool check_and_print_result(mdns_search_once_t *search) +{ + // Check if any result is available + mdns_result_t * result = NULL; + if (!mdns_query_async_get_results(search, 0, &result)) { + return false; + } + + if (!result) { // search timeout, but no result + return true; + } + + // If yes, print the result + mdns_ip_addr_t * a = result->addr; + while (a) { + if(a->addr.type == ESP_IPADDR_TYPE_V6){ + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + // and free the result + mdns_query_results_free(result); + return true; +} + +static void query_mdns_hosts_async(const char * host_name) +{ + ESP_LOGI(TAG, "Query both A and AAA: %s.local", host_name); + + mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1, NULL); + mdns_query_async_delete(s_a); + mdns_search_once_t *s_aaaa = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_AAAA, 1000, 1, NULL); + while (s_a || s_aaaa) { + if (s_a && check_and_print_result(s_a)) { + ESP_LOGI(TAG, "Query A %s.local finished", host_name); + mdns_query_async_delete(s_a); + s_a = NULL; + } + if (s_aaaa && check_and_print_result(s_aaaa)) { + ESP_LOGI(TAG, "Query AAAA %s.local finished", host_name); + mdns_query_async_delete(s_aaaa); + s_aaaa = NULL; + } + } +} + +static void query_mdns_host(const char * host_name) +{ + ESP_LOGI(TAG, "Query A: %s.local", host_name); + + struct esp_ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(host_name, 2000, &addr); + if(err){ + if(err == ESP_ERR_NOT_FOUND){ + ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err)); + return; + } + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); + return; + } + + ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr)); +} + +static void initialise_button(void) +{ + gpio_config_t io_conf = {0}; + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.pin_bit_mask = BIT64(EXAMPLE_BUTTON_GPIO); + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pull_up_en = 1; + io_conf.pull_down_en = 0; + gpio_config(&io_conf); +} + +static void check_button(void) +{ + static bool old_level = true; + bool new_level = gpio_get_level(EXAMPLE_BUTTON_GPIO); + if (!new_level && old_level) { + query_mdns_hosts_async("esp32-mdns"); + query_mdns_host("esp32"); + query_mdns_service("_arduino", "_tcp"); + query_mdns_service("_http", "_tcp"); + query_mdns_service("_printer", "_tcp"); + query_mdns_service("_ipp", "_tcp"); + query_mdns_service("_afpovertcp", "_tcp"); + query_mdns_service("_smb", "_tcp"); + query_mdns_service("_ftp", "_tcp"); + query_mdns_service("_nfs", "_tcp"); + } + old_level = new_level; +} + +static void mdns_example_task(void *pvParameters) +{ +#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 + /* Send initial queries that are started by CI tester */ + query_mdns_host("tinytester"); + query_mdns_host_with_gethostbyname("tinytester-lwip.local"); + query_mdns_host_with_getaddrinfo("tinytester-lwip.local"); +#endif + + while (1) { + check_button(); + vTaskDelay(50 / portTICK_PERIOD_MS); + } +} + +void app_main(void) +{ + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + initialise_mdns(); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + // ESP_ERROR_CHECK(example_connect()); // To-do, change this to explicitelly register first for wifi interface, then add new one + + initialise_button(); + xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL); +} + +/** Generate host name based on sdkconfig, optionally adding a portion of MAC address to it. + * @return host name string allocated from the heap + */ +static char* generate_hostname(void) +{ +#ifndef CONFIG_MDNS_ADD_MAC_TO_HOSTNAME + return strdup(CONFIG_MDNS_HOSTNAME); +#else + uint8_t mac[6]; + char *hostname; + esp_read_mac(mac, ESP_MAC_WIFI_STA); + if (-1 == asprintf(&hostname, "%s-%02X%02X%02X", CONFIG_MDNS_HOSTNAME, mac[3], mac[4], mac[5])) { + abort(); + } + return hostname; +#endif +} + +#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 +/** + * @brief Executes gethostbyname and displays list of resolved addresses. + * Note: This function is used only to test advertised mdns hostnames resolution + */ +static void query_mdns_host_with_gethostbyname(char * host) +{ + struct hostent *res = gethostbyname(host); + if (res) { + unsigned int i = 0; + while (res->h_addr_list[i] != NULL) { + ESP_LOGI(TAG, "gethostbyname: %s resolved to: %s", host, inet_ntoa(*(struct in_addr *) (res->h_addr_list[i]))); + i++; + } + } +} + +/** + * @brief Executes getaddrinfo and displays list of resolved addresses. + * Note: This function is used only to test advertised mdns hostnames resolution + */ +static void query_mdns_host_with_getaddrinfo(char * host) +{ + struct addrinfo hints; + struct addrinfo * res; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if (!getaddrinfo(host, NULL, &hints, &res)) { + while (res) { + ESP_LOGI(TAG, "getaddrinfo: %s resolved to: %s", host, + res->ai_family == AF_INET? + inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr): + inet_ntoa(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr)); + res = res->ai_next; + } + } +} +#endif From fa951bf3206b645fb4cbd199f0a2cb01b380c8f0 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 13 Dec 2021 17:15:54 +0100 Subject: [PATCH 273/289] mdns: Use predefined interfaces to prepare for custom netifs * Original commit: espressif/esp-idf@f90b3b798b446382d848f8c55c5e1653c81871cd --- components/mdns/include/mdns.h | 15 +- components/mdns/mdns.c | 285 +++++----- .../mdns/private_include/mdns_private.h | 5 +- .../mdns/main/mdns_example_wifi_main.c | 495 ------------------ 4 files changed, 171 insertions(+), 629 deletions(-) delete mode 100644 examples/protocols/mdns/main/mdns_example_wifi_main.c diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 758010c7f..fb14077b4 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -22,17 +22,22 @@ extern "C" { #define MDNS_TYPE_ANY 0x00FF #define CONFIG_MDNS_IF_MAX 4 -#define ACTION_ENABLE 1 -#define ACTION_ENABLE_WITH_DHCP_CHECK 2 -#define ACTION_ANNOUNCE 3 -#define ACTION_ENABLE_ANNOUNCE 4 -#define ACTION_DISABLE 5 /** * @brief Asynchronous query handle */ typedef struct mdns_search_once_s mdns_search_once_t; + +typedef enum { + MDNS_EVENT_ENABLE_IP4 = 1 << 1, + MDNS_EVENT_ENABLE_IP6 = 1 << 2, + MDNS_EVENT_ANNOUNCE_IP4 = 1 << 3, + MDNS_EVENT_ANNOUNCE_IP6 = 1 << 4, + MDNS_EVENT_DISABLE_IP4 = 1 << 5, + MDNS_EVENT_DISABLE_IP6 = 1 << 6, +} mdns_event_actions_t; + /** * @brief mDNS enum to specify the ip_protocol type */ diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 28d054563..27c6797cd 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -57,42 +57,74 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, static bool _mdns_append_host_list_in_services(mdns_out_answer_t ** destination, mdns_srv_item_t * services[], size_t services_len, bool flush, bool bye); static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye); static void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); +static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); +typedef enum mdns_netif_predef { + MDNS_USES_PREDEFINED_IF = 0, + MDNS_USES_CUSTOM_IF = 1, +} mdns_netif_predef_t; -typedef struct mdns_event_action { - esp_event_base_t event_base; - int32_t event_id; - uint32_t action; -} mdns_event_action_t; +typedef enum { + MDNS_IF_STA = 0, + MDNS_IF_AP = 1, + MDNS_IF_ETH = 2, +} mdns_predef_if_t; -typedef struct mdns_interfaces { +typedef struct mdns_interfaces mdns_interfaces_t; + +struct mdns_interfaces { + mdns_netif_predef_t predefined; esp_netif_t * netif; - mdns_event_action_t actions[5]; -} mdns_interfaces_t; + mdns_predef_if_t predef_if; + mdns_if_t duplicate; +}; /* * @brief Internal collection of mdns supported interfaces * */ -static mdns_interfaces_t s_esp_netifs[MDNS_IF_MAX] = {}; +static mdns_interfaces_t s_esp_netifs[MDNS_IF_MAX] = { + { .predefined = MDNS_USES_PREDEFINED_IF, .netif = NULL, .predef_if = MDNS_IF_STA, .duplicate = MDNS_IF_MAX }, + { .predefined = MDNS_USES_PREDEFINED_IF, .netif = NULL, .predef_if = MDNS_IF_AP, .duplicate = MDNS_IF_MAX }, + { .predefined = MDNS_USES_PREDEFINED_IF, .netif = NULL, .predef_if = MDNS_IF_ETH, .duplicate = MDNS_IF_MAX }, +}; + /* * @brief Convert mdns if to esp-netif handle */ +static mdns_if_t mdns_if_from_predef_if(mdns_predef_if_t predef_if) +{ + for (int i=0; i MDNS_IF_INVALID && tcpip_if < MDNS_IF_MAX) { - if (s_esp_netifs[tcpip_if].netif == NULL) { - // if local netif copy is NULL, try to search for the default interface key -// if (tcpip_if == MDNS_IF_STA) { -// s_esp_netifs[MDNS_IF_STA] = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); -// } else if (tcpip_if == MDNS_IF_AP) { -// s_esp_netifs[MDNS_IF_AP] = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); -//#if CONFIG_ETH_ENABLED -// } else if (tcpip_if == MDNS_IF_ETH) { -// s_esp_netifs[MDNS_IF_ETH] = esp_netif_get_handle_from_ifkey("ETH_DEF"); -//#endif -// } + if (s_esp_netifs[tcpip_if].netif == NULL && s_esp_netifs[tcpip_if].predefined == MDNS_USES_PREDEFINED_IF) { + // if a predefined interface face and used local copy is NULL, try to search for the default interface key + s_esp_netifs[tcpip_if].netif = esp_netif_from_preset_if(s_esp_netifs[tcpip_if].predef_if); } return s_esp_netifs[tcpip_if].netif; } @@ -1069,11 +1101,9 @@ static uint16_t _mdns_append_question(uint8_t * packet, uint16_t * index, mdns_o */ static mdns_if_t _mdns_get_other_if (mdns_if_t tcpip_if) { -// if (tcpip_if == MDNS_IF_STA) { -// return MDNS_IF_ETH; -// } else if (tcpip_if == MDNS_IF_ETH) { -// return MDNS_IF_STA; -// } + if (tcpip_if > MDNS_IF_INVALID && tcpip_if < MDNS_IF_MAX) { + return s_esp_netifs[tcpip_if].duplicate; + } return MDNS_IF_MAX; } @@ -3789,97 +3819,79 @@ void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) } /** - * @brief Dispatch interface changes based on system events + * @brief Performs interface changes based on system events or custom commands */ -void _action_enable_pcb_dhcps_status_check(esp_netif_t *netif, mdns_if_t interface) { - esp_netif_dhcp_status_t dcst; - - if (!esp_netif_dhcpc_get_status(netif, &dcst)) { - if (dcst == ESP_NETIF_DHCP_STOPPED) { - _mdns_enable_pcb(interface, MDNS_IP_PROTOCOL_V4); - } +static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) +{ + if (!_mdns_server || mdns_if > MDNS_IF_MAX) { + return; + } + if (action & MDNS_EVENT_ENABLE_IP4) { + _mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); + } + if (action & MDNS_EVENT_ENABLE_IP6) { + _mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); + } + if (action & MDNS_EVENT_DISABLE_IP4) { + _mdns_disable_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); + } + if (action & MDNS_EVENT_DISABLE_IP6) { + _mdns_disable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); + } + if (action & MDNS_EVENT_ANNOUNCE_IP4) { + _mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4, NULL, 0, true); + } + if (action & MDNS_EVENT_ANNOUNCE_IP6) { + _mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V6, NULL, 0, true); } } -void _action_enable_pcb(mdns_if_t interface) { - _mdns_enable_pcb(interface, MDNS_IP_PROTOCOL_V4); -} - -void _action_announce_pcb(mdns_if_t interface) { - _mdns_enable_pcb(interface, MDNS_IP_PROTOCOL_V4); -} - -void _action_enable_announce_pcb(mdns_if_t interface) { - _mdns_enable_pcb(interface, MDNS_IP_PROTOCOL_V4); - _mdns_announce_pcb(interface, MDNS_IP_PROTOCOL_V6, NULL, 0, true); -} - -void _action_disable_pcb(mdns_if_t interface) { - _mdns_disable_pcb(interface, MDNS_IP_PROTOCOL_V4); - _mdns_disable_pcb(interface, MDNS_IP_PROTOCOL_V6); -} - -#define CONFIG_MDNS_EVENT_ACTIONS 5 /** * @brief Dispatch interface changes based on system events */ -static void _mdns_handle_system_event(esp_event_base_t event_base, - int32_t event_id, esp_netif_t* interface) +static inline void post_mdns_disable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) { - if (!_mdns_server) { - return; - } - mdns_if_t mdns_if = _mdns_get_if_from_esp_netif(interface); - - if (mdns_if > MDNS_IF_MAX) { - return; - } - - for (int i = 0; i < CONFIG_MDNS_EVENT_ACTIONS; ++i) { // TO-DO - if (s_esp_netifs[mdns_if].actions[i].event_id == event_id) { - if (s_esp_netifs[mdns_if].actions[i].action == ACTION_ENABLE) { - _action_enable_pcb(mdns_if); - } - if (s_esp_netifs[mdns_if].actions[i].action == ACTION_ENABLE_WITH_DHCP_CHECK) { - _action_enable_pcb_dhcps_status_check(interface, mdns_if); - } - if (s_esp_netifs[mdns_if].actions[i].action == ACTION_ENABLE_ANNOUNCE) { - _action_enable_announce_pcb(mdns_if); - } - if (s_esp_netifs[mdns_if].actions[i].action == ACTION_DISABLE) { - _action_disable_pcb(mdns_if); - } - } - } + mdns_post_custom_action_tcpip_if(mdns_if_from_predef_if(preset_if), protocol==MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_DISABLE_IP4 : MDNS_EVENT_DISABLE_IP6); } -#if 0 -static void _mdns_handle_system_event(esp_event_base_t event_base, - int32_t event_id, esp_netif_t* interface) + +static inline void post_mdns_enable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) +{ + mdns_post_custom_action_tcpip_if(mdns_if_from_predef_if(preset_if), protocol==MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_ENABLE_IP4 : MDNS_EVENT_ENABLE_IP6); +} + +static inline void post_mdns_announce_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) +{ + mdns_post_custom_action_tcpip_if(mdns_if_from_predef_if(preset_if), protocol==MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_ANNOUNCE_IP4 : MDNS_EVENT_ANNOUNCE_IP6); +} + +void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { if (!_mdns_server) { return; } + esp_netif_dhcp_status_t dcst; if (event_base == WIFI_EVENT) { switch(event_id) { case WIFI_EVENT_STA_CONNECTED: - if (!esp_netif_dhcpc_get_status(_mdns_get_esp_netif(MDNS_IF_STA), &dcst)) { + if (!esp_netif_dhcpc_get_status(esp_netif_from_preset_if(MDNS_IF_STA), &dcst)) { if (dcst == ESP_NETIF_DHCP_STOPPED) { - _mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + post_mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); } } break; case WIFI_EVENT_STA_DISCONNECTED: - _mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); - _mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6); + post_mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + post_mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6); break; case WIFI_EVENT_AP_START: - _mdns_enable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); + post_mdns_enable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); break; case WIFI_EVENT_AP_STOP: - _mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); - _mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V6); + post_mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); + post_mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V6); break; default: break; @@ -3889,15 +3901,15 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, else if (event_base == ETH_EVENT) { switch (event_id) { case ETHERNET_EVENT_CONNECTED: - if (!esp_netif_dhcpc_get_status(_mdns_get_esp_netif(MDNS_IF_ETH), &dcst)) { + if (!esp_netif_dhcpc_get_status(esp_netif_from_preset_if(MDNS_IF_ETH), &dcst)) { if (dcst == ESP_NETIF_DHCP_STOPPED) { - _mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + post_mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); } } break; case ETHERNET_EVENT_DISCONNECTED: - _mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); - _mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V6); + post_mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + post_mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V6); break; default: break; @@ -3907,20 +3919,21 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, else if (event_base == IP_EVENT) { switch (event_id) { case IP_EVENT_STA_GOT_IP: - _mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); - _mdns_announce_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6, NULL, 0, true); + post_mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + post_mdns_announce_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6); break; #if CONFIG_ETH_ENABLED case IP_EVENT_ETH_GOT_IP: - _mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + post_mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); break; #endif case IP_EVENT_GOT_IP6: { - mdns_if_t mdns_if = _mdns_get_if_from_esp_netif(interface); + ip_event_got_ip6_t* event = (ip_event_got_ip6_t*) event_data; + mdns_if_t mdns_if = _mdns_get_if_from_esp_netif(event->esp_netif); if (mdns_if != MDNS_IF_MAX) { - _mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); - _mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4, NULL, 0, true); + post_mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); + post_mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); } } @@ -3930,7 +3943,6 @@ static void _mdns_handle_system_event(esp_event_base_t event_base, } } } -#endif /* * MDNS Search @@ -4600,8 +4612,7 @@ 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_base, - action->data.sys_event.event_id, action->data.sys_event.interface); + perform_event_action(action->data.sys_event.interface, action->data.sys_event.event_action); break; case ACTION_HOSTNAME_SET: _mdns_send_bye_all_pcbs_no_instance(true); @@ -5014,33 +5025,51 @@ static esp_err_t _mdns_service_task_stop(void) return ESP_OK; } -/* - * Public Methods - * */ - -static void event_handler(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) +static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action) { - if (!_mdns_server) { - return; + if (!_mdns_server || mdns_if >= MDNS_IF_MAX) { + return ESP_FAIL; } mdns_action_t * action = (mdns_action_t *)calloc(1, sizeof(mdns_action_t)); if (!action) { HOOK_MALLOC_FAILED; - return; + return ESP_ERR_NO_MEM; } action->type = ACTION_SYSTEM_EVENT; - 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->esp_netif; - } + action->data.sys_event.event_action = event_action; + action->data.sys_event.interface = mdns_if; if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { free(action); } + return ESP_OK; +} + +static inline void set_default_duplicated_interfaces(void) +{ + mdns_if_t wifi_sta_if = MDNS_IF_MAX, eth_if = MDNS_IF_MAX; + for (mdns_if_t i=0; iaction_queue); free_lock: @@ -5135,10 +5168,10 @@ void mdns_free(void) } // Unregister handlers before destroying the mdns internals to avoid receiving async events while deinit - esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler); - esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler); + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event); + esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event); #if CONFIG_ETH_ENABLED - esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler); + esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event); #endif mdns_service_remove_all(); diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 44535747f..e766146a7 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -404,9 +404,8 @@ typedef struct { } hostname_set; char * instance; struct { - esp_event_base_t event_base; - int32_t event_id; - esp_netif_t* interface; + mdns_if_t interface; + mdns_event_actions_t event_action; } sys_event; struct { mdns_srv_item_t * service; diff --git a/examples/protocols/mdns/main/mdns_example_wifi_main.c b/examples/protocols/mdns/main/mdns_example_wifi_main.c deleted file mode 100644 index 64837b195..000000000 --- a/examples/protocols/mdns/main/mdns_example_wifi_main.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -/* MDNS-SD Query and advertise Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_netif_ip_addr.h" -#include "esp_system.h" -#include "esp_event.h" -#include "esp_log.h" -#include "nvs_flash.h" -#include "esp_netif.h" -#include "protocol_examples_common.h" -#include "mdns.h" -#include "driver/gpio.h" -#include "netdb.h" -#include "esp_wifi.h" - -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event.h" -#include "esp_log.h" -#include "nvs_flash.h" - -#include "lwip/err.h" -#include "lwip/sys.h" -// #include "mdns_if_defaults.h" - - -/* FreeRTOS event group to signal when we are connected*/ -// static EventGroupHandle_t s_wifi_event_group; - -#define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE -#define EXAMPLE_BUTTON_GPIO 0 - -static const char * TAG = "mdns-test"; -static char * generate_hostname(void); - -#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 -static void query_mdns_host_with_gethostbyname(char * host); -static void query_mdns_host_with_getaddrinfo(char * host); -#endif - -static int s_retry_num = 0; - -// #define EXAMPLE_ESP_WIFI_SSID "Coworking" -#define EXAMPLE_ESP_WIFI_SSID "Coworking" -#define EXAMPLE_ESP_WIFI_PASS "Coworkers" - -#define EXAMPLE_ESP_MAXIMUM_RETRY 2 - -#define WIFI_CONNECTED_BIT BIT0 -#define WIFI_FAIL_BIT BIT1 - -static void event_handler(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) -{ - if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { - esp_wifi_connect(); - } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { - if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { - esp_wifi_connect(); - s_retry_num++; - ESP_LOGI(TAG, "retry to connect to the AP"); - } else { - // xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); - } - ESP_LOGI(TAG,"connect to the AP fail"); - } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { - ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; - ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); - s_retry_num = 0; - //xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); - } -} - -static void initialise_mdns(void) -{ - esp_netif_t* netif_wifi = esp_netif_create_default_wifi_sta(); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - - esp_event_handler_instance_t instance_any_id; - esp_event_handler_instance_t instance_got_ip; - ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, - ESP_EVENT_ANY_ID, - &event_handler, - NULL, - &instance_any_id)); - ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, - IP_EVENT_STA_GOT_IP, - &event_handler, - NULL, - &instance_got_ip)); - - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_ESP_WIFI_SSID, - .password = EXAMPLE_ESP_WIFI_PASS, - /* Setting a password implies station will connect to all security modes including WEP/WPA. - * However these modes are deprecated and not advisable to be used. Incase your Access point - * doesn't support WPA2, these mode can be enabled by commenting below line */ - .threshold.authmode = WIFI_AUTH_WPA2_PSK, - - .pmf_cfg = { - .capable = true, - .required = false - }, - }, - }; - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_start()); - - ESP_LOGI(TAG, "wifi_init_sta finished."); - - char * hostname = generate_hostname(); - - //initialize mDNS - // mdns_config_t mdns_config = MDNS_NETIF_DEFAULT_WIFI(netif_wifi); - - //_mdns_action_t _actions[] = { - // { - // .event_base = WIFI_EVENT, - // .event_id = WIFI_EVENT_STA_CONNECTED, - // .action = ACTION_ENABLE_WITH_DHCP_CHECK - // }, - // { - // .event_base = WIFI_EVENT, - // .event_id = WIFI_EVENT_STA_DISCONNECTED, - // .action = ACTION_DISABLE - // }, - // { - // .event_base = IP_EVENT, - // .event_id = IP_EVENT_STA_GOT_IP, - // .action = ACTION_ENABLE_ANNOUNCE - // } - // }; - - //mdns_config_t mdns_config = { - // .netif = netif_wifi, - // .num = 3, - // .next = {NULL}, - // .actions = _actions - //}; - - mdns_config_t * mdns_config = calloc(1, sizeof(struct mdns_config_s)); - mdns_config->netif = netif_wifi; - mdns_config->num = 3; - mdns_config->actions = malloc(sizeof(_mdns_action_t) * 3); - //mdns_config->actions = { { .esp_event_base_t = WIFI_EVENT, .event_id = WIFI_EVENT_STA_CONNECTED, .action = ACTION_ENABLE_WITH_DHCP_CHECK}}; - //mdns_config->actionsesp_event_base_t = WIFI_EVENT; - mdns_config->actions[0].event_base = WIFI_EVENT; - mdns_config->actions[0].event_id = WIFI_EVENT_STA_CONNECTED; - mdns_config->actions[0].action = ACTION_ENABLE_WITH_DHCP_CHECK; - - mdns_config->actions[1].event_base = WIFI_EVENT; - mdns_config->actions[1].event_id = WIFI_EVENT_STA_DISCONNECTED; - mdns_config->actions[1].action = ACTION_DISABLE; - - mdns_config->actions[2].event_base = IP_EVENT; - mdns_config->actions[2].event_id = IP_EVENT_STA_GOT_IP; - mdns_config->actions[2].action = ACTION_ENABLE_ANNOUNCE; - - ESP_ERROR_CHECK( mdns_init_cfg(mdns_config) ); // mdns_add_netif - - esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); - char * desc; - asprintf(&desc, "%s: %s", TAG, esp_netif_config.if_desc); - esp_netif_config.if_desc = desc; - esp_netif_config.route_prio = 64; - esp_netif_config_t netif_config = { - .base = &esp_netif_config, - .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH - }; - - - esp_netif_t * netif_eth = esp_netif_new(&netif_config); - mdns_config_t * mdns_config_eth = calloc(1, sizeof(struct mdns_config_s)); - mdns_config_eth->netif = netif_eth; - mdns_config_eth->num = 2; - mdns_config_eth->actions = malloc(sizeof(_mdns_action_t) * 3); - //mdns_config->actions = { { .esp_event_base_t = WIFI_EVENT, .event_id = WIFI_EVENT_STA_CONNECTED, .action = ACTION_ENABLE_WITH_DHCP_CHECK}}; - mdns_config_eth->actions[0].event_base = ETH_EVENT; - mdns_config_eth->actions[0].event_id = ETHERNET_EVENT_CONNECTED; - mdns_config_eth->actions[0].action = ACTION_ENABLE; - - - mdns_config_eth->actions[1].event_base = ETH_EVENT; - mdns_config_eth->actions[1].event_id = ETHERNET_EVENT_DISCONNECTED; - mdns_config_eth->actions[1].action = ACTION_DISABLE; - - mdns_cfg_add_to_list(mdns_config_eth); - - //set mDNS hostname (required if you want to advertise services) - ESP_ERROR_CHECK( mdns_hostname_set(hostname) ); - ESP_LOGI(TAG, "mdns hostname set to: [%s]", hostname); - //set default mDNS instance name - ESP_ERROR_CHECK( mdns_instance_name_set(EXAMPLE_MDNS_INSTANCE) ); - - //structure with TXT records - mdns_txt_item_t serviceTxtData[3] = { - {"board", "esp32"}, - {"u", "user"}, - {"p", "password"} - }; - - //initialize service - ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) ); - -#if CONFIG_MDNS_PUBLISH_DELEGATE_HOST - char *delegated_hostname; - if (-1 == asprintf(&delegated_hostname, "%s-delegated", hostname)) { - abort(); - } - - mdns_ip_addr_t addr4, addr6; - esp_netif_str_to_ip4("10.0.0.1", &addr4.addr.u_addr.ip4); - addr4.addr.type = ESP_IPADDR_TYPE_V4; - esp_netif_str_to_ip6("fd11:22::1", &addr6.addr.u_addr.ip6); - addr6.addr.type = ESP_IPADDR_TYPE_V6; - addr4.next = &addr6; - addr6.next = NULL; - ESP_ERROR_CHECK( mdns_delegate_hostname_add(delegated_hostname, &addr4) ); - ESP_ERROR_CHECK( mdns_service_add_for_host("test0", "_http", "_tcp", delegated_hostname, 1234, serviceTxtData, 3) ); - free(delegated_hostname); -#endif // CONFIG_MDNS_PUBLISH_DELEGATE_HOST - - //add another TXT item - ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") ); - //change TXT item value - ESP_ERROR_CHECK( mdns_service_txt_item_set_with_explicit_value_len("_http", "_tcp", "u", "admin", strlen("admin")) ); - free(hostname); -} - -/* these strings match tcpip_adapter_if_t enumeration */ -// static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; - -/* these strings match mdns_ip_protocol_t enumeration */ -// static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; - -static void mdns_print_results(mdns_result_t *results) -{ - mdns_result_t *r = results; - mdns_ip_addr_t *a = NULL; - //int i = 1; - int t; - while(r){ - //printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]); - if(r->instance_name){ - printf(" PTR : %s\n", r->instance_name); - } - if (r->hostname) { - printf(" SRV : %s.local:%u\n", r->hostname, r->port); - } - if (r->txt_count) { - printf(" TXT : [%zu] ", r->txt_count); - for (t = 0; t < r->txt_count; t++) { - printf("%s=%s(%d); ", r->txt[t].key, r->txt[t].value ? r->txt[t].value : "NULL", r->txt_value_len[t]); - } - printf("\n"); - } - a = r->addr; - while (a) { - if (a->addr.type == ESP_IPADDR_TYPE_V6) { - printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); - } else { - printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); - } - a = a->next; - } - r = r->next; - } -} - -static void query_mdns_service(const char * service_name, const char * proto) -{ - ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); - - mdns_result_t * results = NULL; - esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); - if(err){ - ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); - return; - } - if(!results){ - ESP_LOGW(TAG, "No results found!"); - return; - } - - mdns_print_results(results); - mdns_query_results_free(results); -} - -static bool check_and_print_result(mdns_search_once_t *search) -{ - // Check if any result is available - mdns_result_t * result = NULL; - if (!mdns_query_async_get_results(search, 0, &result)) { - return false; - } - - if (!result) { // search timeout, but no result - return true; - } - - // If yes, print the result - mdns_ip_addr_t * a = result->addr; - while (a) { - if(a->addr.type == ESP_IPADDR_TYPE_V6){ - printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); - } else { - printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); - } - a = a->next; - } - // and free the result - mdns_query_results_free(result); - return true; -} - -static void query_mdns_hosts_async(const char * host_name) -{ - ESP_LOGI(TAG, "Query both A and AAA: %s.local", host_name); - - mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1, NULL); - mdns_query_async_delete(s_a); - mdns_search_once_t *s_aaaa = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_AAAA, 1000, 1, NULL); - while (s_a || s_aaaa) { - if (s_a && check_and_print_result(s_a)) { - ESP_LOGI(TAG, "Query A %s.local finished", host_name); - mdns_query_async_delete(s_a); - s_a = NULL; - } - if (s_aaaa && check_and_print_result(s_aaaa)) { - ESP_LOGI(TAG, "Query AAAA %s.local finished", host_name); - mdns_query_async_delete(s_aaaa); - s_aaaa = NULL; - } - } -} - -static void query_mdns_host(const char * host_name) -{ - ESP_LOGI(TAG, "Query A: %s.local", host_name); - - struct esp_ip4_addr addr; - addr.addr = 0; - - esp_err_t err = mdns_query_a(host_name, 2000, &addr); - if(err){ - if(err == ESP_ERR_NOT_FOUND){ - ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err)); - return; - } - ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); - return; - } - - ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr)); -} - -static void initialise_button(void) -{ - gpio_config_t io_conf = {0}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.pin_bit_mask = BIT64(EXAMPLE_BUTTON_GPIO); - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pull_up_en = 1; - io_conf.pull_down_en = 0; - gpio_config(&io_conf); -} - -static void check_button(void) -{ - static bool old_level = true; - bool new_level = gpio_get_level(EXAMPLE_BUTTON_GPIO); - if (!new_level && old_level) { - query_mdns_hosts_async("esp32-mdns"); - query_mdns_host("esp32"); - query_mdns_service("_arduino", "_tcp"); - query_mdns_service("_http", "_tcp"); - query_mdns_service("_printer", "_tcp"); - query_mdns_service("_ipp", "_tcp"); - query_mdns_service("_afpovertcp", "_tcp"); - query_mdns_service("_smb", "_tcp"); - query_mdns_service("_ftp", "_tcp"); - query_mdns_service("_nfs", "_tcp"); - } - old_level = new_level; -} - -static void mdns_example_task(void *pvParameters) -{ -#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 - /* Send initial queries that are started by CI tester */ - query_mdns_host("tinytester"); - query_mdns_host_with_gethostbyname("tinytester-lwip.local"); - query_mdns_host_with_getaddrinfo("tinytester-lwip.local"); -#endif - - while (1) { - check_button(); - vTaskDelay(50 / portTICK_PERIOD_MS); - } -} - -void app_main(void) -{ - ESP_ERROR_CHECK(nvs_flash_init()); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - initialise_mdns(); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - // ESP_ERROR_CHECK(example_connect()); // To-do, change this to explicitelly register first for wifi interface, then add new one - - initialise_button(); - xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL); -} - -/** Generate host name based on sdkconfig, optionally adding a portion of MAC address to it. - * @return host name string allocated from the heap - */ -static char* generate_hostname(void) -{ -#ifndef CONFIG_MDNS_ADD_MAC_TO_HOSTNAME - return strdup(CONFIG_MDNS_HOSTNAME); -#else - uint8_t mac[6]; - char *hostname; - esp_read_mac(mac, ESP_MAC_WIFI_STA); - if (-1 == asprintf(&hostname, "%s-%02X%02X%02X", CONFIG_MDNS_HOSTNAME, mac[3], mac[4], mac[5])) { - abort(); - } - return hostname; -#endif -} - -#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 -/** - * @brief Executes gethostbyname and displays list of resolved addresses. - * Note: This function is used only to test advertised mdns hostnames resolution - */ -static void query_mdns_host_with_gethostbyname(char * host) -{ - struct hostent *res = gethostbyname(host); - if (res) { - unsigned int i = 0; - while (res->h_addr_list[i] != NULL) { - ESP_LOGI(TAG, "gethostbyname: %s resolved to: %s", host, inet_ntoa(*(struct in_addr *) (res->h_addr_list[i]))); - i++; - } - } -} - -/** - * @brief Executes getaddrinfo and displays list of resolved addresses. - * Note: This function is used only to test advertised mdns hostnames resolution - */ -static void query_mdns_host_with_getaddrinfo(char * host) -{ - struct addrinfo hints; - struct addrinfo * res; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - if (!getaddrinfo(host, NULL, &hints, &res)) { - while (res) { - ESP_LOGI(TAG, "getaddrinfo: %s resolved to: %s", host, - res->ai_family == AF_INET? - inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr): - inet_ntoa(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr)); - res = res->ai_next; - } - } -} -#endif From ddc58e8220f8b4d8829cfe47cfecdf071e92c845 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 14 Dec 2021 16:14:21 +0100 Subject: [PATCH 274/289] mdns: Indicate interface using esp_netif in search results * Original commit: espressif/esp-idf@f8495f1e86de9a8e7d046bf13d0ca04775041b4c --- components/mdns/Kconfig | 33 ++++ components/mdns/include/mdns.h | 9 +- components/mdns/mdns.c | 147 ++++++++++-------- components/mdns/mdns_console.c | 26 ++-- components/mdns/mdns_networking_lwip.c | 6 +- components/mdns/mdns_networking_socket.c | 6 +- .../mdns/private_include/mdns_private.h | 25 ++- .../protocols/mdns/main/mdns_example_main.c | 5 +- 8 files changed, 156 insertions(+), 101 deletions(-) diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig index 5607afac8..7ceefd88d 100644 --- a/components/mdns/Kconfig +++ b/components/mdns/Kconfig @@ -1,5 +1,13 @@ menu "mDNS" + config MDNS_MAX_INTERFACES + int "Max number of interfaces" + range 1 9 + default 3 + help + Number of network interfaces to be served by the mdns library. + Lowering this number helps to reduce some static RAM usage. + config MDNS_MAX_SERVICES int "Max number of services" range 1 64 @@ -90,4 +98,29 @@ menu "mDNS" help Enables adding multiple service instances under the same service type. + menu "MDNS Predefined interfaces" + + config MDNS_PREDEF_NETIF_STA + bool "Use predefined interface for WiFi Station" + default y + help + Set up mdns for the default WiFi station. + Disable this option if you do not need mDNS on default WiFi STA. + + config MDNS_PREDEF_NETIF_AP + bool "Use predefined interface for WiFi Access Point" + default y + help + Set up mdns for the default WiFi Access Point. + Disable this option if you do not need mDNS on default WiFi AP. + + config MDNS_PREDEF_NETIF_ETH + bool "Use predefined interface for Ethernet" + default y + help + Set up mdns for the default Ethernet interface. + Disable this option if you do not need mDNS on default Ethernet. + + endmenu # MDNS Predefined interfaces + endmenu diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index fb14077b4..ab4e97ac3 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -21,8 +21,6 @@ extern "C" { #define MDNS_TYPE_NSEC 0x002F #define MDNS_TYPE_ANY 0x00FF -#define CONFIG_MDNS_IF_MAX 4 - /** * @brief Asynchronous query handle */ @@ -64,11 +62,6 @@ typedef struct mdns_ip_addr_s { struct mdns_ip_addr_s * next; /*!< next IP, or NULL for the last IP in the list */ } mdns_ip_addr_t; -typedef enum mdns_if_internal { - MDNS_IF_INVALID = -1, - MDNS_IF_MAX = CONFIG_MDNS_IF_MAX -} mdns_if_t; - /** * @brief mDNS query type to be explicitly set to either Unicast or Multicast */ @@ -83,7 +76,7 @@ typedef enum { typedef struct mdns_result_s { struct mdns_result_s * next; /*!< next result, or NULL for the last result in the list */ - mdns_if_t tcpip_if; /*!< interface index */ + esp_netif_t* esp_netif; /*!< ptr to corresponding esp-netif */ uint32_t ttl; /*!< time to live */ mdns_ip_protocol_t ip_protocol; /*!< ip_protocol type of the interface (v4/v6) */ diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 27c6797cd..50996cf7f 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -59,11 +59,6 @@ static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, static void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); -typedef enum mdns_netif_predef { - MDNS_USES_PREDEFINED_IF = 0, - MDNS_USES_CUSTOM_IF = 1, -} mdns_netif_predef_t; - typedef enum { MDNS_IF_STA = 0, MDNS_IF_AP = 1, @@ -73,7 +68,7 @@ typedef enum { typedef struct mdns_interfaces mdns_interfaces_t; struct mdns_interfaces { - mdns_netif_predef_t predefined; + bool predefined; esp_netif_t * netif; mdns_predef_if_t predef_if; mdns_if_t duplicate; @@ -83,10 +78,16 @@ struct mdns_interfaces { * @brief Internal collection of mdns supported interfaces * */ -static mdns_interfaces_t s_esp_netifs[MDNS_IF_MAX] = { - { .predefined = MDNS_USES_PREDEFINED_IF, .netif = NULL, .predef_if = MDNS_IF_STA, .duplicate = MDNS_IF_MAX }, - { .predefined = MDNS_USES_PREDEFINED_IF, .netif = NULL, .predef_if = MDNS_IF_AP, .duplicate = MDNS_IF_MAX }, - { .predefined = MDNS_USES_PREDEFINED_IF, .netif = NULL, .predef_if = MDNS_IF_ETH, .duplicate = MDNS_IF_MAX }, +static mdns_interfaces_t s_esp_netifs[MDNS_MAX_INTERFACES] = { +#if CONFIG_MDNS_PREDEF_NETIF_STA + { .predefined = true, .netif = NULL, .predef_if = MDNS_IF_STA, .duplicate = MDNS_MAX_INTERFACES }, +#endif +#if CONFIG_MDNS_PREDEF_NETIF_AP + { .predefined = true, .netif = NULL, .predef_if = MDNS_IF_AP, .duplicate = MDNS_MAX_INTERFACES }, +#endif +#if CONFIG_MDNS_PREDEF_NETIF_ETH + { .predefined = true, .netif = NULL, .predef_if = MDNS_IF_ETH, .duplicate = MDNS_MAX_INTERFACES }, +#endif }; @@ -95,12 +96,12 @@ static mdns_interfaces_t s_esp_netifs[MDNS_IF_MAX] = { */ static mdns_if_t mdns_if_from_predef_if(mdns_predef_if_t predef_if) { - for (int i=0; i MDNS_IF_INVALID && tcpip_if < MDNS_IF_MAX) { - if (s_esp_netifs[tcpip_if].netif == NULL && s_esp_netifs[tcpip_if].predefined == MDNS_USES_PREDEFINED_IF) { + if (tcpip_if < MDNS_MAX_INTERFACES) { + if (s_esp_netifs[tcpip_if].netif == NULL && s_esp_netifs[tcpip_if].predefined) { // if a predefined interface face and used local copy is NULL, try to search for the default interface key s_esp_netifs[tcpip_if].netif = esp_netif_from_preset_if(s_esp_netifs[tcpip_if].predef_if); } @@ -136,7 +137,7 @@ esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) * @brief Clean internal mdns interface's pointer */ static inline void _mdns_clean_netif_ptr(mdns_if_t tcpip_if) { - if (tcpip_if < MDNS_IF_MAX) { + if (tcpip_if < MDNS_MAX_INTERFACES) { s_esp_netifs[tcpip_if].netif = NULL; } } @@ -147,11 +148,11 @@ static inline void _mdns_clean_netif_ptr(mdns_if_t tcpip_if) { */ static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *interface) { - for (int i=0; i MDNS_IF_INVALID && tcpip_if < MDNS_IF_MAX) { + if (tcpip_if < MDNS_MAX_INTERFACES) { return s_esp_netifs[tcpip_if].duplicate; } - return MDNS_IF_MAX; + return MDNS_MAX_INTERFACES; } /** @@ -1113,7 +1114,7 @@ static mdns_if_t _mdns_get_other_if (mdns_if_t tcpip_if) static bool _mdns_if_is_dup(mdns_if_t tcpip_if) { mdns_if_t other_if = _mdns_get_other_if (tcpip_if); - if (other_if == MDNS_IF_MAX) { + if (other_if == MDNS_MAX_INTERFACES) { return false; } if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP @@ -2119,7 +2120,7 @@ static void _mdns_send_bye(mdns_srv_item_t ** services, size_t len, bool include return; } - for (i=0; iinterfaces[i].pcbs[j].pcb && _mdns_server->interfaces[i].pcbs[j].state == PCB_RUNNING) { _mdns_pcb_send_bye((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); @@ -2177,7 +2178,7 @@ static void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco static void _mdns_probe_all_pcbs(mdns_srv_item_t ** services, size_t len, bool probe_ip, bool clear_old_probe) { uint8_t i, j; - for (i=0; iinterfaces[i].pcbs[j].pcb) { mdns_pcb_t * _pcb = &_mdns_server->interfaces[i].pcbs[j]; @@ -2199,7 +2200,7 @@ static void _mdns_probe_all_pcbs(mdns_srv_item_t ** services, size_t len, bool p static void _mdns_announce_all_pcbs(mdns_srv_item_t ** services, size_t len, bool include_ip) { uint8_t i, j; - for (i=0; itype == MDNS_TYPE_PTR) { result = search_result->result; while (result) { - if (packet->tcpip_if == result->tcpip_if + if (_mdns_get_esp_netif(packet->tcpip_if) == result->esp_netif && packet->ip_protocol == result->ip_protocol && result->instance_name && !strcmp(name->host, result->instance_name)) { break; @@ -3602,7 +3603,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) if (search_result->type == MDNS_TYPE_PTR) { result = search_result->result; while (result) { - if (packet->tcpip_if == result->tcpip_if + if (_mdns_get_esp_netif(packet->tcpip_if) == result->esp_netif && packet->ip_protocol == result->ip_protocol && result->instance_name && !strcmp(name->host, result->instance_name)) { break; @@ -3810,7 +3811,7 @@ void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); _mdns_pcb_deinit(tcpip_if, ip_protocol); mdns_if_t other_if = _mdns_get_other_if (tcpip_if); - if (other_if != MDNS_IF_MAX && _mdns_server->interfaces[other_if].pcbs[ip_protocol].state == PCB_DUP) { + if (other_if != MDNS_MAX_INTERFACES && _mdns_server->interfaces[other_if].pcbs[ip_protocol].state == PCB_DUP) { _mdns_server->interfaces[other_if].pcbs[ip_protocol].state = PCB_OFF; _mdns_enable_pcb(other_if, ip_protocol); } @@ -3823,7 +3824,7 @@ void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) */ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) { - if (!_mdns_server || mdns_if > MDNS_IF_MAX) { + if (!_mdns_server || mdns_if > MDNS_MAX_INTERFACES) { return; } if (action & MDNS_EVENT_ENABLE_IP4) { @@ -3871,7 +3872,6 @@ void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, return; } - esp_netif_dhcp_status_t dcst; if (event_base == WIFI_EVENT) { switch(event_id) { @@ -3931,7 +3931,7 @@ void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, { ip_event_got_ip6_t* event = (ip_event_got_ip6_t*) event_data; mdns_if_t mdns_if = _mdns_get_if_from_esp_netif(event->esp_netif); - if (mdns_if != MDNS_IF_MAX) { + if (mdns_if < MDNS_MAX_INTERFACES) { post_mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); post_mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); } @@ -4120,7 +4120,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * || search->type == MDNS_TYPE_ANY) { r = search->result; while (r) { - if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { _mdns_result_add_ip(r, ip); _mdns_result_update_ttl(r, ttl); return; @@ -4144,7 +4144,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * a->next = r->addr; r->hostname = strdup(hostname); r->addr = a; - r->tcpip_if = tcpip_if; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->next = search->result; r->ttl = ttl; @@ -4154,7 +4154,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * } else if (search->type == MDNS_TYPE_PTR || search->type == MDNS_TYPE_SRV) { r = search->result; while (r) { - if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { _mdns_result_add_ip(r, ip); _mdns_result_update_ttl(r, ttl); break; @@ -4173,7 +4173,7 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, { mdns_result_t * r = search->result; while (r) { - if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { _mdns_result_update_ttl(r, ttl); return r; } @@ -4195,7 +4195,7 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, return NULL; } - r->tcpip_if = tcpip_if; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = search->result; @@ -4214,7 +4214,7 @@ static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char * { mdns_result_t * r = search->result; while (r) { - if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { _mdns_result_update_ttl(r, ttl); return; } @@ -4239,7 +4239,7 @@ static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char * r->service_type = strdup(search->service); r->proto = strdup(search->proto); r->port = port; - r->tcpip_if = tcpip_if; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = search->result; @@ -4257,7 +4257,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_ite { mdns_result_t * r = search->result; while (r) { - if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { if (r->txt) { goto free_txt; } @@ -4280,7 +4280,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_ite r->txt = txt; r->txt_value_len = txt_value_len; r->txt_count = txt_count; - r->tcpip_if = tcpip_if; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); r->ip_protocol = ip_protocol; r->ttl = ttl; r->next = search->result; @@ -4325,7 +4325,7 @@ static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * s, mdns_ } r = s->result; while (r) { - if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { return s; } r = r->next; @@ -4398,7 +4398,7 @@ static mdns_tx_packet_t * _mdns_create_search_packet(mdns_search_once_t * search r = search->result; while (r) { //full record on the same interface is available - if (r->tcpip_if != tcpip_if || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { + if (r->esp_netif != _mdns_get_esp_netif(tcpip_if) || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { r = r->next; continue; } @@ -4462,7 +4462,7 @@ static void _mdns_search_send(mdns_search_once_t * search) } uint8_t i, j; - for (i=0; i= MDNS_IF_MAX) { + if (!_mdns_server || mdns_if >= MDNS_MAX_INTERFACES) { return ESP_FAIL; } @@ -5048,21 +5048,35 @@ static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_ static inline void set_default_duplicated_interfaces(void) { - mdns_if_t wifi_sta_if = MDNS_IF_MAX, eth_if = MDNS_IF_MAX; - for (mdns_if_t i=0; ilock = xSemaphoreCreateMutex(); if (!_mdns_server->lock) { @@ -5100,13 +5116,18 @@ esp_err_t mdns_init(void) err = ESP_ERR_NO_MEM; goto free_lock; } + +#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP if ((err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event, NULL)) != ESP_OK) { goto free_event_handlers; } +#endif +#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH if ((err = esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event, NULL)) != ESP_OK) { goto free_event_handlers; } -#if CONFIG_ETH_ENABLED +#endif +#if defined(CONFIG_ETH_ENABLED) && CONFIG_MDNS_PREDEF_NETIF_ETH if ((err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event, NULL)) != ESP_OK) { goto free_event_handlers; } @@ -5120,7 +5141,7 @@ esp_err_t mdns_init(void) #endif esp_netif_ip_info_t if_ip_info; - for (i=0; iaction_queue); free_lock: vSemaphoreDelete(_mdns_server->lock); @@ -5168,16 +5185,12 @@ void mdns_free(void) } // Unregister handlers before destroying the mdns internals to avoid receiving async events while deinit - esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event); - esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event); -#if CONFIG_ETH_ENABLED - esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event); -#endif + unregister_predefined_handlers(); mdns_service_remove_all(); free_delegated_hostnames(); _mdns_service_task_stop(); - for (i=0; i #include #include "esp_console.h" #include "argtable3/argtable3.h" #include "mdns.h" -static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; +static const char * if_str(esp_netif_t *netif) +{ + return esp_netif_get_ifkey(netif); +} + static void mdns_print_results(mdns_result_t * results) { mdns_result_t * r = results; mdns_ip_addr_t * a = NULL; int i = 1; while (r) { - printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]); + printf("%d: Interface: %s, Type: %s\n", i++, if_str(r->esp_netif), ip_protocol_str[r->ip_protocol]); if (r->instance_name) { printf(" PTR : %s\n", r->instance_name); } diff --git a/components/mdns/mdns_networking_lwip.c b/components/mdns/mdns_networking_lwip.c index 5f7a6673f..370661d12 100644 --- a/components/mdns/mdns_networking_lwip.c +++ b/components/mdns/mdns_networking_lwip.c @@ -134,7 +134,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip continue; } - packet->tcpip_if = MDNS_IF_MAX; + packet->tcpip_if = MDNS_MAX_INTERFACES; packet->pb = this_pb; packet->src_port = rport; #if CONFIG_LWIP_IPV6 @@ -164,7 +164,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces) struct netif * netif = NULL; struct udp_pcb * pcb = NULL; - for (i=0; iinterfaces[i].pcbs[packet->ip_protocol].pcb; netif = esp_netif_get_netif_impl(_mdns_get_esp_netif(i)); if (pcb && netif && netif == ip_current_input_netif ()) { @@ -198,7 +198,7 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip */ static bool _udp_pcb_is_in_use(void){ int i, p; - for (i=0; iinterfaces[i].pcbs[p].pcb){ return true; diff --git a/components/mdns/mdns_networking_socket.c b/components/mdns/mdns_networking_socket.c index 45ad83dec..f4341d4f6 100644 --- a/components/mdns/mdns_networking_socket.c +++ b/components/mdns/mdns_networking_socket.c @@ -101,7 +101,7 @@ esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) } } - for (int i=0; iinterfaces[i].pcbs[j].pcb) // If any of the interfaces/protocol initialized @@ -247,7 +247,7 @@ void sock_recv_task(void* arg) fd_set rfds; FD_ZERO(&rfds); int max_sock = -1; - for (int i=0; iinterfaces[i].pcbs[j].pcb); if (sock >= 0) { @@ -267,7 +267,7 @@ void sock_recv_task(void* arg) ESP_LOGE(TAG, "Select failed. errno=%d: %s", errno, strerror(errno)); break; } else if (s > 0) { - for (int tcpip_if=0; tcpip_ifinterfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb); if (sock < 0) { diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index e766146a7..bf1d6d8bf 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -41,6 +41,27 @@ * any item in question field */ #define MDNS_REPEAT_QUERY_IN_RESPONSE 1 #endif + +/** Number of predefined interfaces */ +#ifndef CONFIG_MDNS_PREDEF_NETIF_STA +#define CONFIG_MDNS_PREDEF_NETIF_STA 0 +#endif +#ifndef CONFIG_MDNS_PREDEF_NETIF_AP +#define CONFIG_MDNS_PREDEF_NETIF_AP 0 +#endif +#ifndef CONFIG_MDNS_PREDEF_NETIF_ETH +#define CONFIG_MDNS_PREDEF_NETIF_ETH 0 +#endif +#define MDNS_MAX_PREDEF_INTERFACES (CONFIG_MDNS_PREDEF_NETIF_STA + CONFIG_MDNS_PREDEF_NETIF_AP + CONFIG_MDNS_PREDEF_NETIF_ETH) + +/** Number of configured interfaces */ +#if MDNS_MAX_PREDEF_INTERFACES > CONFIG_MDNS_MAX_INTERFACES +#warning Number of configured interfaces is less then number of predefined interfaces. Please update CONFIG_MDNS_MAX_INTERFACES. +#define MDNS_MAX_INTERFACES (MDNS_MAX_PREDEF_INTERFACES) +#else +#define MDNS_MAX_INTERFACES (CONFIG_MDNS_MAX_INTERFACES) +#endif + /** The maximum number of services */ #define MDNS_MAX_SERVICES CONFIG_MDNS_MAX_SERVICES @@ -150,6 +171,8 @@ #define HOOK_MALLOC_FAILED ESP_LOGE(TAG, "Cannot allocate memory (line: %d, free heap: %d bytes)", __LINE__, esp_get_free_heap_size()); #endif +typedef size_t mdns_if_t; + typedef enum { PCB_OFF, PCB_DUP, PCB_INIT, PCB_PROBE_1, PCB_PROBE_2, PCB_PROBE_3, @@ -384,7 +407,7 @@ typedef struct mdns_search_once_s { typedef struct mdns_server_s { struct { mdns_pcb_t pcbs[MDNS_IP_PROTOCOL_MAX]; - } interfaces[MDNS_IF_MAX]; + } interfaces[MDNS_MAX_INTERFACES]; const char * hostname; const char * instance; mdns_srv_item_t * services; diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index c1db88ba0..5a90b5165 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -83,9 +83,6 @@ static void initialise_mdns(void) free(hostname); } -/* these strings match tcpip_adapter_if_t enumeration */ -static const char * if_str[] = {"STA", "AP", "ETH", "MAX"}; - /* these strings match mdns_ip_protocol_t enumeration */ static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; @@ -95,7 +92,7 @@ static void mdns_print_results(mdns_result_t *results) mdns_ip_addr_t *a = NULL; int i = 1, t; while (r) { - printf("%d: Interface: %s, Type: %s, TTL: %u\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol], + printf("%d: Interface: %s, Type: %s, TTL: %u\n", i++, esp_netif_get_ifkey(r->esp_netif), ip_protocol_str[r->ip_protocol], r->ttl); if (r->instance_name) { printf(" PTR : %s.%s.%s\n", r->instance_name, r->service_type, r->proto); From 30f37c05655e07a0678bfb5c9622bf781723f6b8 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 14 Dec 2021 18:07:23 +0100 Subject: [PATCH 275/289] mdns: Add support for registering custom netif * Original commit: espressif/esp-idf@bec42ff85d5091d71e1cb1063bea20d7c6ac8c76 --- components/mdns/include/mdns.h | 5 ++ components/mdns/mdns.c | 50 +++++++++++++++++++ .../protocols/mdns/main/Kconfig.projbuild | 9 ++++ .../protocols/mdns/main/mdns_example_main.c | 8 +++ 4 files changed, 72 insertions(+) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index ab4e97ac3..58121135a 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -719,6 +719,11 @@ esp_err_t mdns_query_a(const char * host_name, uint32_t timeout, esp_ip4_addr_t esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, esp_ip6_addr_t * addr); #endif + +esp_err_t mdns_add_custom_netif(esp_netif_t *esp_netif); +esp_err_t mdns_post_custom_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action); +esp_err_t mdns_delete_custom_netif(esp_netif_t *esp_netif); + #ifdef __cplusplus } #endif diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 50996cf7f..519365397 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -5086,6 +5086,52 @@ esp_err_t mdns_post_custom_action(esp_netif_t *esp_netif, mdns_event_actions_t e return mdns_post_custom_action_tcpip_if(_mdns_get_if_from_esp_netif(esp_netif), event_action); } +esp_err_t mdns_add_custom_netif(esp_netif_t *esp_netif) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = ESP_ERR_NO_MEM; + MDNS_SERVICE_LOCK(); + for (mdns_if_t i=0; iaction_queue); free_lock: vSemaphoreDelete(_mdns_server->lock); diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index bc4b1a055..b66e6f867 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -48,4 +48,13 @@ menu "Example Configuration" help Set the GPIO number used as mDNS test button + config MDNS_ADD_CUSTOM_NETIF + bool "Add user netif to mdns service" + default n + help + If enabled, we try to add a custom netif to mdns service. + Note that for using with common connection example code, we have to disable + all predefined interfaces in mdns component setup (since we're adding one + of the default interfaces) + endmenu diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 5a90b5165..c1a9ba868 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -266,6 +266,14 @@ void app_main(void) */ ESP_ERROR_CHECK(example_connect()); +#if defined(CONFIG_MDNS_ADD_CUSTOM_NETIF) && !defined(CONFIG_MDNS_PREDEF_NETIF_STA) && !defined(CONFIG_MDNS_PREDEF_NETIF_ETH) + /* Demonstration of adding a custom netif to mdns service, but we're adding the default example one, + * so we must disable all predefined interfaces (PREDEF_NETIF_STA, AP and ETH) first + */ + ESP_ERROR_CHECK(mdns_add_custom_netif(EXAMPLE_INTERFACE)); + ESP_ERROR_CHECK(mdns_post_custom_action(EXAMPLE_INTERFACE, MDNS_EVENT_ENABLE_IP4)); + ESP_ERROR_CHECK(mdns_post_custom_action(EXAMPLE_INTERFACE, MDNS_EVENT_ANNOUNCE_IP4)); +#endif initialise_button(); xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL); } From 05675c7d630f656f9d862b8c8b0e403e070f2a85 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 14 Dec 2021 18:34:04 +0100 Subject: [PATCH 276/289] CI/mdns: Extend example test for sockets, netifs * Original commit: espressif/esp-idf@d1b809e6a1807687e772cee819534634ed1378de --- examples/protocols/mdns/mdns_example_test.py | 29 ++++++++++++++----- .../protocols/mdns/sdkconfig.ci.custom_netif | 8 +++++ examples/protocols/mdns/sdkconfig.ci.socket | 5 ++++ 3 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 examples/protocols/mdns/sdkconfig.ci.custom_netif create mode 100644 examples/protocols/mdns/sdkconfig.ci.socket diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index f06707718..4307b9972 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -34,7 +34,7 @@ def get_dns_answer_to_mdns(tester_host): arr.type = dpkt.dns.DNS_A arr.name = tester_host arr.ip = socket.inet_aton('127.0.0.1') - dns. an.append(arr) + dns.an.append(arr) console_log('Created answer to mdns query: {} '.format(dns.__repr__())) return dns.pack() @@ -64,7 +64,7 @@ def mdns_server(esp_host): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) sock.setblocking(False) - sock.bind((UDP_IP,UDP_PORT)) + sock.bind((UDP_IP, UDP_PORT)) mreq = struct.pack('4sl', socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) last_query_timepoint = time.time() @@ -74,9 +74,9 @@ def mdns_server(esp_host): if current_time - last_query_timepoint > QUERY_TIMEOUT: last_query_timepoint = current_time if not esp_answered.is_set(): - sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT)) + sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP, UDP_PORT)) if not esp_delegated_answered.is_set(): - sock.sendto(get_dns_query_for_esp(esp_host + '-delegated'), (MCAST_GRP,UDP_PORT)) + sock.sendto(get_dns_query_for_esp(esp_host + '-delegated'), (MCAST_GRP, UDP_PORT)) timeout = max(0, QUERY_TIMEOUT - (current_time - last_query_timepoint)) read_socks, _, _ = select.select([sock], [], [], timeout) if not read_socks: @@ -86,7 +86,7 @@ def mdns_server(esp_host): if len(dns.qd) > 0 and dns.qd[0].type == dpkt.dns.DNS_A: if dns.qd[0].name == TESTER_NAME: console_log('Received query: {} '.format(dns.__repr__())) - sock.sendto(get_dns_answer_to_mdns(TESTER_NAME), (MCAST_GRP,UDP_PORT)) + sock.sendto(get_dns_answer_to_mdns(TESTER_NAME), (MCAST_GRP, UDP_PORT)) elif dns.qd[0].name == TESTER_NAME_LWIP: console_log('Received query: {} '.format(dns.__repr__())) sock.sendto(get_dns_answer_to_mdns_lwip(TESTER_NAME_LWIP, dns.id), addr) @@ -105,7 +105,7 @@ def mdns_server(esp_host): @ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') -def test_examples_protocol_mdns(env, extra_data): +def test_examples_protocol_mdns(env, config): global stop_mdns_server """ steps: | @@ -152,5 +152,20 @@ def test_examples_protocol_mdns(env, extra_data): mdns_responder.join() +@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') +def test_examples_protocol_mdns_default(env, _): + test_examples_protocol_mdns(env, None) + + +@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') +def test_examples_protocol_mdns_socket(env, _): + test_examples_protocol_mdns(env, 'socket') + + +@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') +def test_examples_protocol_mdns_custom_netif(env, _): + test_examples_protocol_mdns(env, 'custom_netif') + + if __name__ == '__main__': - test_examples_protocol_mdns() + test_examples_protocol_mdns_default() diff --git a/examples/protocols/mdns/sdkconfig.ci.custom_netif b/examples/protocols/mdns/sdkconfig.ci.custom_netif new file mode 100644 index 000000000..3550c5204 --- /dev/null +++ b/examples/protocols/mdns/sdkconfig.ci.custom_netif @@ -0,0 +1,8 @@ +CONFIG_MDNS_RESOLVE_TEST_SERVICES=y +CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +CONFIG_MDNS_PREDEF_NETIF_STA=n +CONFIG_MDNS_PREDEF_NETIF_AP=n +CONFIG_MDNS_PREDEF_NETIF_ETH=n +CONFIG_MDNS_ADD_CUSTOM_NETIF=y diff --git a/examples/protocols/mdns/sdkconfig.ci.socket b/examples/protocols/mdns/sdkconfig.ci.socket new file mode 100644 index 000000000..dc1884f11 --- /dev/null +++ b/examples/protocols/mdns/sdkconfig.ci.socket @@ -0,0 +1,5 @@ +CONFIG_MDNS_RESOLVE_TEST_SERVICES=y +CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +CONFIG_MDNS_NETWORKING_SOCKET=y From 4b5f24f5b8f97f95fd0df1ebccf28dece9e65b8d Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 14 Dec 2021 21:35:27 +0100 Subject: [PATCH 277/289] CI/mdns: Fix fuzzer build * Original commit: espressif/esp-idf@98e9426b660a6e825f811cccd45a0722cc801ccd --- components/mdns/test_afl_fuzz_host/sdkconfig.h | 1 + components/mdns/test_afl_fuzz_host/test.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index d17d4f5e8..fe207b001 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -284,6 +284,7 @@ #define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 #define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 #define CONFIG_MDNS_MAX_SERVICES 25 +#define CONFIG_MDNS_MAX_INTERFACES 3 #define CONFIG_MDNS_TASK_PRIORITY 1 #define CONFIG_MDNS_TASK_STACK_SIZE 4096 #define CONFIG_MDNS_TASK_AFFINITY_CPU0 1 diff --git a/components/mdns/test_afl_fuzz_host/test.c b/components/mdns/test_afl_fuzz_host/test.c index b48d904e3..568c7eee1 100644 --- a/components/mdns/test_afl_fuzz_host/test.c +++ b/components/mdns/test_afl_fuzz_host/test.c @@ -34,8 +34,10 @@ extern mdns_server_t * _mdns_server; // mdns function wrappers for mdns setup in test mode static int mdns_test_hostname_set(const char * mdns_hostname) { - _mdns_server->interfaces[MDNS_IF_STA].pcbs[MDNS_IP_PROTOCOL_V4].state = PCB_RUNNING; // mark the PCB running to exercise mdns in fully operational mode - _mdns_server->interfaces[MDNS_IF_STA].pcbs[MDNS_IP_PROTOCOL_V6].state = PCB_RUNNING; + for (int i=0; iinterfaces[i].pcbs[MDNS_IP_PROTOCOL_V4].state = PCB_RUNNING; // mark the PCB running to exercise mdns in fully operational mode + _mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V6].state = PCB_RUNNING; + } int ret = mdns_hostname_set(mdns_hostname); mdns_action_t * a = NULL; GetLastItem(&a); From e9a1c26e0c7f7a6bce1a5b051d7bc0aedd62820d Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 15 Dec 2021 15:48:59 +0100 Subject: [PATCH 278/289] CI/mdns: Reworked example test to be run repeatably * Original commit: espressif/esp-idf@dd3cd52fd6c04c6ed078247f47963fbc3f216608 --- examples/protocols/mdns/mdns_example_test.py | 43 ++++++++----------- .../protocols/mdns/sdkconfig.ci.custom_netif | 8 ---- .../mdns/sdkconfig.ci.eth_custom_netif | 19 ++++++++ ...config.ci.eth_kit => sdkconfig.ci.eth_def} | 0 .../protocols/mdns/sdkconfig.ci.eth_socket | 16 +++++++ examples/protocols/mdns/sdkconfig.ci.socket | 5 --- 6 files changed, 54 insertions(+), 37 deletions(-) delete mode 100644 examples/protocols/mdns/sdkconfig.ci.custom_netif create mode 100644 examples/protocols/mdns/sdkconfig.ci.eth_custom_netif rename examples/protocols/mdns/{sdkconfig.ci.eth_kit => sdkconfig.ci.eth_def} (100%) create mode 100644 examples/protocols/mdns/sdkconfig.ci.eth_socket delete mode 100644 examples/protocols/mdns/sdkconfig.ci.socket diff --git a/examples/protocols/mdns/mdns_example_test.py b/examples/protocols/mdns/mdns_example_test.py index 4307b9972..83763634e 100644 --- a/examples/protocols/mdns/mdns_example_test.py +++ b/examples/protocols/mdns/mdns_example_test.py @@ -13,10 +13,6 @@ import ttfw_idf from tiny_test_fw import DUT from tiny_test_fw.Utility import console_log -stop_mdns_server = Event() -esp_answered = Event() -esp_delegated_answered = Event() - def get_dns_query_for_esp(esp_host): dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') @@ -52,8 +48,7 @@ def get_dns_answer_to_mdns_lwip(tester_host, id): return dns.pack() -def mdns_server(esp_host): - global esp_answered +def mdns_server(esp_host, events): UDP_IP = '0.0.0.0' UDP_PORT = 5353 MCAST_GRP = '224.0.0.251' @@ -68,14 +63,14 @@ def mdns_server(esp_host): mreq = struct.pack('4sl', socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) last_query_timepoint = time.time() - while not stop_mdns_server.is_set(): + while not events['stop'].is_set(): try: current_time = time.time() if current_time - last_query_timepoint > QUERY_TIMEOUT: last_query_timepoint = current_time - if not esp_answered.is_set(): + if not events['esp_answered'].is_set(): sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP, UDP_PORT)) - if not esp_delegated_answered.is_set(): + if not events['esp_delegated_answered'].is_set(): sock.sendto(get_dns_query_for_esp(esp_host + '-delegated'), (MCAST_GRP, UDP_PORT)) timeout = max(0, QUERY_TIMEOUT - (current_time - last_query_timepoint)) read_socks, _, _ = select.select([sock], [], [], timeout) @@ -94,19 +89,17 @@ def mdns_server(esp_host): console_log('Received answer from {}'.format(dns.an[0].name)) if dns.an[0].name == esp_host + u'.local': console_log('Received answer to esp32-mdns query: {}'.format(dns.__repr__())) - esp_answered.set() + events['esp_answered'].set() if dns.an[0].name == esp_host + u'-delegated.local': console_log('Received answer to esp32-mdns-delegate query: {}'.format(dns.__repr__())) - esp_delegated_answered.set() + events['esp_delegated_answered'].set() except socket.timeout: break except dpkt.UnpackError: continue -@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') def test_examples_protocol_mdns(env, config): - global stop_mdns_server """ steps: | 1. obtain IP address + init mdns example @@ -114,7 +107,7 @@ def test_examples_protocol_mdns(env, config): 3. check the mdns name is accessible 4. check DUT output if mdns advertized host is resolved """ - dut1 = env.get_dut('mdns-test', 'examples/protocols/mdns', dut_class=ttfw_idf.ESP32DUT, app_config_name='eth_kit') + dut1 = env.get_dut('mdns-test', 'examples/protocols/mdns', dut_class=ttfw_idf.ESP32DUT, app_config_name=config) # check and log bin size binary_file = os.path.join(dut1.app.binary_path, 'mdns_test.bin') bin_size = os.path.getsize(binary_file) @@ -123,7 +116,9 @@ def test_examples_protocol_mdns(env, config): dut1.start_app() # 2. get the dut host name (and IP address) specific_host = dut1.expect(re.compile(r'mdns hostname set to: \[([^\]]+)\]'), timeout=30)[0] - mdns_responder = Thread(target=mdns_server, args=(str(specific_host),)) + + mdns_server_events = {'stop': Event(), 'esp_answered': Event(), 'esp_delegated_answered': Event()} + mdns_responder = Thread(target=mdns_server, args=(str(specific_host), mdns_server_events)) try: ip_address = dut1.expect(re.compile(r' eth ip: ([^,]+),'), timeout=30)[0] console_log('Connected to AP with IP: {}'.format(ip_address)) @@ -132,9 +127,9 @@ def test_examples_protocol_mdns(env, config): try: # 3. check the mdns name is accessible mdns_responder.start() - if not esp_answered.wait(timeout=30): + if not mdns_server_events['esp_answered'].wait(timeout=30): raise ValueError('Test has failed: did not receive mdns answer within timeout') - if not esp_delegated_answered.wait(timeout=30): + if not mdns_server_events['esp_delegated_answered'].wait(timeout=30): raise ValueError('Test has failed: did not receive mdns answer for delegated host within timeout') # 4. check DUT output if mdns advertized host is resolved dut1.expect(re.compile(r'mdns-test: Query A: tinytester.local resolved to: 127.0.0.1'), timeout=30) @@ -148,23 +143,23 @@ def test_examples_protocol_mdns(env, config): raise ValueError('Test has failed: Incorrectly resolved DUT hostname using dig' "Output should've contained DUT's IP address:{}".format(ip_address)) finally: - stop_mdns_server.set() + mdns_server_events['stop'].set() mdns_responder.join() -@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') +@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') def test_examples_protocol_mdns_default(env, _): - test_examples_protocol_mdns(env, None) + test_examples_protocol_mdns(env, 'eth_def') -@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') +@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') def test_examples_protocol_mdns_socket(env, _): - test_examples_protocol_mdns(env, 'socket') + test_examples_protocol_mdns(env, 'eth_socket') -@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') +@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1') def test_examples_protocol_mdns_custom_netif(env, _): - test_examples_protocol_mdns(env, 'custom_netif') + test_examples_protocol_mdns(env, 'eth_custom_netif') if __name__ == '__main__': diff --git a/examples/protocols/mdns/sdkconfig.ci.custom_netif b/examples/protocols/mdns/sdkconfig.ci.custom_netif deleted file mode 100644 index 3550c5204..000000000 --- a/examples/protocols/mdns/sdkconfig.ci.custom_netif +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_MDNS_RESOLVE_TEST_SERVICES=y -CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y -CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y -CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y -CONFIG_MDNS_PREDEF_NETIF_STA=n -CONFIG_MDNS_PREDEF_NETIF_AP=n -CONFIG_MDNS_PREDEF_NETIF_ETH=n -CONFIG_MDNS_ADD_CUSTOM_NETIF=y diff --git a/examples/protocols/mdns/sdkconfig.ci.eth_custom_netif b/examples/protocols/mdns/sdkconfig.ci.eth_custom_netif new file mode 100644 index 000000000..56499bd43 --- /dev/null +++ b/examples/protocols/mdns/sdkconfig.ci.eth_custom_netif @@ -0,0 +1,19 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_MDNS_RESOLVE_TEST_SERVICES=y +CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y +CONFIG_MDNS_PREDEF_NETIF_STA=n +CONFIG_MDNS_PREDEF_NETIF_AP=n +CONFIG_MDNS_PREDEF_NETIF_ETH=n +CONFIG_MDNS_ADD_CUSTOM_NETIF=y +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y +CONFIG_MDNS_BUTTON_GPIO=32 diff --git a/examples/protocols/mdns/sdkconfig.ci.eth_kit b/examples/protocols/mdns/sdkconfig.ci.eth_def similarity index 100% rename from examples/protocols/mdns/sdkconfig.ci.eth_kit rename to examples/protocols/mdns/sdkconfig.ci.eth_def diff --git a/examples/protocols/mdns/sdkconfig.ci.eth_socket b/examples/protocols/mdns/sdkconfig.ci.eth_socket new file mode 100644 index 000000000..5d9240526 --- /dev/null +++ b/examples/protocols/mdns/sdkconfig.ci.eth_socket @@ -0,0 +1,16 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_MDNS_RESOLVE_TEST_SERVICES=y +CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y +CONFIG_MDNS_NETWORKING_SOCKET=y +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y +CONFIG_MDNS_BUTTON_GPIO=32 diff --git a/examples/protocols/mdns/sdkconfig.ci.socket b/examples/protocols/mdns/sdkconfig.ci.socket deleted file mode 100644 index dc1884f11..000000000 --- a/examples/protocols/mdns/sdkconfig.ci.socket +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG_MDNS_RESOLVE_TEST_SERVICES=y -CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y -CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y -CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y -CONFIG_MDNS_NETWORKING_SOCKET=y From f836ae7f6565a3ea7bd963606915a2535794ffc8 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 20 Dec 2021 13:59:11 +0100 Subject: [PATCH 279/289] mdns: Add API to control custom network interfaces * Original commit: espressif/esp-idf@b02468dc98d614f931d14cd8b5e2373ca51fb18d --- components/mdns/include/mdns.h | 40 +++++++++++++++++-- components/mdns/mdns.c | 10 ++--- components/mdns/mdns_console.c | 7 +--- .../protocols/mdns/main/mdns_example_main.c | 6 +-- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 58121135a..28cd2f2b4 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -720,9 +720,43 @@ esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, esp_ip6_addr #endif -esp_err_t mdns_add_custom_netif(esp_netif_t *esp_netif); -esp_err_t mdns_post_custom_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action); -esp_err_t mdns_delete_custom_netif(esp_netif_t *esp_netif); +/** + * @brief Register custom esp_netif with mDNS functionality + * mDNS service runs by on default interfaces (STA, AP, ETH). This API enables running the service + * on any customized interface, either using standard WiFi or Ethernet driver or any kind of user + * defined driver. + * + * @param esp_netif Pointer to esp-netif interface + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running or this netif is already registered + * - ESP_ERR_NO_MEM not enough memory for this in interface in the netif list (see CONFIG_MDNS_MAX_INTERFACES) + */ +esp_err_t mdns_register_esp_netif(esp_netif_t *esp_netif); + +/** + * @brief Unregister esp-netif already registered in mDNS service + * + * @param esp_netif Pointer to esp-netif interface + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NOT_FOUND this esp-netif was not registered in mDNS service + */ +esp_err_t mdns_unregister_esp_netif(esp_netif_t *esp_netif); + +/** + * @brief Set esp_netif to a desired state, or perform a desired action, such as enable/disable this interface + * or send announcement packets to this netif + * @param esp_netif Pointer to esp-netif interface + * @param event_action Disable/Enable/Announce on this interface over IPv4/IPv6 protocol. + * Actions enumerated in mdns_event_actions_t type. + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running or this netif is not registered + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_set_esp_netif_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action); #ifdef __cplusplus } diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 519365397..aad353811 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -3824,7 +3824,7 @@ void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) */ static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) { - if (!_mdns_server || mdns_if > MDNS_MAX_INTERFACES) { + if (!_mdns_server || mdns_if >= MDNS_MAX_INTERFACES) { return; } if (action & MDNS_EVENT_ENABLE_IP4) { @@ -5028,7 +5028,7 @@ static esp_err_t _mdns_service_task_stop(void) static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action) { if (!_mdns_server || mdns_if >= MDNS_MAX_INTERFACES) { - return ESP_FAIL; + return ESP_ERR_INVALID_STATE; } mdns_action_t * action = (mdns_action_t *)calloc(1, sizeof(mdns_action_t)); @@ -5081,12 +5081,12 @@ static inline void unregister_predefined_handlers(void) * Public Methods * */ -esp_err_t mdns_post_custom_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action) +esp_err_t mdns_set_esp_netif_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action) { return mdns_post_custom_action_tcpip_if(_mdns_get_if_from_esp_netif(esp_netif), event_action); } -esp_err_t mdns_add_custom_netif(esp_netif_t *esp_netif) +esp_err_t mdns_register_esp_netif(esp_netif_t *esp_netif) { if (!_mdns_server) { return ESP_ERR_INVALID_STATE; @@ -5112,7 +5112,7 @@ esp_err_t mdns_add_custom_netif(esp_netif_t *esp_netif) return err; } -esp_err_t mdns_delete_custom_netif(esp_netif_t *esp_netif) +esp_err_t mdns_unregister_esp_netif(esp_netif_t *esp_netif) { if (!_mdns_server) { return ESP_ERR_INVALID_STATE; diff --git a/components/mdns/mdns_console.c b/components/mdns/mdns_console.c index 16379fade..f677e337c 100644 --- a/components/mdns/mdns_console.c +++ b/components/mdns/mdns_console.c @@ -11,18 +11,13 @@ static const char * ip_protocol_str[] = {"V4", "V6", "MAX"}; -static const char * if_str(esp_netif_t *netif) -{ - return esp_netif_get_ifkey(netif); -} - static void mdns_print_results(mdns_result_t * results) { mdns_result_t * r = results; mdns_ip_addr_t * a = NULL; int i = 1; while (r) { - printf("%d: Interface: %s, Type: %s\n", i++, if_str(r->esp_netif), ip_protocol_str[r->ip_protocol]); + 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); } diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index c1a9ba868..ee8c77519 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -270,9 +270,9 @@ void app_main(void) /* Demonstration of adding a custom netif to mdns service, but we're adding the default example one, * so we must disable all predefined interfaces (PREDEF_NETIF_STA, AP and ETH) first */ - ESP_ERROR_CHECK(mdns_add_custom_netif(EXAMPLE_INTERFACE)); - ESP_ERROR_CHECK(mdns_post_custom_action(EXAMPLE_INTERFACE, MDNS_EVENT_ENABLE_IP4)); - ESP_ERROR_CHECK(mdns_post_custom_action(EXAMPLE_INTERFACE, MDNS_EVENT_ANNOUNCE_IP4)); + ESP_ERROR_CHECK(mdns_register_esp_netif(EXAMPLE_INTERFACE)); + ESP_ERROR_CHECK(mdns_set_esp_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_ENABLE_IP4)); + ESP_ERROR_CHECK(mdns_set_esp_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_ANNOUNCE_IP4)); #endif initialise_button(); xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL); From 2c764b1b7afc875ec74470e9f2fd6708d59ac032 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 3 Jan 2022 16:36:08 +0100 Subject: [PATCH 280/289] mdns: Fix copyright messages, update API descrition * Impove docs and comments on custom netifs * Make predef interfaces const, minor docs fixes * Original commit: espressif/esp-idf@42ba8a8338fd5efd82498a5989fc5c105938d447 --- components/mdns/Kconfig | 15 +++--- components/mdns/include/mdns.h | 20 ++++--- components/mdns/mdns.c | 54 +++++++++++++------ components/mdns/mdns_console.c | 2 +- components/mdns/mdns_networking_socket.c | 2 +- .../protocols/mdns/main/mdns_example_main.c | 10 ++-- 6 files changed, 69 insertions(+), 34 deletions(-) diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig index 7ceefd88d..def0d850d 100644 --- a/components/mdns/Kconfig +++ b/components/mdns/Kconfig @@ -5,7 +5,7 @@ menu "mDNS" range 1 9 default 3 help - Number of network interfaces to be served by the mdns library. + Number of network interfaces to be served by the mDNS library. Lowering this number helps to reduce some static RAM usage. config MDNS_MAX_SERVICES @@ -72,7 +72,7 @@ menu "mDNS" Currently the only strict feature: Do not repeat original questions in response packets (defined in RFC6762 sec. 6). Default configuration is 0, i.e. non-strict mode, since some implementations, - such as lwIP mdns resolver (used by standard POSIX API like getaddrinfo, gethostbyname) + such as lwIP mDNS resolver (used by standard POSIX API like getaddrinfo, gethostbyname) could not correctly resolve advertised names. config MDNS_TIMER_PERIOD_MS @@ -84,10 +84,10 @@ menu "mDNS" and schedules mDNS searches. config MDNS_NETWORKING_SOCKET - bool "Use BSD sockets for mdns networking" + bool "Use BSD sockets for mDNS networking" default n help - Enables optional mdns networking implementation using BSD sockets + Enables optional mDNS networking implementation using BSD sockets in UDP multicast mode. This option creates a new thread to serve receiving packets (TODO). This option uses additional N sockets, where N is number of interfaces. @@ -104,21 +104,22 @@ menu "mDNS" bool "Use predefined interface for WiFi Station" default y help - Set up mdns for the default WiFi station. + Set up mDNS for the default WiFi station. Disable this option if you do not need mDNS on default WiFi STA. config MDNS_PREDEF_NETIF_AP bool "Use predefined interface for WiFi Access Point" default y help - Set up mdns for the default WiFi Access Point. + Set up mDNS for the default WiFi Access Point. Disable this option if you do not need mDNS on default WiFi AP. config MDNS_PREDEF_NETIF_ETH bool "Use predefined interface for Ethernet" + depends on ETH_ENABLED default y help - Set up mdns for the default Ethernet interface. + Set up mDNS for the default Ethernet interface. Disable this option if you do not need mDNS on default Ethernet. endmenu # MDNS Predefined interfaces diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 28cd2f2b4..7f81d0af8 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -722,9 +722,9 @@ esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, esp_ip6_addr /** * @brief Register custom esp_netif with mDNS functionality - * mDNS service runs by on default interfaces (STA, AP, ETH). This API enables running the service - * on any customized interface, either using standard WiFi or Ethernet driver or any kind of user - * defined driver. + * mDNS service runs by default on preconfigured interfaces (STA, AP, ETH). + * This API enables running the service on any customized interface, + * either using standard WiFi or Ethernet driver or any kind of user defined driver. * * @param esp_netif Pointer to esp-netif interface * @return @@ -732,7 +732,7 @@ esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, esp_ip6_addr * - ESP_ERR_INVALID_STATE mDNS is not running or this netif is already registered * - ESP_ERR_NO_MEM not enough memory for this in interface in the netif list (see CONFIG_MDNS_MAX_INTERFACES) */ -esp_err_t mdns_register_esp_netif(esp_netif_t *esp_netif); +esp_err_t mdns_register_netif(esp_netif_t *esp_netif); /** * @brief Unregister esp-netif already registered in mDNS service @@ -743,11 +743,19 @@ esp_err_t mdns_register_esp_netif(esp_netif_t *esp_netif); * - ESP_ERR_INVALID_STATE mDNS is not running * - ESP_ERR_NOT_FOUND this esp-netif was not registered in mDNS service */ -esp_err_t mdns_unregister_esp_netif(esp_netif_t *esp_netif); +esp_err_t mdns_unregister_netif(esp_netif_t *esp_netif); /** * @brief Set esp_netif to a desired state, or perform a desired action, such as enable/disable this interface * or send announcement packets to this netif + * + * * This function is used to enable (probe, resolve conflicts and announce), announce, or disable (send bye) mDNS + * services on the specified network interface. + * * This function must be called if users registers a specific interface using mdns_register_netif() + * to enable mDNS services on that interface. + * * This function could be used in IP/connection event handlers to automatically enable/announce mDNS services + * when network properties change and/or disable them on disconnection. + * * @param esp_netif Pointer to esp-netif interface * @param event_action Disable/Enable/Announce on this interface over IPv4/IPv6 protocol. * Actions enumerated in mdns_event_actions_t type. @@ -756,7 +764,7 @@ esp_err_t mdns_unregister_esp_netif(esp_netif_t *esp_netif); * - ESP_ERR_INVALID_STATE mDNS is not running or this netif is not registered * - ESP_ERR_NO_MEM memory error */ -esp_err_t mdns_set_esp_netif_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action); +esp_err_t mdns_netif_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action); #ifdef __cplusplus } diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index aad353811..15b32e338 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -68,9 +68,9 @@ typedef enum { typedef struct mdns_interfaces mdns_interfaces_t; struct mdns_interfaces { - bool predefined; + const bool predefined; esp_netif_t * netif; - mdns_predef_if_t predef_if; + const mdns_predef_if_t predef_if; mdns_if_t duplicate; }; @@ -91,10 +91,13 @@ static mdns_interfaces_t s_esp_netifs[MDNS_MAX_INTERFACES] = { }; -/* - * @brief Convert mdns if to esp-netif handle +/** + * @brief Convert Predefined interface to the netif id from the internal netif list + * @param predef_if Predefined interface enum + * @return Ordinal number of internal list of mdns network interface. + * Returns MDNS_MAX_INTERFACES if the predefined interface wasn't found in the list */ -static mdns_if_t mdns_if_from_predef_if(mdns_predef_if_t predef_if) +static mdns_if_t mdns_if_from_preset_if(mdns_predef_if_t predef_if) { for (int i=0; i "STA", "AP", "ETH" + * - if no entry in the list (NULL) -> check if the system added this netif + * - point to a custom netif -> just return the entry in the list + * - users is responsible for the lifetime of this netif (to be valid between mdns-init -> deinit) + * + * @param tcpip_if Ordinal number of the interface + * @return Pointer ot the esp_netif object if the interface is available, NULL otherwise + */ esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) { if (tcpip_if < MDNS_MAX_INTERFACES) { if (s_esp_netifs[tcpip_if].netif == NULL && s_esp_netifs[tcpip_if].predefined) { - // if a predefined interface face and used local copy is NULL, try to search for the default interface key + // If the local copy is NULL and this netif is predefined -> we can find it in the global netif list s_esp_netifs[tcpip_if].netif = esp_netif_from_preset_if(s_esp_netifs[tcpip_if].predef_if); + // failing to find it means that the netif is *not* available -> return NULL } return s_esp_netifs[tcpip_if].netif; } @@ -146,11 +167,12 @@ static inline void _mdns_clean_netif_ptr(mdns_if_t tcpip_if) { /* * @brief Convert esp-netif handle to mdns if */ -static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *interface) +static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *esp_netif) { for (int i=0; i Date: Tue, 8 Feb 2022 17:08:04 +0100 Subject: [PATCH 281/289] esp_netif: Remove tcpip_adapter compatibility layer * Original commit: espressif/esp-idf@795b7ed993784e3134195e12b0978504d83dfd56 --- components/mdns/test_afl_fuzz_host/Makefile | 1 - .../mdns/test_afl_fuzz_host/esp32_mock.h | 26 ------------------- .../mdns/test_afl_fuzz_host/sdkconfig.h | 1 - 3 files changed, 28 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index b700bf4f5..af58a3c05 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -33,7 +33,6 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi -I$(COMPONENTS_DIR)/soc/include \ -I$(COMPONENTS_DIR)/soc/esp32/include \ -I$(COMPONENTS_DIR)/soc/src/esp32/include \ - -I$(COMPONENTS_DIR)/tcpip_adapter/include \ -I$(COMPONENTS_DIR)/xtensa/include \ -I$(COMPONENTS_DIR)/xtensa/esp32/include \ -I$(COMPILER_ICLUDE_DIR)/include diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h index 8afe01fba..e76a17ab6 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_mock.h +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.h @@ -11,7 +11,6 @@ #define INC_FREERTOS_H #define QUEUE_H #define SEMAPHORE_H -#define _TCPIP_ADAPTER_H_ #define _ESP_TASK_H_ #ifdef USE_BSD_STRING @@ -92,14 +91,6 @@ extern const char * WIFI_EVENT; extern const char * IP_EVENT; extern const char * ETH_EVENT; -/* status of DHCP client or DHCP server */ -typedef enum { - TCPIP_ADAPTER_DHCP_INIT = 0, /**< DHCP client/server in initial state */ - TCPIP_ADAPTER_DHCP_STARTED, /**< DHCP client/server already been started */ - TCPIP_ADAPTER_DHCP_STOPPED, /**< DHCP client/server already been stopped */ - TCPIP_ADAPTER_DHCP_STATUS_MAX -} tcpip_adapter_dhcp_status_t; - struct udp_pcb { uint8_t dummy; }; @@ -114,23 +105,6 @@ struct ip6_addr { }; typedef struct ip6_addr ip6_addr_t; -typedef struct { - ip4_addr_t ip; - ip4_addr_t netmask; - ip4_addr_t gw; -} tcpip_adapter_ip_info_t; - -typedef enum { - TCPIP_ADAPTER_IF_STA = 0, /**< ESP32 station interface */ - TCPIP_ADAPTER_IF_AP, /**< ESP32 soft-AP interface */ - TCPIP_ADAPTER_IF_ETH, /**< ESP32 ethernet interface */ - TCPIP_ADAPTER_IF_MAX -} tcpip_adapter_if_t; - -typedef struct { - ip6_addr_t ip; -} tcpip_adapter_ip6_info_t; - typedef void* system_event_t; struct pbuf { diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index fe207b001..71bb12823 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -123,7 +123,6 @@ #define CONFIG_HTTPD_PURGE_BUF_LEN 32 #define CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL 120 #define CONFIG_ESP_NETIF_TCPIP_LWIP 1 -#define CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER 1 #define CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT 1 #define CONFIG_ESP_TIMER_TASK_STACK_SIZE 3584 #define CONFIG_ESP_TIMER_IMPL_TG0_LAC 1 From b720d02fca7b16db0b94036142209c108e572b51 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 10 Mar 2022 10:36:38 +0100 Subject: [PATCH 282/289] examples: Fix implicit includes after legacy code removal * Original commit: espressif/esp-idf@c941e29cf62859cbea47270f8c150f6b82b222b4 --- tools/test_apps/protocols/mdns/main/mdns_test.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/test_apps/protocols/mdns/main/mdns_test.c b/tools/test_apps/protocols/mdns/main/mdns_test.c index b47e67cc1..d82229f1d 100644 --- a/tools/test_apps/protocols/mdns/main/mdns_test.c +++ b/tools/test_apps/protocols/mdns/main/mdns_test.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "mdns.h" #include "esp_log.h" #include "esp_netif.h" From eb536a74a03a31a545be510f397fdc7eabdd7d5f Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Thu, 10 Mar 2022 14:26:37 +0530 Subject: [PATCH 283/289] kconfig: Changed default values of bool configs - Some bool configs were using default values true and false, instead of y and n. * Original commit: espressif/esp-idf@25c5c214f38ca690b03533e12fb5a4d774c7eae0 --- components/mdns/host_test/components/esp_netif_linux/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/host_test/components/esp_netif_linux/Kconfig b/components/mdns/host_test/components/esp_netif_linux/Kconfig index c903f7ca5..f91ec201b 100644 --- a/components/mdns/host_test/components/esp_netif_linux/Kconfig +++ b/components/mdns/host_test/components/esp_netif_linux/Kconfig @@ -2,7 +2,7 @@ menu "LWIP-MOCK-CONFIG" config LWIP_IPV6 bool "Enable IPv6" - default true + default y help Enable/disable IPv6 From 87c269911de57d3789847f7dec116edbd8825490 Mon Sep 17 00:00:00 2001 From: Anton Maklakov Date: Fri, 4 Mar 2022 16:51:43 +0700 Subject: [PATCH 284/289] cmake: fix issue with passing cxx_std option for GCC 11, a common workaround * Original commit: espressif/esp-idf@ea0d2123c806bd0ad77bc49843ee905cf9be65ff --- .../host_test/components/esp_timer_linux/CMakeLists.txt | 6 +++++- .../host_test/components/freertos_linux/CMakeLists.txt | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt b/components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt index 0c598a2e6..a2bec32aa 100644 --- a/components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt +++ b/components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt @@ -2,4 +2,8 @@ idf_component_register(SRCS esp_timer_linux.c timer_task.cpp INCLUDE_DIRS include REQUIRES esp_system_protocols_linux freertos_linux) -target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17) +set_target_properties(${COMPONENT_LIB} PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS ON +) diff --git a/components/mdns/host_test/components/freertos_linux/CMakeLists.txt b/components/mdns/host_test/components/freertos_linux/CMakeLists.txt index 7a84af21a..cd1686154 100644 --- a/components/mdns/host_test/components/freertos_linux/CMakeLists.txt +++ b/components/mdns/host_test/components/freertos_linux/CMakeLists.txt @@ -4,6 +4,10 @@ idf_component_register(SRCS freertos_linux.c queue_unique_ptr.cpp set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) -target_link_libraries(${COMPONENT_LIB} PRIVATE Threads::Threads) +target_link_libraries(${COMPONENT_LIB} PRIVATE Threads::Threads) -target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17) +set_target_properties(${COMPONENT_LIB} PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS ON +) From 00e76759130897bd899cd84323f439b1f911bc0e Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Thu, 31 Mar 2022 14:52:27 +0200 Subject: [PATCH 285/289] examples: added ESP-NETIF L2 TAP example * Original commit: espressif/esp-idf@fcdb0306d04f521531534e2f577e4fead27ec755 --- .../common_components/protocol_examples_common/connect.c | 6 ++++++ .../include/protocol_examples_common.h | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index c54deae67..85878d78b 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -479,6 +479,7 @@ static void eth_stop(void) ESP_ERROR_CHECK(esp_eth_stop(s_eth_handle)); ESP_ERROR_CHECK(esp_eth_del_netif_glue(s_eth_glue)); ESP_ERROR_CHECK(esp_eth_driver_uninstall(s_eth_handle)); + s_eth_handle = NULL; ESP_ERROR_CHECK(s_phy->del(s_phy)); ESP_ERROR_CHECK(s_mac->del(s_mac)); @@ -486,6 +487,11 @@ static void eth_stop(void) s_example_esp_netif = NULL; } +esp_eth_handle_t get_example_eth_handle(void) +{ + return s_eth_handle; +} + #endif // CONFIG_EXAMPLE_CONNECT_ETHERNET esp_netif_t *get_example_netif(void) diff --git a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h index 8c0a0a30e..7afc78a74 100644 --- a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h +++ b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h @@ -78,6 +78,15 @@ esp_netif_t *get_example_netif(void); */ esp_netif_t *get_example_netif_from_desc(const char *desc); +#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET +/** + * @brief Get the example Ethernet driver handle + * + * @return esp_eth_handle_t + */ +esp_eth_handle_t get_example_eth_handle(void); +#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET + #ifdef __cplusplus } #endif From 4a52cf23f5132b3940cdcde1d934a064527e7f97 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Wed, 2 Mar 2022 15:49:31 +0800 Subject: [PATCH 286/289] soc: moved kconfig options out of the target component. Moved the following kconfig options out of the target component: * CONFIG_ESP*_DEFAULT_CPU_FREQ* -> esp_system * ESP*_REV_MIN -> esp_hw_support * ESP*_TIME_SYSCALL -> newlib * ESP*_RTC_* -> esp_hw_support Where applicable these target specific konfig names were merged into a single common config, e.g; CONFIG_ESP*_DEFAULT_CPU_FREQ -> CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * Original commit: espressif/esp-idf@d2872095f93ed82fb91c776081bc1d032493d93e --- components/mdns/test_afl_fuzz_host/sdkconfig.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index 71bb12823..bcb1b9d13 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -60,20 +60,20 @@ #define CONFIG_ESP32_REV_MIN_0 1 #define CONFIG_ESP32_REV_MIN 0 #define CONFIG_ESP32_DPORT_WORKAROUND 1 -#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1 -#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 1 +#define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 160 #define CONFIG_ESP32_TRACEMEM_RESERVE_DRAM 0x0 #define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR 1 #define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES 4 -#define CONFIG_ESP32_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_ULP_COPROC_RESERVE_MEM 0 #define CONFIG_ESP_DEBUG_OCDAWARE 1 #define CONFIG_ESP_BROWNOUT_DET 1 #define CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0 1 #define CONFIG_ESP_BROWNOUT_DET_LVL 0 #define CONFIG_ESP32_REDUCE_PHY_TX_POWER 1 -#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_HRT 1 -#define CONFIG_ESP32_RTC_CLK_SRC_INT_RC 1 -#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT 1 +#define CONFIG_RTC_CLK_SRC_INT_RC 1 +#define CONFIG_RTC_CLK_CAL_CYCLES 1024 #define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 #define CONFIG_ESP32_XTAL_FREQ_40 1 #define CONFIG_ESP32_XTAL_FREQ 40 @@ -357,7 +357,6 @@ #define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT CONFIG_PTHREAD_TASK_NAME_DEFAULT #define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT CONFIG_PTHREAD_TASK_PRIO_DEFAULT #define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT -#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC CONFIG_ESP32_RTC_CLK_SRC_INT_RC #define CONFIG_ESP_GRATUITOUS_ARP CONFIG_LWIP_ESP_GRATUITOUS_ARP #define CONFIG_FLASHMODE_DIO CONFIG_ESPTOOLPY_FLASHMODE_DIO #define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR From 78001ec8710a198e6e2ed7a302d7a9cdfd42970b Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Wed, 20 Apr 2022 11:02:26 +0200 Subject: [PATCH 287/289] Examples: common source for GPIO range in Kconfigs defined * Original commit: espressif/esp-idf@1a20b10fd345c90a1731fb0761731791ef309827 --- .../Kconfig.projbuild | 27 +++++++------------ .../protocols/mdns/main/Kconfig.projbuild | 9 ++----- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/examples/common_components/protocol_examples_common/Kconfig.projbuild index 867863e48..86ee4f140 100644 --- a/examples/common_components/protocol_examples_common/Kconfig.projbuild +++ b/examples/common_components/protocol_examples_common/Kconfig.projbuild @@ -1,15 +1,6 @@ menu "Example Connection Configuration" - config EXAMPLE_GPIO_RANGE_MIN - int - default 0 - - config EXAMPLE_GPIO_RANGE_MAX - int - default 33 if IDF_TARGET_ESP32 - default 46 if IDF_TARGET_ESP32S2 - default 19 if IDF_TARGET_ESP32C3 - default 48 if IDF_TARGET_ESP32S3 + orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps" config EXAMPLE_CONNECT_WIFI bool "connect using WiFi interface" @@ -204,14 +195,14 @@ menu "Example Connection Configuration" config EXAMPLE_ETH_MDC_GPIO int "SMI MDC GPIO number" - range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX default 23 help Set the GPIO number used by SMI MDC. config EXAMPLE_ETH_MDIO_GPIO int "SMI MDIO GPIO number" - range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX default 18 help Set the GPIO number used by SMI MDIO. @@ -227,28 +218,28 @@ menu "Example Connection Configuration" config EXAMPLE_ETH_SPI_SCLK_GPIO int "SPI SCLK GPIO number" - range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX default 14 help Set the GPIO number used by SPI SCLK. config EXAMPLE_ETH_SPI_MOSI_GPIO int "SPI MOSI GPIO number" - range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX default 13 help Set the GPIO number used by SPI MOSI. config EXAMPLE_ETH_SPI_MISO_GPIO int "SPI MISO GPIO number" - range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX default 12 help Set the GPIO number used by SPI MISO. config EXAMPLE_ETH_SPI_CS_GPIO int "SPI CS GPIO number" - range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX default 15 help Set the GPIO number used by SPI CS. @@ -262,7 +253,7 @@ menu "Example Connection Configuration" config EXAMPLE_ETH_SPI_INT_GPIO int "Interrupt GPIO number" - range EXAMPLE_GPIO_RANGE_MIN EXAMPLE_GPIO_RANGE_MAX + range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX default 4 help Set the GPIO number used by the SPI Ethernet module interrupt line. @@ -270,7 +261,7 @@ menu "Example Connection Configuration" config EXAMPLE_ETH_PHY_RST_GPIO int "PHY Reset GPIO number" - range -1 EXAMPLE_GPIO_RANGE_MAX + range -1 ENV_GPIO_OUT_RANGE_MAX default 5 help Set the GPIO number used to reset PHY chip. diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index b66e6f867..18e1cc209 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -1,11 +1,6 @@ menu "Example Configuration" - config MDNS_GPIO_RANGE_MAX - int - default 33 if IDF_TARGET_ESP32 - default 46 if IDF_TARGET_ESP32S2 - default 19 if IDF_TARGET_ESP32C3 - default 48 if IDF_TARGET_ESP32S3 + orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps" config MDNS_HOSTNAME string "mDNS Hostname" @@ -43,7 +38,7 @@ menu "Example Configuration" config MDNS_BUTTON_GPIO int "Button GPIO to trigger querries" - range 0 MDNS_GPIO_RANGE_MAX + range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX default 0 help Set the GPIO number used as mDNS test button From 8863ed944d61e1bc2bc862cd51aaefb2d2b2340c Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Thu, 28 Apr 2022 14:34:20 +0800 Subject: [PATCH 288/289] docs: update redirected links * Original commit: espressif/esp-idf@030cb77597eccf2a0d5f5bf6c9d5c58bf4110bd7 --- docs/en/api-reference/protocols/mdns.rst | 2 +- docs/zh_CN/api-reference/protocols/mdns.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/api-reference/protocols/mdns.rst b/docs/en/api-reference/protocols/mdns.rst index 1370b3015..00c8b37de 100644 --- a/docs/en/api-reference/protocols/mdns.rst +++ b/docs/en/api-reference/protocols/mdns.rst @@ -7,7 +7,7 @@ Overview mDNS is a multicast UDP service that is used to provide local network service and host discovery. -mDNS is installed by default on most operating systems or is available as separate package. On ``Mac OS`` it is installed by default and is called ``Bonjour``. Apple releases an installer for ``Windows`` that can be found `on Apple's support page `_. On ``Linux``, mDNS is provided by `avahi `_ and is usually installed by default. +mDNS is installed by default on most operating systems or is available as separate package. On ``Mac OS`` it is installed by default and is called ``Bonjour``. Apple releases an installer for ``Windows`` that can be found `on Apple's support page `_. On ``Linux``, mDNS is provided by `avahi `_ and is usually installed by default. mDNS Properties ^^^^^^^^^^^^^^^ diff --git a/docs/zh_CN/api-reference/protocols/mdns.rst b/docs/zh_CN/api-reference/protocols/mdns.rst index 29bdbf345..08b3b373d 100644 --- a/docs/zh_CN/api-reference/protocols/mdns.rst +++ b/docs/zh_CN/api-reference/protocols/mdns.rst @@ -7,7 +7,7 @@ mDNS 服务 mDNS 是一种组播 UDP 服务,用来提供本地网络服务和主机发现。 -绝大多数的操作系统默认都会安装 mDNS 服务,或者提供单独的安装包。``Mac OS`` 默认会安装名为 ``Bonjour`` 的服务(该服务基于 mDNS),此外 Apple 还发布了适用于 Windows 系统的安装程序,可以在 `官方支持 `_ 找到。在 ``Linux`` 上,mDNS 服务由 `avahi `_ 提供,通常也会被默认安装。 +绝大多数的操作系统默认都会安装 mDNS 服务,或者提供单独的安装包。``Mac OS`` 默认会安装名为 ``Bonjour`` 的服务(该服务基于 mDNS),此外 Apple 还发布了适用于 Windows 系统的安装程序,可以在 `官方支持 `_ 找到。在 ``Linux`` 上,mDNS 服务由 `avahi `_ 提供,通常也会被默认安装。 mDNS 属性 ^^^^^^^^^ From b6b20ad399b1948eca270ef2c9c19ad7768eb2a8 Mon Sep 17 00:00:00 2001 From: suren-gabrielyan-espressif Date: Fri, 27 May 2022 17:47:00 +0400 Subject: [PATCH 289/289] mDNS: Initial version based on IDF 5.0 --- .../build_and_run_example_test_mdns.yml | 35 ++++++++ .github/workflows/publish-docs-component.yml | 19 ++++- .github/workflows/test_afl_fuzzer.yml | 30 +++++++ README.md | 5 ++ .../protocol_examples_common/CMakeLists.txt | 0 .../Kconfig.projbuild | 0 .../addr_from_stdin.c | 0 .../protocol_examples_common/connect.c | 0 .../include/addr_from_stdin.h | 0 .../include/protocol_examples_common.h | 0 .../protocol_examples_common/stdin_out.c | 0 components/mdns/README.md | 11 +++ components/mdns/docs/Doxyfile | 75 ++++++++++++++++++ components/mdns/docs/conf_common.py | 21 +++++ components/mdns/docs/en/conf.py | 24 ++++++ .../mdns/docs/en/index.rst | 20 ++++- components/mdns/docs/generate_docs | 28 +++++++ components/mdns/docs/zh_CN/conf.py | 27 +++++++ .../mdns/docs/zh_CN/index.rst | 4 +- .../mdns/examples}/CMakeLists.txt | 4 +- .../mdns/examples}/README.md | 4 +- .../mdns/examples}/main/CMakeLists.txt | 0 .../mdns/examples}/main/Kconfig.projbuild | 0 .../mdns/examples}/main/mdns_example_main.c | 0 .../mdns/examples}/mdns_example_test.py | 0 .../examples}/sdkconfig.ci.eth_custom_netif | 0 .../mdns/examples}/sdkconfig.ci.eth_def | 0 .../mdns/examples}/sdkconfig.ci.eth_socket | 0 .../mdns/{ => tests}/host_test/CMakeLists.txt | 0 .../mdns/{ => tests}/host_test/README.md | 0 .../components/esp_event_mock/CMakeLists.txt | 0 .../esp_event_mock/esp_event_mock.c | 0 .../esp_event_mock/include/esp_event.h | 0 .../esp_event_mock/include/esp_event_base.h | 0 .../components/esp_netif_linux/CMakeLists.txt | 0 .../components/esp_netif_linux/Kconfig | 0 .../esp_netif_linux/esp_netif_linux.c | 0 .../esp_netif_linux/include/esp_wifi_types.h | 0 .../esp_system_protocols_linux/CMakeLists.txt | 0 .../esp_system_protocols_linux/esp_log_impl.c | 0 .../include/bsd_strings.h | 0 .../include/machine/endian.h | 0 .../esp_system_protocols_linux/strlcat.c | 0 .../components/esp_timer_linux/CMakeLists.txt | 0 .../esp_timer_linux/esp_timer_linux.c | 0 .../esp_timer_linux/include/esp_timer.h | 0 .../components/esp_timer_linux/timer_task.cpp | 0 .../components/esp_timer_linux/timer_task.hpp | 0 .../components/freertos_linux/CMakeLists.txt | 0 .../components/freertos_linux/Kconfig | 0 .../freertos_linux/freertos_linux.c | 0 .../freertos_linux/include/esp_task.h | 0 .../include/freertos/FreeRTOS.h | 0 .../freertos_linux/include/freertos/task.h | 0 .../freertos_linux/queue_unique_ptr.cpp | 0 .../freertos_linux/queue_unique_ptr.hpp | 0 .../{ => tests}/host_test/main/CMakeLists.txt | 0 .../mdns/{ => tests}/host_test/main/main.c | 0 .../test_afl_fuzz_host/CMakeLists.txt | 0 .../{ => tests}/test_afl_fuzz_host/Makefile | 6 +- .../{ => tests}/test_afl_fuzz_host/README.md | 0 .../test_afl_fuzz_host/esp32_mock.c | 0 .../test_afl_fuzz_host/esp32_mock.h | 0 .../{ => tests}/test_afl_fuzz_host/esp_attr.h | 0 .../test_afl_fuzz_host/esp_netif_mock.c | 0 .../test_afl_fuzz_host/in/file2.bin | Bin .../test_afl_fuzz_host/in/minif_4a_txt.bin | Bin .../test_afl_fuzz_host/in/minif_aaaa.bin | Bin .../test_afl_fuzz_host/in/minif_any.bin | Bin .../test_afl_fuzz_host/in/minif_disc.bin | Bin .../test_afl_fuzz_host/in/minif_ptr.bin | Bin .../test_afl_fuzz_host/in/minif_query.bin | Bin .../test_afl_fuzz_host/in/minif_query2.bin | Bin .../test_afl_fuzz_host/in/sub_fritz_m.bin | Bin .../test_afl_fuzz_host/in/telnet_ptr.bin | Bin .../test_afl_fuzz_host/in/test-14.bin | Bin .../test_afl_fuzz_host/in/test-15.bin | Bin .../test_afl_fuzz_host/in/test-16.bin | Bin .../test_afl_fuzz_host/in/test-28.bin | Bin .../test_afl_fuzz_host/in/test-29.bin | Bin .../test_afl_fuzz_host/in/test-31.bin | Bin .../test_afl_fuzz_host/in/test-53.bin | Bin .../test_afl_fuzz_host/in/test-56.bin | Bin .../test_afl_fuzz_host/in/test-63.bin | Bin .../test_afl_fuzz_host/in/test-83.bin | Bin .../test_afl_fuzz_host/in/test-88.bin | Bin .../test_afl_fuzz_host/in/test-89.bin | Bin .../test_afl_fuzz_host/in/test-95.bin | Bin .../test_afl_fuzz_host/in/test-96.bin | Bin .../test_afl_fuzz_host/input_packets.txt | 0 .../{ => tests}/test_afl_fuzz_host/mdns_di.h | 0 .../test_afl_fuzz_host/mdns_mock.h | 0 .../test_afl_fuzz_host/sdkconfig.h | 0 .../{ => tests}/test_afl_fuzz_host/test.c | 0 .../mdns/tests/test_apps}/CMakeLists.txt | 2 +- .../mdns/tests/test_apps}/README.md | 3 +- .../mdns/tests/test_apps}/app_test.py | 0 .../mdns/tests/test_apps}/main/CMakeLists.txt | 0 .../tests/test_apps}/main/Kconfig.projbuild | 0 .../mdns/tests/test_apps}/main/main.c | 0 .../mdns/tests/test_apps}/main/mdns_test.c | 0 .../mdns/tests/test_apps}/sdkconfig.defaults | 0 .../{test => tests/unit_test}/CMakeLists.txt | 0 .../{test => tests/unit_test}/test_mdns.c | 0 docs/docs_versions.js | 12 +++ 105 files changed, 312 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/build_and_run_example_test_mdns.yml create mode 100644 .github/workflows/test_afl_fuzzer.yml rename {examples/common_components => common_components}/protocol_examples_common/CMakeLists.txt (100%) rename {examples/common_components => common_components}/protocol_examples_common/Kconfig.projbuild (100%) rename {examples/common_components => common_components}/protocol_examples_common/addr_from_stdin.c (100%) rename {examples/common_components => common_components}/protocol_examples_common/connect.c (100%) rename {examples/common_components => common_components}/protocol_examples_common/include/addr_from_stdin.h (100%) rename {examples/common_components => common_components}/protocol_examples_common/include/protocol_examples_common.h (100%) rename {examples/common_components => common_components}/protocol_examples_common/stdin_out.c (100%) create mode 100644 components/mdns/README.md create mode 100755 components/mdns/docs/Doxyfile create mode 100644 components/mdns/docs/conf_common.py create mode 100644 components/mdns/docs/en/conf.py rename docs/en/api-reference/protocols/mdns.rst => components/mdns/docs/en/index.rst (87%) create mode 100755 components/mdns/docs/generate_docs create mode 100644 components/mdns/docs/zh_CN/conf.py rename docs/zh_CN/api-reference/protocols/mdns.rst => components/mdns/docs/zh_CN/index.rst (96%) rename {examples/protocols/mdns => components/mdns/examples}/CMakeLists.txt (72%) rename {examples/protocols/mdns => components/mdns/examples}/README.md (95%) rename {examples/protocols/mdns => components/mdns/examples}/main/CMakeLists.txt (100%) rename {examples/protocols/mdns => components/mdns/examples}/main/Kconfig.projbuild (100%) rename {examples/protocols/mdns => components/mdns/examples}/main/mdns_example_main.c (100%) rename {examples/protocols/mdns => components/mdns/examples}/mdns_example_test.py (100%) rename {examples/protocols/mdns => components/mdns/examples}/sdkconfig.ci.eth_custom_netif (100%) rename {examples/protocols/mdns => components/mdns/examples}/sdkconfig.ci.eth_def (100%) rename {examples/protocols/mdns => components/mdns/examples}/sdkconfig.ci.eth_socket (100%) rename components/mdns/{ => tests}/host_test/CMakeLists.txt (100%) rename components/mdns/{ => tests}/host_test/README.md (100%) rename components/mdns/{ => tests}/host_test/components/esp_event_mock/CMakeLists.txt (100%) rename components/mdns/{ => tests}/host_test/components/esp_event_mock/esp_event_mock.c (100%) rename components/mdns/{ => tests}/host_test/components/esp_event_mock/include/esp_event.h (100%) rename components/mdns/{ => tests}/host_test/components/esp_event_mock/include/esp_event_base.h (100%) rename components/mdns/{ => tests}/host_test/components/esp_netif_linux/CMakeLists.txt (100%) rename components/mdns/{ => tests}/host_test/components/esp_netif_linux/Kconfig (100%) rename components/mdns/{ => tests}/host_test/components/esp_netif_linux/esp_netif_linux.c (100%) rename components/mdns/{ => tests}/host_test/components/esp_netif_linux/include/esp_wifi_types.h (100%) rename components/mdns/{ => tests}/host_test/components/esp_system_protocols_linux/CMakeLists.txt (100%) rename components/mdns/{ => tests}/host_test/components/esp_system_protocols_linux/esp_log_impl.c (100%) rename components/mdns/{ => tests}/host_test/components/esp_system_protocols_linux/include/bsd_strings.h (100%) rename components/mdns/{ => tests}/host_test/components/esp_system_protocols_linux/include/machine/endian.h (100%) rename components/mdns/{ => tests}/host_test/components/esp_system_protocols_linux/strlcat.c (100%) rename components/mdns/{ => tests}/host_test/components/esp_timer_linux/CMakeLists.txt (100%) rename components/mdns/{ => tests}/host_test/components/esp_timer_linux/esp_timer_linux.c (100%) rename components/mdns/{ => tests}/host_test/components/esp_timer_linux/include/esp_timer.h (100%) rename components/mdns/{ => tests}/host_test/components/esp_timer_linux/timer_task.cpp (100%) rename components/mdns/{ => tests}/host_test/components/esp_timer_linux/timer_task.hpp (100%) rename components/mdns/{ => tests}/host_test/components/freertos_linux/CMakeLists.txt (100%) rename components/mdns/{ => tests}/host_test/components/freertos_linux/Kconfig (100%) rename components/mdns/{ => tests}/host_test/components/freertos_linux/freertos_linux.c (100%) rename components/mdns/{ => tests}/host_test/components/freertos_linux/include/esp_task.h (100%) rename components/mdns/{ => tests}/host_test/components/freertos_linux/include/freertos/FreeRTOS.h (100%) rename components/mdns/{ => tests}/host_test/components/freertos_linux/include/freertos/task.h (100%) rename components/mdns/{ => tests}/host_test/components/freertos_linux/queue_unique_ptr.cpp (100%) rename components/mdns/{ => tests}/host_test/components/freertos_linux/queue_unique_ptr.hpp (100%) rename components/mdns/{ => tests}/host_test/main/CMakeLists.txt (100%) rename components/mdns/{ => tests}/host_test/main/main.c (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/CMakeLists.txt (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/Makefile (95%) rename components/mdns/{ => tests}/test_afl_fuzz_host/README.md (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/esp32_mock.c (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/esp32_mock.h (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/esp_attr.h (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/esp_netif_mock.c (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/file2.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/minif_4a_txt.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/minif_aaaa.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/minif_any.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/minif_disc.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/minif_ptr.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/minif_query.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/minif_query2.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/sub_fritz_m.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/telnet_ptr.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-14.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-15.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-16.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-28.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-29.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-31.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-53.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-56.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-63.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-83.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-88.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-89.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-95.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/in/test-96.bin (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/input_packets.txt (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/mdns_di.h (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/mdns_mock.h (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/sdkconfig.h (100%) rename components/mdns/{ => tests}/test_afl_fuzz_host/test.c (100%) rename {tools/test_apps/protocols/mdns => components/mdns/tests/test_apps}/CMakeLists.txt (79%) rename {tools/test_apps/protocols/mdns => components/mdns/tests/test_apps}/README.md (95%) rename {tools/test_apps/protocols/mdns => components/mdns/tests/test_apps}/app_test.py (100%) rename {tools/test_apps/protocols/mdns => components/mdns/tests/test_apps}/main/CMakeLists.txt (100%) rename {tools/test_apps/protocols/mdns => components/mdns/tests/test_apps}/main/Kconfig.projbuild (100%) rename {tools/test_apps/protocols/mdns => components/mdns/tests/test_apps}/main/main.c (100%) rename {tools/test_apps/protocols/mdns => components/mdns/tests/test_apps}/main/mdns_test.c (100%) rename {tools/test_apps/protocols/mdns => components/mdns/tests/test_apps}/sdkconfig.defaults (100%) rename components/mdns/{test => tests/unit_test}/CMakeLists.txt (100%) rename components/mdns/{test => tests/unit_test}/test_mdns.c (100%) create mode 100644 docs/docs_versions.js diff --git a/.github/workflows/build_and_run_example_test_mdns.yml b/.github/workflows/build_and_run_example_test_mdns.yml new file mode 100644 index 000000000..de4aac90e --- /dev/null +++ b/.github/workflows/build_and_run_example_test_mdns.yml @@ -0,0 +1,35 @@ +name: Build mDNS + +on: [push, pull_request] + +jobs: + build: + strategy: + matrix: + idf_ver: ["latest"] + idf_target: ["esp32", "esp32s2", "esp32c3"] + + runs-on: ubuntu-20.04 + container: espressif/idf:${{ matrix.idf_ver }} + steps: + - name: Checkout esp-protocols + uses: actions/checkout@master + with: + path: esp-protocols + - name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }} + env: + IDF_TARGET: ${{ matrix.idf_target }} + shell: bash + run: | + . ${IDF_PATH}/export.sh + cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/examples/ + cat sdkconfig.ci.eth_def >> sdkconfig.defaults + idf.py build + rm sdkconfig.defaults + cat sdkconfig.ci.eth_custom_netif >> sdkconfig.defaults + idf.py build + rm sdkconfig.defaults + cat sdkconfig.ci.eth_socket >> sdkconfig.defaults + idf.py build + cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/test_apps/ + idf.py build diff --git a/.github/workflows/publish-docs-component.yml b/.github/workflows/publish-docs-component.yml index 08b330994..fbc674a2d 100644 --- a/.github/workflows/publish-docs-component.yml +++ b/.github/workflows/publish-docs-component.yml @@ -21,25 +21,36 @@ jobs: run: | sudo apt-get update sudo apt-get -y install doxygen clang python3-pip - python -m pip install breathe recommonmark esp-docs==0.2.1 + python -m pip install breathe recommonmark esp-docs cd $GITHUB_WORKSPACE/components/esp_modem/docs ./generate_docs mkdir -p $GITHUB_WORKSPACE/docs/esp_modem cp -r html/. $GITHUB_WORKSPACE/docs/esp_modem + cd $GITHUB_WORKSPACE/components/esp_websocket_client/docs ./generate_docs mkdir -p $GITHUB_WORKSPACE/docs/esp_websocket_client cp -r html/. $GITHUB_WORKSPACE/docs/esp_websocket_client + + cd $GITHUB_WORKSPACE/components/mdns/docs + ./generate_docs + mkdir -p $GITHUB_WORKSPACE/docs/mdns/en + mkdir -p $GITHUB_WORKSPACE/docs/mdns/zh_CN + cp -r html_en/. $GITHUB_WORKSPACE/docs/mdns/en + cp -r html_zh_CN/. $GITHUB_WORKSPACE/docs/mdns/zh_CN + cd $GITHUB_WORKSPACE/docs touch .nojekyll - echo 'esp-modem' > index.html - echo 'esp-websocket-client' >> index.html + echo 'esp-modem
' > index.html + echo 'esp-websocket-client
' >> index.html + echo 'mDNS_en
' >> index.html + echo 'mDNS_zh_CN
' >> index.html - name: Upload components to component service uses: espressif/github-actions/upload_components@master with: - directories: "components/esp_modem;components/esp_websocket_client" + directories: "components/esp_modem;components/esp_websocket_client;components/mdns" namespace: "espressif" api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} diff --git a/.github/workflows/test_afl_fuzzer.yml b/.github/workflows/test_afl_fuzzer.yml new file mode 100644 index 000000000..a82e0096a --- /dev/null +++ b/.github/workflows/test_afl_fuzzer.yml @@ -0,0 +1,30 @@ +name: AFL fuzzer compilation test + +on: [push, pull_request] + +jobs: + build: + strategy: + matrix: + idf_ver: ["latest"] + idf_target: ["esp32"] + + runs-on: ubuntu-20.04 + container: espressif/idf:${{ matrix.idf_ver }} + steps: + - name: Checkout esp-protocols + uses: actions/checkout@master + with: + path: esp-protocols + - name: Install Necessary Libs + run: | + apt-get update -y + apt-get install -y libbsd-dev + - name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }} + env: + IDF_TARGET: ${{ matrix.idf_target }} + shell: bash + run: | + . ${IDF_PATH}/export.sh + cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/test_afl_fuzz_host/ + make INSTR=off diff --git a/README.md b/README.md index 366e078c9..f1952a9e6 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,11 @@ * Brief introduction [README](components/esp_modem/README.md) * Full html [documentation](https://espressif.github.io/esp-protocols/esp_modem/index.html) +### mDNS + +* Brief introduction [README](components/mdns/README.md) +* Full html [documentation](https://espressif.github.io/esp-protocols/mdns/index.html) + ### esp_websocket_client * Brief introduction [README](components/esp_websocket_client/README.md) diff --git a/examples/common_components/protocol_examples_common/CMakeLists.txt b/common_components/protocol_examples_common/CMakeLists.txt similarity index 100% rename from examples/common_components/protocol_examples_common/CMakeLists.txt rename to common_components/protocol_examples_common/CMakeLists.txt diff --git a/examples/common_components/protocol_examples_common/Kconfig.projbuild b/common_components/protocol_examples_common/Kconfig.projbuild similarity index 100% rename from examples/common_components/protocol_examples_common/Kconfig.projbuild rename to common_components/protocol_examples_common/Kconfig.projbuild diff --git a/examples/common_components/protocol_examples_common/addr_from_stdin.c b/common_components/protocol_examples_common/addr_from_stdin.c similarity index 100% rename from examples/common_components/protocol_examples_common/addr_from_stdin.c rename to common_components/protocol_examples_common/addr_from_stdin.c diff --git a/examples/common_components/protocol_examples_common/connect.c b/common_components/protocol_examples_common/connect.c similarity index 100% rename from examples/common_components/protocol_examples_common/connect.c rename to common_components/protocol_examples_common/connect.c diff --git a/examples/common_components/protocol_examples_common/include/addr_from_stdin.h b/common_components/protocol_examples_common/include/addr_from_stdin.h similarity index 100% rename from examples/common_components/protocol_examples_common/include/addr_from_stdin.h rename to common_components/protocol_examples_common/include/addr_from_stdin.h diff --git a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h b/common_components/protocol_examples_common/include/protocol_examples_common.h similarity index 100% rename from examples/common_components/protocol_examples_common/include/protocol_examples_common.h rename to common_components/protocol_examples_common/include/protocol_examples_common.h diff --git a/examples/common_components/protocol_examples_common/stdin_out.c b/common_components/protocol_examples_common/stdin_out.c similarity index 100% rename from examples/common_components/protocol_examples_common/stdin_out.c rename to common_components/protocol_examples_common/stdin_out.c diff --git a/components/mdns/README.md b/components/mdns/README.md new file mode 100644 index 000000000..dd8678527 --- /dev/null +++ b/components/mdns/README.md @@ -0,0 +1,11 @@ +# mDNS Service + +mDNS is a multicast UDP service that is used to provide local network service and host discovery. + +## Examples + +Get started with example test [Example](examples/README.md): + +## Documentation + +* View the full [html documentation](https://espressif.github.io/esp-protocols/mdns/index.html) diff --git a/components/mdns/docs/Doxyfile b/components/mdns/docs/Doxyfile new file mode 100755 index 000000000..4c6b12bcc --- /dev/null +++ b/components/mdns/docs/Doxyfile @@ -0,0 +1,75 @@ +# This is Doxygen configuration file +# +# Doxygen provides over 260 configuration statements +# To make this file easier to follow, +# it contains only statements that are non-default +# +# NOTE: +# It is recommended not to change defaults unless specifically required +# Test any changes how they affect generated documentation +# Make sure that correct warnings are generated to flag issues with documented code +# +# For the complete list of configuration statements see: +# http://doxygen.nl/manual/config.html + + +PROJECT_NAME = "ESP Protocols Programming Guide" + +## The 'INPUT' statement below is used as input by script 'gen-df-input.py' +## to automatically generate API reference list files heder_file.inc +## These files are placed in '_inc' directory +## and used to include in API reference documentation + +INPUT = \ + $(PROJECT_PATH)/include/mdns.h + +## Get warnings for functions that have no documentation for their parameters or return value +## +WARN_NO_PARAMDOC = YES + +## Enable preprocessing and remove __attribute__(...) expressions from the INPUT files +## +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +PREDEFINED = \ + $(ENV_DOXYGEN_DEFINES) \ + __DOXYGEN__=1 \ + __attribute__(x)= \ + _Static_assert()= \ + IDF_DEPRECATED(X)= \ + IRAM_ATTR= \ + configSUPPORT_DYNAMIC_ALLOCATION=1 \ + configSUPPORT_STATIC_ALLOCATION=1 \ + configQUEUE_REGISTRY_SIZE=1 \ + configUSE_RECURSIVE_MUTEXES=1 \ + configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS=1 \ + configNUM_THREAD_LOCAL_STORAGE_POINTERS=1 \ + configUSE_APPLICATION_TASK_TAG=1 \ + configTASKLIST_INCLUDE_COREID=1 \ + "ESP_EVENT_DECLARE_BASE(x)=extern esp_event_base_t x" + +## Do not complain about not having dot +## +HAVE_DOT = NO + +## Generate XML that is required for Breathe +## +GENERATE_XML = YES +XML_OUTPUT = xml + +GENERATE_HTML = NO +HAVE_DOT = NO +GENERATE_LATEX = NO +GENERATE_MAN = YES +GENERATE_RTF = NO + +## Skip distracting progress messages +## +QUIET = YES + +## Enable Section Tags for conditional documentation +## +ENABLED_SECTIONS += \ + DOC_EXCLUDE_HEADER_SECTION \ ## To conditionally remove doc sections from IDF source files without affecting documentation in upstream files. + DOC_SINGLE_GROUP ## To conditionally remove groups from the documentation and create a 'flat' document without affecting documentation in upstream files. diff --git a/components/mdns/docs/conf_common.py b/components/mdns/docs/conf_common.py new file mode 100644 index 000000000..10d1e997e --- /dev/null +++ b/components/mdns/docs/conf_common.py @@ -0,0 +1,21 @@ +from esp_docs.conf_docs import * # noqa: F403,F401 + +extensions += ['sphinx_copybutton', + # Needed as a trigger for running doxygen + 'esp_docs.esp_extensions.dummy_build_system', + 'esp_docs.esp_extensions.run_doxygen', + ] + +# link roles config +github_repo = 'espressif/esp-protocols' + +# context used by sphinx_idf_theme +html_context['github_user'] = 'espressif' +html_context['github_repo'] = 'esp-protocols' + +# Extra options required by sphinx_idf_theme +project_slug = 'esp-idf' # >=5.0 +versions_url = 'https://github.com/espressif/esp-protocols/docs/docs_versions.js' + +idf_targets = ['esp32'] +languages = ['en', 'zh_CN'] diff --git a/components/mdns/docs/en/conf.py b/components/mdns/docs/en/conf.py new file mode 100644 index 000000000..bba642268 --- /dev/null +++ b/components/mdns/docs/en/conf.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# +# English Language RTD & Sphinx config file +# +# Uses ../conf_common.py for most non-language-specific settings. + +# Importing conf_common adds all the non-language-specific +# parts to this conf module + +try: + from conf_common import * # noqa: F403,F401 +except ImportError: + import os + import sys + sys.path.insert(0, os.path.abspath('../')) + from conf_common import * # noqa: F403,F401 + +# General information about the project. +project = u'ESP-Protocols' +copyright = u'2016 - 2022, Espressif Systems (Shanghai) Co., Ltd' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +language = 'en' diff --git a/docs/en/api-reference/protocols/mdns.rst b/components/mdns/docs/en/index.rst similarity index 87% rename from docs/en/api-reference/protocols/mdns.rst rename to components/mdns/docs/en/index.rst index 00c8b37de..007d1bd9d 100644 --- a/docs/en/api-reference/protocols/mdns.rst +++ b/components/mdns/docs/en/index.rst @@ -7,7 +7,7 @@ Overview mDNS is a multicast UDP service that is used to provide local network service and host discovery. -mDNS is installed by default on most operating systems or is available as separate package. On ``Mac OS`` it is installed by default and is called ``Bonjour``. Apple releases an installer for ``Windows`` that can be found `on Apple's support page `_. On ``Linux``, mDNS is provided by `avahi `_ and is usually installed by default. +mDNS is installed by default on most operating systems or is available as separate package. On ``Mac OS`` it is installed by default and is called ``Bonjour``. Apple releases an installer for ``Windows`` that can be found `on Apple's support page `_. On ``Linux``, mDNS is provided by `avahi `_ and is usually installed by default. mDNS Properties ^^^^^^^^^^^^^^^ @@ -176,10 +176,26 @@ Example of using the methods above:: find_mdns_service("_ipp", "_tcp"); } + +Performance Optimization +^^^^^^^^^^^^^^^^^^^^^^^^ + +Execution Speed +^^^^^^^^^^^^^^^ + + - mDNS creates a task with default low priority 1 ``CONFIG_MDNS_TASK_PRIORITY`` (If ``CONFIG_FREERTOS_UNICORE`` enabeled it pinned to CPU0 (``CONFIG_MDNS_TASK_AFFINITY``). + Please check `Maximizing Execution Speed `_ for more details. + +Minimizing RAM Usage +^^^^^^^^^^^^^^^^^^^^ + +- mDNS creates a tasks with stack sizes configured by ``CONFIG_MDNS_TASK_STACK_SIZE``. +Please check `Minimizing RAM Usage `_ for more details. + Application Example ------------------- -mDNS server/scanner example: :example:`protocols/mdns`. +mDNS server/scanner example: :example:`<../examples>`. API Reference ------------- diff --git a/components/mdns/docs/generate_docs b/components/mdns/docs/generate_docs new file mode 100755 index 000000000..d822222b5 --- /dev/null +++ b/components/mdns/docs/generate_docs @@ -0,0 +1,28 @@ +build-docs --target esp32 --language en +build-docs --target esp32 --language zh_CN + +cp -rf _build/en/esp32/html html_en +cp -rf _build/zh_CN/esp32/html html_zh_CN +rm -rf _build __pycache__ tee + +# Modifes some version and target fields of index.html +echo "" | tee -a html_en/index.html html_zh_CN/index.html > /dev/null diff --git a/components/mdns/docs/zh_CN/conf.py b/components/mdns/docs/zh_CN/conf.py new file mode 100644 index 000000000..cc6fbc271 --- /dev/null +++ b/components/mdns/docs/zh_CN/conf.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# +# English Language RTD & Sphinx config file +# +# Uses ../conf_common.py for most non-language-specific settings. + +# Importing conf_common adds all the non-language-specific +# parts to this conf module +try: + from conf_common import * # noqa: F403,F401 +except ImportError: + import os + import sys + sys.path.insert(0, os.path.abspath('..')) + from conf_common import * # noqa: F403,F401 + +import datetime + +current_year = datetime.datetime.now().year + +# General information about the project. +project = u'ESP-IDF 编程指南' +copyright = u'2016 - {} 乐鑫信息科技(上海)股份有限公司'.format(current_year) + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +language = 'zh_CN' diff --git a/docs/zh_CN/api-reference/protocols/mdns.rst b/components/mdns/docs/zh_CN/index.rst similarity index 96% rename from docs/zh_CN/api-reference/protocols/mdns.rst rename to components/mdns/docs/zh_CN/index.rst index 08b3b373d..68befb637 100644 --- a/docs/zh_CN/api-reference/protocols/mdns.rst +++ b/components/mdns/docs/zh_CN/index.rst @@ -7,7 +7,7 @@ mDNS 服务 mDNS 是一种组播 UDP 服务,用来提供本地网络服务和主机发现。 -绝大多数的操作系统默认都会安装 mDNS 服务,或者提供单独的安装包。``Mac OS`` 默认会安装名为 ``Bonjour`` 的服务(该服务基于 mDNS),此外 Apple 还发布了适用于 Windows 系统的安装程序,可以在 `官方支持 `_ 找到。在 ``Linux`` 上,mDNS 服务由 `avahi `_ 提供,通常也会被默认安装。 +绝大多数的操作系统默认都会安装 mDNS 服务,或者提供单独的安装包。``Mac OS`` 默认会安装名为 ``Bonjour`` 的服务(该服务基于 mDNS),此外 Apple 还发布了适用于 Windows 系统的安装程序,可以在 `官方支持 `_ 找到。在 ``Linux`` 上,mDNS 服务由 `avahi `_ 提供,通常也会被默认安装。 mDNS 属性 ^^^^^^^^^ @@ -179,7 +179,7 @@ mDNS 提供查询服务和解析主机 IP/IPv6 地址的方法。 应用示例 -------- -有关 mDNS 服务器和查询器的应用示例请参考 :example:`protocols/mdns`。 +有关 mDNS 服务器和查询器的应用示例请参考 :example:`<../examples>`。 API 参考 -------- diff --git a/examples/protocols/mdns/CMakeLists.txt b/components/mdns/examples/CMakeLists.txt similarity index 72% rename from examples/protocols/mdns/CMakeLists.txt rename to components/mdns/examples/CMakeLists.txt index e624184a2..9461155a1 100644 --- a/examples/protocols/mdns/CMakeLists.txt +++ b/components/mdns/examples/CMakeLists.txt @@ -2,9 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -# (Not part of the boilerplate) +set(EXTRA_COMPONENT_DIRS "../..") # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +list(APPEND EXTRA_COMPONENT_DIRS "../../../common_components/protocol_examples_common") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mdns_test) diff --git a/examples/protocols/mdns/README.md b/components/mdns/examples/README.md similarity index 95% rename from examples/protocols/mdns/README.md rename to components/mdns/examples/README.md index b66cebc57..04047a6f7 100644 --- a/examples/protocols/mdns/README.md +++ b/components/mdns/examples/README.md @@ -15,7 +15,7 @@ Shows how to use mDNS to advertise lookup services and hosts * Open the project configuration menu (`idf.py menuconfig`) -* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../README.md) for more details. +* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu * Set `mDNS Hostname` as host name prefix for the device and its instance name in `mDNS Instance Name` * Disable `Resolve test services` to prevent the example from querying defined names/services on startup (cause warnings in example logs, as illustrated below) @@ -89,5 +89,3 @@ I (29396) mdns-test: Query PTR: _printer._tcp.local 2: Interface: STA, Type: V4 PTR : HP Color LaserJet MFP M277dw (7C2E10) ``` - -See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/mdns/main/CMakeLists.txt b/components/mdns/examples/main/CMakeLists.txt similarity index 100% rename from examples/protocols/mdns/main/CMakeLists.txt rename to components/mdns/examples/main/CMakeLists.txt diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/components/mdns/examples/main/Kconfig.projbuild similarity index 100% rename from examples/protocols/mdns/main/Kconfig.projbuild rename to components/mdns/examples/main/Kconfig.projbuild diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/components/mdns/examples/main/mdns_example_main.c similarity index 100% rename from examples/protocols/mdns/main/mdns_example_main.c rename to components/mdns/examples/main/mdns_example_main.c diff --git a/examples/protocols/mdns/mdns_example_test.py b/components/mdns/examples/mdns_example_test.py similarity index 100% rename from examples/protocols/mdns/mdns_example_test.py rename to components/mdns/examples/mdns_example_test.py diff --git a/examples/protocols/mdns/sdkconfig.ci.eth_custom_netif b/components/mdns/examples/sdkconfig.ci.eth_custom_netif similarity index 100% rename from examples/protocols/mdns/sdkconfig.ci.eth_custom_netif rename to components/mdns/examples/sdkconfig.ci.eth_custom_netif diff --git a/examples/protocols/mdns/sdkconfig.ci.eth_def b/components/mdns/examples/sdkconfig.ci.eth_def similarity index 100% rename from examples/protocols/mdns/sdkconfig.ci.eth_def rename to components/mdns/examples/sdkconfig.ci.eth_def diff --git a/examples/protocols/mdns/sdkconfig.ci.eth_socket b/components/mdns/examples/sdkconfig.ci.eth_socket similarity index 100% rename from examples/protocols/mdns/sdkconfig.ci.eth_socket rename to components/mdns/examples/sdkconfig.ci.eth_socket diff --git a/components/mdns/host_test/CMakeLists.txt b/components/mdns/tests/host_test/CMakeLists.txt similarity index 100% rename from components/mdns/host_test/CMakeLists.txt rename to components/mdns/tests/host_test/CMakeLists.txt diff --git a/components/mdns/host_test/README.md b/components/mdns/tests/host_test/README.md similarity index 100% rename from components/mdns/host_test/README.md rename to components/mdns/tests/host_test/README.md diff --git a/components/mdns/host_test/components/esp_event_mock/CMakeLists.txt b/components/mdns/tests/host_test/components/esp_event_mock/CMakeLists.txt similarity index 100% rename from components/mdns/host_test/components/esp_event_mock/CMakeLists.txt rename to components/mdns/tests/host_test/components/esp_event_mock/CMakeLists.txt diff --git a/components/mdns/host_test/components/esp_event_mock/esp_event_mock.c b/components/mdns/tests/host_test/components/esp_event_mock/esp_event_mock.c similarity index 100% rename from components/mdns/host_test/components/esp_event_mock/esp_event_mock.c rename to components/mdns/tests/host_test/components/esp_event_mock/esp_event_mock.c diff --git a/components/mdns/host_test/components/esp_event_mock/include/esp_event.h b/components/mdns/tests/host_test/components/esp_event_mock/include/esp_event.h similarity index 100% rename from components/mdns/host_test/components/esp_event_mock/include/esp_event.h rename to components/mdns/tests/host_test/components/esp_event_mock/include/esp_event.h diff --git a/components/mdns/host_test/components/esp_event_mock/include/esp_event_base.h b/components/mdns/tests/host_test/components/esp_event_mock/include/esp_event_base.h similarity index 100% rename from components/mdns/host_test/components/esp_event_mock/include/esp_event_base.h rename to components/mdns/tests/host_test/components/esp_event_mock/include/esp_event_base.h diff --git a/components/mdns/host_test/components/esp_netif_linux/CMakeLists.txt b/components/mdns/tests/host_test/components/esp_netif_linux/CMakeLists.txt similarity index 100% rename from components/mdns/host_test/components/esp_netif_linux/CMakeLists.txt rename to components/mdns/tests/host_test/components/esp_netif_linux/CMakeLists.txt diff --git a/components/mdns/host_test/components/esp_netif_linux/Kconfig b/components/mdns/tests/host_test/components/esp_netif_linux/Kconfig similarity index 100% rename from components/mdns/host_test/components/esp_netif_linux/Kconfig rename to components/mdns/tests/host_test/components/esp_netif_linux/Kconfig diff --git a/components/mdns/host_test/components/esp_netif_linux/esp_netif_linux.c b/components/mdns/tests/host_test/components/esp_netif_linux/esp_netif_linux.c similarity index 100% rename from components/mdns/host_test/components/esp_netif_linux/esp_netif_linux.c rename to components/mdns/tests/host_test/components/esp_netif_linux/esp_netif_linux.c diff --git a/components/mdns/host_test/components/esp_netif_linux/include/esp_wifi_types.h b/components/mdns/tests/host_test/components/esp_netif_linux/include/esp_wifi_types.h similarity index 100% rename from components/mdns/host_test/components/esp_netif_linux/include/esp_wifi_types.h rename to components/mdns/tests/host_test/components/esp_netif_linux/include/esp_wifi_types.h diff --git a/components/mdns/host_test/components/esp_system_protocols_linux/CMakeLists.txt b/components/mdns/tests/host_test/components/esp_system_protocols_linux/CMakeLists.txt similarity index 100% rename from components/mdns/host_test/components/esp_system_protocols_linux/CMakeLists.txt rename to components/mdns/tests/host_test/components/esp_system_protocols_linux/CMakeLists.txt diff --git a/components/mdns/host_test/components/esp_system_protocols_linux/esp_log_impl.c b/components/mdns/tests/host_test/components/esp_system_protocols_linux/esp_log_impl.c similarity index 100% rename from components/mdns/host_test/components/esp_system_protocols_linux/esp_log_impl.c rename to components/mdns/tests/host_test/components/esp_system_protocols_linux/esp_log_impl.c diff --git a/components/mdns/host_test/components/esp_system_protocols_linux/include/bsd_strings.h b/components/mdns/tests/host_test/components/esp_system_protocols_linux/include/bsd_strings.h similarity index 100% rename from components/mdns/host_test/components/esp_system_protocols_linux/include/bsd_strings.h rename to components/mdns/tests/host_test/components/esp_system_protocols_linux/include/bsd_strings.h diff --git a/components/mdns/host_test/components/esp_system_protocols_linux/include/machine/endian.h b/components/mdns/tests/host_test/components/esp_system_protocols_linux/include/machine/endian.h similarity index 100% rename from components/mdns/host_test/components/esp_system_protocols_linux/include/machine/endian.h rename to components/mdns/tests/host_test/components/esp_system_protocols_linux/include/machine/endian.h diff --git a/components/mdns/host_test/components/esp_system_protocols_linux/strlcat.c b/components/mdns/tests/host_test/components/esp_system_protocols_linux/strlcat.c similarity index 100% rename from components/mdns/host_test/components/esp_system_protocols_linux/strlcat.c rename to components/mdns/tests/host_test/components/esp_system_protocols_linux/strlcat.c diff --git a/components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt b/components/mdns/tests/host_test/components/esp_timer_linux/CMakeLists.txt similarity index 100% rename from components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt rename to components/mdns/tests/host_test/components/esp_timer_linux/CMakeLists.txt diff --git a/components/mdns/host_test/components/esp_timer_linux/esp_timer_linux.c b/components/mdns/tests/host_test/components/esp_timer_linux/esp_timer_linux.c similarity index 100% rename from components/mdns/host_test/components/esp_timer_linux/esp_timer_linux.c rename to components/mdns/tests/host_test/components/esp_timer_linux/esp_timer_linux.c diff --git a/components/mdns/host_test/components/esp_timer_linux/include/esp_timer.h b/components/mdns/tests/host_test/components/esp_timer_linux/include/esp_timer.h similarity index 100% rename from components/mdns/host_test/components/esp_timer_linux/include/esp_timer.h rename to components/mdns/tests/host_test/components/esp_timer_linux/include/esp_timer.h diff --git a/components/mdns/host_test/components/esp_timer_linux/timer_task.cpp b/components/mdns/tests/host_test/components/esp_timer_linux/timer_task.cpp similarity index 100% rename from components/mdns/host_test/components/esp_timer_linux/timer_task.cpp rename to components/mdns/tests/host_test/components/esp_timer_linux/timer_task.cpp diff --git a/components/mdns/host_test/components/esp_timer_linux/timer_task.hpp b/components/mdns/tests/host_test/components/esp_timer_linux/timer_task.hpp similarity index 100% rename from components/mdns/host_test/components/esp_timer_linux/timer_task.hpp rename to components/mdns/tests/host_test/components/esp_timer_linux/timer_task.hpp diff --git a/components/mdns/host_test/components/freertos_linux/CMakeLists.txt b/components/mdns/tests/host_test/components/freertos_linux/CMakeLists.txt similarity index 100% rename from components/mdns/host_test/components/freertos_linux/CMakeLists.txt rename to components/mdns/tests/host_test/components/freertos_linux/CMakeLists.txt diff --git a/components/mdns/host_test/components/freertos_linux/Kconfig b/components/mdns/tests/host_test/components/freertos_linux/Kconfig similarity index 100% rename from components/mdns/host_test/components/freertos_linux/Kconfig rename to components/mdns/tests/host_test/components/freertos_linux/Kconfig diff --git a/components/mdns/host_test/components/freertos_linux/freertos_linux.c b/components/mdns/tests/host_test/components/freertos_linux/freertos_linux.c similarity index 100% rename from components/mdns/host_test/components/freertos_linux/freertos_linux.c rename to components/mdns/tests/host_test/components/freertos_linux/freertos_linux.c diff --git a/components/mdns/host_test/components/freertos_linux/include/esp_task.h b/components/mdns/tests/host_test/components/freertos_linux/include/esp_task.h similarity index 100% rename from components/mdns/host_test/components/freertos_linux/include/esp_task.h rename to components/mdns/tests/host_test/components/freertos_linux/include/esp_task.h diff --git a/components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h b/components/mdns/tests/host_test/components/freertos_linux/include/freertos/FreeRTOS.h similarity index 100% rename from components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h rename to components/mdns/tests/host_test/components/freertos_linux/include/freertos/FreeRTOS.h diff --git a/components/mdns/host_test/components/freertos_linux/include/freertos/task.h b/components/mdns/tests/host_test/components/freertos_linux/include/freertos/task.h similarity index 100% rename from components/mdns/host_test/components/freertos_linux/include/freertos/task.h rename to components/mdns/tests/host_test/components/freertos_linux/include/freertos/task.h diff --git a/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.cpp b/components/mdns/tests/host_test/components/freertos_linux/queue_unique_ptr.cpp similarity index 100% rename from components/mdns/host_test/components/freertos_linux/queue_unique_ptr.cpp rename to components/mdns/tests/host_test/components/freertos_linux/queue_unique_ptr.cpp diff --git a/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.hpp b/components/mdns/tests/host_test/components/freertos_linux/queue_unique_ptr.hpp similarity index 100% rename from components/mdns/host_test/components/freertos_linux/queue_unique_ptr.hpp rename to components/mdns/tests/host_test/components/freertos_linux/queue_unique_ptr.hpp diff --git a/components/mdns/host_test/main/CMakeLists.txt b/components/mdns/tests/host_test/main/CMakeLists.txt similarity index 100% rename from components/mdns/host_test/main/CMakeLists.txt rename to components/mdns/tests/host_test/main/CMakeLists.txt diff --git a/components/mdns/host_test/main/main.c b/components/mdns/tests/host_test/main/main.c similarity index 100% rename from components/mdns/host_test/main/main.c rename to components/mdns/tests/host_test/main/main.c diff --git a/components/mdns/test_afl_fuzz_host/CMakeLists.txt b/components/mdns/tests/test_afl_fuzz_host/CMakeLists.txt similarity index 100% rename from components/mdns/test_afl_fuzz_host/CMakeLists.txt rename to components/mdns/tests/test_afl_fuzz_host/CMakeLists.txt diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/tests/test_afl_fuzz_host/Makefile similarity index 95% rename from components/mdns/test_afl_fuzz_host/Makefile rename to components/mdns/tests/test_afl_fuzz_host/Makefile index af58a3c05..313b21ac5 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/tests/test_afl_fuzz_host/Makefile @@ -1,10 +1,10 @@ TEST_NAME=test FUZZ=afl-fuzz -COMPONENTS_DIR=../.. +COMPONENTS_DIR=$(IDF_PATH)/components COMPILER_ICLUDE_DIR=$(shell echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf) CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversion -Wno-macro-redefined -Wno-int-to-void-pointer-cast -DHOOK_MALLOC_FAILED -DESP_EVENT_H_ -D__ESP_LOG_H__ \ - -I. -I.. -I../include -I../private_include -I ./build/config \ + -I. -I../.. -I../../include -I../../private_include -I ./build/config \ -I$(COMPONENTS_DIR) \ -I$(COMPONENTS_DIR)/driver/include \ -I$(COMPONENTS_DIR)/esp_common/include \ @@ -68,7 +68,7 @@ all: $(TEST_NAME) @echo "[CC] $<" @$(CC) $(CFLAGS) -c $< -o $@ -mdns.o: ../mdns.c +mdns.o: ../../mdns.c @echo "[CC] $<" @$(CC) $(CFLAGS) -include mdns_mock.h $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@ diff --git a/components/mdns/test_afl_fuzz_host/README.md b/components/mdns/tests/test_afl_fuzz_host/README.md similarity index 100% rename from components/mdns/test_afl_fuzz_host/README.md rename to components/mdns/tests/test_afl_fuzz_host/README.md diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.c b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.c similarity index 100% rename from components/mdns/test_afl_fuzz_host/esp32_mock.c rename to components/mdns/tests/test_afl_fuzz_host/esp32_mock.c diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/tests/test_afl_fuzz_host/esp32_mock.h similarity index 100% rename from components/mdns/test_afl_fuzz_host/esp32_mock.h rename to components/mdns/tests/test_afl_fuzz_host/esp32_mock.h diff --git a/components/mdns/test_afl_fuzz_host/esp_attr.h b/components/mdns/tests/test_afl_fuzz_host/esp_attr.h similarity index 100% rename from components/mdns/test_afl_fuzz_host/esp_attr.h rename to components/mdns/tests/test_afl_fuzz_host/esp_attr.h diff --git a/components/mdns/test_afl_fuzz_host/esp_netif_mock.c b/components/mdns/tests/test_afl_fuzz_host/esp_netif_mock.c similarity index 100% rename from components/mdns/test_afl_fuzz_host/esp_netif_mock.c rename to components/mdns/tests/test_afl_fuzz_host/esp_netif_mock.c diff --git a/components/mdns/test_afl_fuzz_host/in/file2.bin b/components/mdns/tests/test_afl_fuzz_host/in/file2.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/file2.bin rename to components/mdns/tests/test_afl_fuzz_host/in/file2.bin diff --git a/components/mdns/test_afl_fuzz_host/in/minif_4a_txt.bin b/components/mdns/tests/test_afl_fuzz_host/in/minif_4a_txt.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/minif_4a_txt.bin rename to components/mdns/tests/test_afl_fuzz_host/in/minif_4a_txt.bin diff --git a/components/mdns/test_afl_fuzz_host/in/minif_aaaa.bin b/components/mdns/tests/test_afl_fuzz_host/in/minif_aaaa.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/minif_aaaa.bin rename to components/mdns/tests/test_afl_fuzz_host/in/minif_aaaa.bin diff --git a/components/mdns/test_afl_fuzz_host/in/minif_any.bin b/components/mdns/tests/test_afl_fuzz_host/in/minif_any.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/minif_any.bin rename to components/mdns/tests/test_afl_fuzz_host/in/minif_any.bin diff --git a/components/mdns/test_afl_fuzz_host/in/minif_disc.bin b/components/mdns/tests/test_afl_fuzz_host/in/minif_disc.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/minif_disc.bin rename to components/mdns/tests/test_afl_fuzz_host/in/minif_disc.bin diff --git a/components/mdns/test_afl_fuzz_host/in/minif_ptr.bin b/components/mdns/tests/test_afl_fuzz_host/in/minif_ptr.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/minif_ptr.bin rename to components/mdns/tests/test_afl_fuzz_host/in/minif_ptr.bin diff --git a/components/mdns/test_afl_fuzz_host/in/minif_query.bin b/components/mdns/tests/test_afl_fuzz_host/in/minif_query.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/minif_query.bin rename to components/mdns/tests/test_afl_fuzz_host/in/minif_query.bin diff --git a/components/mdns/test_afl_fuzz_host/in/minif_query2.bin b/components/mdns/tests/test_afl_fuzz_host/in/minif_query2.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/minif_query2.bin rename to components/mdns/tests/test_afl_fuzz_host/in/minif_query2.bin diff --git a/components/mdns/test_afl_fuzz_host/in/sub_fritz_m.bin b/components/mdns/tests/test_afl_fuzz_host/in/sub_fritz_m.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/sub_fritz_m.bin rename to components/mdns/tests/test_afl_fuzz_host/in/sub_fritz_m.bin diff --git a/components/mdns/test_afl_fuzz_host/in/telnet_ptr.bin b/components/mdns/tests/test_afl_fuzz_host/in/telnet_ptr.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/telnet_ptr.bin rename to components/mdns/tests/test_afl_fuzz_host/in/telnet_ptr.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-14.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-14.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-14.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-14.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-15.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-15.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-15.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-15.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-16.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-16.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-16.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-16.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-28.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-28.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-28.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-28.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-29.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-29.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-29.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-29.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-31.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-31.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-31.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-31.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-53.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-53.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-53.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-53.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-56.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-56.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-56.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-56.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-63.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-63.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-63.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-63.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-83.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-83.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-83.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-83.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-88.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-88.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-88.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-88.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-89.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-89.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-89.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-89.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-95.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-95.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-95.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-95.bin diff --git a/components/mdns/test_afl_fuzz_host/in/test-96.bin b/components/mdns/tests/test_afl_fuzz_host/in/test-96.bin similarity index 100% rename from components/mdns/test_afl_fuzz_host/in/test-96.bin rename to components/mdns/tests/test_afl_fuzz_host/in/test-96.bin diff --git a/components/mdns/test_afl_fuzz_host/input_packets.txt b/components/mdns/tests/test_afl_fuzz_host/input_packets.txt similarity index 100% rename from components/mdns/test_afl_fuzz_host/input_packets.txt rename to components/mdns/tests/test_afl_fuzz_host/input_packets.txt diff --git a/components/mdns/test_afl_fuzz_host/mdns_di.h b/components/mdns/tests/test_afl_fuzz_host/mdns_di.h similarity index 100% rename from components/mdns/test_afl_fuzz_host/mdns_di.h rename to components/mdns/tests/test_afl_fuzz_host/mdns_di.h diff --git a/components/mdns/test_afl_fuzz_host/mdns_mock.h b/components/mdns/tests/test_afl_fuzz_host/mdns_mock.h similarity index 100% rename from components/mdns/test_afl_fuzz_host/mdns_mock.h rename to components/mdns/tests/test_afl_fuzz_host/mdns_mock.h diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/tests/test_afl_fuzz_host/sdkconfig.h similarity index 100% rename from components/mdns/test_afl_fuzz_host/sdkconfig.h rename to components/mdns/tests/test_afl_fuzz_host/sdkconfig.h diff --git a/components/mdns/test_afl_fuzz_host/test.c b/components/mdns/tests/test_afl_fuzz_host/test.c similarity index 100% rename from components/mdns/test_afl_fuzz_host/test.c rename to components/mdns/tests/test_afl_fuzz_host/test.c diff --git a/tools/test_apps/protocols/mdns/CMakeLists.txt b/components/mdns/tests/test_apps/CMakeLists.txt similarity index 79% rename from tools/test_apps/protocols/mdns/CMakeLists.txt rename to components/mdns/tests/test_apps/CMakeLists.txt index e756f2b40..466df27ef 100644 --- a/tools/test_apps/protocols/mdns/CMakeLists.txt +++ b/components/mdns/tests/test_apps/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.5) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(EXTRA_COMPONENT_DIRS "../../../../common_components/protocol_examples_common") include($ENV{IDF_PATH}/tools/cmake/project.cmake) diff --git a/tools/test_apps/protocols/mdns/README.md b/components/mdns/tests/test_apps/README.md similarity index 95% rename from tools/test_apps/protocols/mdns/README.md rename to components/mdns/tests/test_apps/README.md index 40ae127fe..96b76dcb7 100644 --- a/tools/test_apps/protocols/mdns/README.md +++ b/components/mdns/tests/test_apps/README.md @@ -23,7 +23,8 @@ In order to run both of them just needed to set up the project and run by 'pytho * Open the project configuration menu (`idf.py menuconfig`) -* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](README.md) for more details. +* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. + * Set `mDNS Hostname` as host name prefix for the device and its instance name in `mDNS Instance Name` ### Build and Flash diff --git a/tools/test_apps/protocols/mdns/app_test.py b/components/mdns/tests/test_apps/app_test.py similarity index 100% rename from tools/test_apps/protocols/mdns/app_test.py rename to components/mdns/tests/test_apps/app_test.py diff --git a/tools/test_apps/protocols/mdns/main/CMakeLists.txt b/components/mdns/tests/test_apps/main/CMakeLists.txt similarity index 100% rename from tools/test_apps/protocols/mdns/main/CMakeLists.txt rename to components/mdns/tests/test_apps/main/CMakeLists.txt diff --git a/tools/test_apps/protocols/mdns/main/Kconfig.projbuild b/components/mdns/tests/test_apps/main/Kconfig.projbuild similarity index 100% rename from tools/test_apps/protocols/mdns/main/Kconfig.projbuild rename to components/mdns/tests/test_apps/main/Kconfig.projbuild diff --git a/tools/test_apps/protocols/mdns/main/main.c b/components/mdns/tests/test_apps/main/main.c similarity index 100% rename from tools/test_apps/protocols/mdns/main/main.c rename to components/mdns/tests/test_apps/main/main.c diff --git a/tools/test_apps/protocols/mdns/main/mdns_test.c b/components/mdns/tests/test_apps/main/mdns_test.c similarity index 100% rename from tools/test_apps/protocols/mdns/main/mdns_test.c rename to components/mdns/tests/test_apps/main/mdns_test.c diff --git a/tools/test_apps/protocols/mdns/sdkconfig.defaults b/components/mdns/tests/test_apps/sdkconfig.defaults similarity index 100% rename from tools/test_apps/protocols/mdns/sdkconfig.defaults rename to components/mdns/tests/test_apps/sdkconfig.defaults diff --git a/components/mdns/test/CMakeLists.txt b/components/mdns/tests/unit_test/CMakeLists.txt similarity index 100% rename from components/mdns/test/CMakeLists.txt rename to components/mdns/tests/unit_test/CMakeLists.txt diff --git a/components/mdns/test/test_mdns.c b/components/mdns/tests/unit_test/test_mdns.c similarity index 100% rename from components/mdns/test/test_mdns.c rename to components/mdns/tests/unit_test/test_mdns.c diff --git a/docs/docs_versions.js b/docs/docs_versions.js new file mode 100644 index 000000000..447ce23d1 --- /dev/null +++ b/docs/docs_versions.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_VERSIONS = { + VERSIONS: [ + { name: "latest", has_targets: true, supported_targets: [ "esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3" ] }, + ], + IDF_TARGETS: [ + { text: "ESP32", value: "esp32"}, + { text: "ESP32-S2", value: "esp32s2"}, + { text: "ESP32-S3", value: "esp32s3"}, + { text: "ESP32-C2", value: "esp32c2"}, + { text: "ESP32-C3", value: "esp32c3"} + ], +};