Skip to content

Commit

Permalink
Merge pull request espressif#137 from david-cermak/mdns/isolate_netwo…
Browse files Browse the repository at this point in the history
…rking

mdns: Decouple networking from the main mdns module
  • Loading branch information
david-cermak authored Mar 22, 2023
2 parents a838af4 + ee9b04f commit 76047a4
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 106 deletions.
46 changes: 31 additions & 15 deletions components/mdns/mdns.c
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,7 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an
} else if (answer->type == MDNS_TYPE_A) {
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) {
if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && _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)) {
Expand Down Expand Up @@ -1387,8 +1387,7 @@ static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_an
if (answer->host == &_mdns_self_host) {
struct esp_ip6_addr if_ip6s[NETIF_IPV6_MAX_NUMS];
uint8_t count = 0;
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) {
if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state != PCB_DUP) {
return 0;
}
count = esp_netif_get_all_ip6(_mdns_get_esp_netif(tcpip_if), if_ip6s);
Expand Down Expand Up @@ -2275,7 +2274,7 @@ static void _mdns_send_bye(mdns_srv_item_t **services, size_t len, bool include_

for (i = 0; i < MDNS_MAX_INTERFACES; i++) {
for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) {
if (_mdns_server->interfaces[i].pcbs[j].pcb && _mdns_server->interfaces[i].pcbs[j].state == PCB_RUNNING) {
if (mdns_is_netif_ready(i, j) && _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);
}
}
Expand All @@ -2289,7 +2288,7 @@ static void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco
{
mdns_pcb_t *_pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol];
size_t i;
if (_pcb->pcb) {
if (mdns_is_netif_ready(tcpip_if, ip_protocol)) {
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)) {
Expand Down Expand Up @@ -2333,7 +2332,7 @@ static void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool pr
uint8_t i, j;
for (i = 0; i < MDNS_MAX_INTERFACES; i++) {
for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) {
if (_mdns_server->interfaces[i].pcbs[j].pcb) {
if (mdns_is_netif_ready(i, j)) {
mdns_pcb_t *_pcb = &_mdns_server->interfaces[i].pcbs[j];
if (clear_old_probe) {
free(_pcb->probe_services);
Expand Down Expand Up @@ -2628,7 +2627,7 @@ static void _mdns_remove_scheduled_service_packets(mdns_service_t *service)


mdns_pcb_t *_pcb = &_mdns_server->interfaces[q->tcpip_if].pcbs[q->ip_protocol];
if (_pcb->pcb) {
if (mdns_is_netif_ready(q->tcpip_if, q->ip_protocol)) {
if (PCB_STATE_IS_PROBING(_pcb)) {
uint8_t i;
//check if we are probing this service
Expand Down Expand Up @@ -2829,6 +2828,22 @@ static int _mdns_check_txt_collision(mdns_service_t *service, const uint8_t *dat
return 0;//same
}

static esp_err_t mdns_pcb_deinit_local(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_proto)
{
esp_err_t err = _mdns_pcb_deinit(tcpip_if, ip_proto);
mdns_pcb_t *_pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_proto];
if (_pcb == NULL || err != ESP_OK) {
return err;
}
free(_pcb->probe_services);
_pcb->state = PCB_OFF;
_pcb->probe_ip = false;
_pcb->probe_services = NULL;
_pcb->probe_services_len = 0;
_pcb->probe_running = false;
_pcb->failed_probes = 0;
return ESP_OK;
}
/**
* @brief Set interface as duplicate if another is found on the same subnet
*/
Expand All @@ -2840,11 +2855,11 @@ static void _mdns_dup_interface(mdns_if_t tcpip_if)
return; // no other interface found
}
for (i = 0; i < MDNS_IP_PROTOCOL_MAX; i++) {
if (_mdns_server->interfaces[other_if].pcbs[i].pcb) {
if (mdns_is_netif_ready(other_if, i)) {
//stop this interface and mark as dup
if (_mdns_server->interfaces[tcpip_if].pcbs[i].pcb) {
if (mdns_is_netif_ready(tcpip_if, i)) {
_mdns_clear_pcb_tx_queue_head(tcpip_if, i);
_mdns_pcb_deinit(tcpip_if, i);
mdns_pcb_deinit_local(tcpip_if, i);
}
_mdns_server->interfaces[tcpip_if].pcbs[i].state = PCB_DUP;
_mdns_announce_pcb(other_if, i, NULL, 0, true);
Expand Down Expand Up @@ -3984,8 +3999,9 @@ void mdns_parse_packet(mdns_rx_packet_t *packet)
*/
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_is_netif_ready(tcpip_if, ip_protocol)) {
if (_mdns_pcb_init(tcpip_if, ip_protocol)) {
_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].failed_probes = 0;
return;
}
}
Expand All @@ -3999,9 +4015,9 @@ 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) {
if (mdns_is_netif_ready(tcpip_if, ip_protocol)) {
_mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol);
_mdns_pcb_deinit(tcpip_if, ip_protocol);
mdns_pcb_deinit_local(tcpip_if, ip_protocol);
mdns_if_t other_if = _mdns_get_other_if (tcpip_if);
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;
Expand Down Expand Up @@ -4669,7 +4685,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, 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) {
if (mdns_is_netif_ready(tcpip_if, ip_protocol) && _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state > PCB_INIT) {
packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol);
if (!packet) {
return;
Expand Down Expand Up @@ -5483,7 +5499,7 @@ void mdns_free(void)
_mdns_service_task_stop();
for (i = 0; i < MDNS_MAX_INTERFACES; i++) {
for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) {
_mdns_pcb_deinit(i, j);
mdns_pcb_deinit_local(i, j);
}
}
free((char *)_mdns_server->hostname);
Expand Down
64 changes: 33 additions & 31 deletions components/mdns/mdns_networking_lwip.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,26 @@
#include "mdns_networking.h"
#include "esp_netif_net_stack.h"

extern mdns_server_t *_mdns_server;

/*
* MDNS Server Networking
*
*/
static const char *TAG = "mdns_networking";
enum interface_protocol {
PROTO_IPV4 = 1 << MDNS_IP_PROTOCOL_V4,
PROTO_IPV6 = 1 << MDNS_IP_PROTOCOL_V6
};

typedef struct interfaces {
bool ready;
int proto;
} interfaces_t;

static interfaces_t s_interfaces[MDNS_MAX_INTERFACES];

static struct udp_pcb *_pcb_main = NULL;

static const char *TAG = "mdns_networking";

static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport);

/**
Expand All @@ -53,7 +63,7 @@ static esp_err_t _udp_pcb_main_init(void)
_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);
udp_recv(_pcb_main, &_udp_recv, NULL);
return ESP_OK;
}

Expand Down Expand Up @@ -168,36 +178,39 @@ 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;
bool found = false;
for (i = 0; i < MDNS_MAX_INTERFACES; i++) {
pcb = _mdns_server->interfaces[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 ()) {
if (s_interfaces[i].proto && 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)) {
#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;
}
}
packet->tcpip_if = i;
found = true;
break;
}
pcb = NULL;
}

if (!pcb || !_mdns_server || !_mdns_server->action_queue
|| _mdns_send_rx_action(packet) != ESP_OK) {
if (!found || _mdns_send_rx_action(packet) != ESP_OK) {
pbuf_free(this_pb);
free(packet);
}
}

}

bool mdns_is_netif_ready(mdns_if_t netif, mdns_ip_protocol_t ip_proto)
{
return s_interfaces[netif].ready &&
s_interfaces[netif].proto & (ip_proto == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6);
}

/**
* @brief Check if any of the interfaces is up
*/
Expand All @@ -206,7 +219,7 @@ static bool _udp_pcb_is_in_use(void)
int i, p;
for (i = 0; i < MDNS_MAX_INTERFACES; i++) {
for (p = 0; p < MDNS_IP_PROTOCOL_MAX; p++) {
if (_mdns_server->interfaces[i].pcbs[p].pcb) {
if (mdns_is_netif_ready(i, p)) {
return true;
}
}
Expand All @@ -219,19 +232,9 @@ static bool _udp_pcb_is_in_use(void)
*/
static void _udp_pcb_deinit(mdns_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) {
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;
s_interfaces[tcpip_if].proto &= ~(ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6);
if (s_interfaces[tcpip_if].proto == 0) {
s_interfaces[tcpip_if].ready = false;
_udp_join_group(tcpip_if, ip_protocol, false);
if (!_udp_pcb_is_in_use()) {
_udp_pcb_main_deinit();
Expand All @@ -244,7 +247,7 @@ static void _udp_pcb_deinit(mdns_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) {
if (mdns_is_netif_ready(tcpip_if, ip_protocol)) {
return ESP_ERR_INVALID_STATE;
}

Expand All @@ -257,9 +260,9 @@ static esp_err_t _udp_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protoco
if (err) {
return err;
}
s_interfaces[tcpip_if].proto |= (ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6);
s_interfaces[tcpip_if].ready = true;

_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;
}

Expand Down Expand Up @@ -323,14 +326,13 @@ 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];
nif = esp_netif_get_netif_impl(_mdns_get_esp_netif(msg->tcpip_if));
if (!nif) {
if (!nif || !mdns_is_netif_ready(msg->tcpip_if, msg->ip_protocol) || _pcb_main == NULL) {
pbuf_free(msg->pbt);
msg->err = ERR_IF;
return ERR_IF;
}
esp_err_t err = udp_sendto_if (_pcb->pcb, msg->pbt, msg->ip, msg->port, (struct netif *)nif);
esp_err_t err = udp_sendto_if (_pcb_main, msg->pbt, msg->ip, msg->port, (struct netif *)nif);
pbuf_free(msg->pbt);
msg->err = err;
return err;
Expand Down
Loading

0 comments on commit 76047a4

Please sign in to comment.