mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-08-06 15:15:15 +08:00
feat(mdns): Sync mDNS function from ESP-IDF 607d899503afd4ce0e457c815249a0213083f9f5
This commit is contained in:
9
components/mdns/CMakeLists.txt
Normal file
9
components/mdns/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
||||
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()
|
||||
|
13
components/mdns/Kconfig
Normal file
13
components/mdns/Kconfig
Normal file
@ -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
|
@ -16,7 +16,6 @@
|
||||
#include "mdns_private.h"
|
||||
#include "mdns_networking.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef MDNS_ENABLE_DEBUG
|
||||
void mdns_debug_packet(const uint8_t * data, size_t len);
|
||||
@ -97,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;
|
||||
@ -1181,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)
|
||||
@ -1405,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; i<len; i++) {
|
||||
if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, true, true)) {
|
||||
@ -1741,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
|
||||
@ -2555,7 +2581,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;
|
||||
}
|
||||
|
||||
@ -3539,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);
|
||||
@ -3621,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;
|
||||
@ -4125,6 +4145,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;
|
||||
@ -4204,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;
|
||||
}
|
||||
|
@ -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; i<TCPIP_ADAPTER_IF_MAX; i++) {
|
||||
for (p=0; p<MDNS_IP_PROTOCOL_MAX; p++) {
|
||||
if(_mdns_server->interfaces[i].pcbs[p].pcb){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop PCB Main code
|
||||
*/
|
||||
@ -92,105 +190,19 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,16 +210,27 @@ static esp_err_t _udp_pcb_v6_init(tcpip_adapter_if_t tcpip_if)
|
||||
*/
|
||||
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 {
|
||||
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 +239,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 +249,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 +268,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 +278,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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
@ -361,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;
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define CONFIG_MDNS_MAX_SERVICES 25
|
||||
|
||||
#define ERR_OK 0
|
||||
#define ESP_OK 0
|
||||
|
Reference in New Issue
Block a user