Skip to content

(WIP) mDNS: single instance for all interfaces (udp: +multicast on all interfaces) #7268

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions libraries/ESP8266WiFi/src/WiFiUdp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ uint8_t WiFiUDP::begin(uint16_t port)
return (_ctx->listen(IPAddress(), port)) ? 1 : 0;
}

uint8_t WiFiUDP::beginMulticast(IPAddress multicast, uint16_t port)
{
return beginMulticast(IPAddress(IP4_ADDR_ANY), multicast, port);
}

uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port)
{
if (_ctx) {
Expand Down Expand Up @@ -156,11 +161,7 @@ int WiFiUDP::beginPacket(IPAddress ip, uint16_t port)
int WiFiUDP::beginPacketMulticast(IPAddress multicastAddress, uint16_t port,
IPAddress interfaceAddress, int ttl)
{
if (!_ctx) {
_ctx = new UdpContext;
_ctx->ref();
}
if (!_ctx->connect(multicastAddress, port)) {
if (!beginPacket(multicastAddress, port)) {
return 0;
}
_ctx->setMulticastInterface(interfaceAddress);
Expand All @@ -176,6 +177,14 @@ int WiFiUDP::endPacket()
return (_ctx->send()) ? 1 : 0;
}

int WiFiUDP::endPacketOverMulticast()
{
if (!_ctx)
return 0;

return (_ctx->send_multicast_all()) ? 1 : 0;
}

size_t WiFiUDP::write(uint8_t byte)
{
return write(&byte, 1);
Expand Down
8 changes: 8 additions & 0 deletions libraries/ESP8266WiFi/src/WiFiUdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,18 @@ class WiFiUDP : public UDP, public SList<WiFiUDP> {
void stop() override;
// join a multicast group and listen on the given port
uint8_t beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port);
uint8_t beginMulticast(IPAddress multicast, uint16_t port);

// Sending UDP packets

// Start building up a packet to send to the remote host specific in ip and port
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
int beginPacket(IPAddress ip, uint16_t port) override;

// Start building up a packet to send to the remote host specific in host and port
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
int beginPacket(const char *host, uint16_t port) override;

// Start building up a packet to send to the multicast address
// multicastAddress - muticast address to send to
// interfaceAddress - the local IP address of the interface that should be used
Expand All @@ -67,9 +70,14 @@ class WiFiUDP : public UDP, public SList<WiFiUDP> {
uint16_t port,
IPAddress interfaceAddress,
int ttl = 1);

// Finish off this packet and send it
// Returns 1 if the packet was sent successfully, 0 if there was an error
int endPacket() override;

int beginPacketOverMulticast(const IPAddress& ip, uint16_t port) { return beginPacket(ip, port); }
int endPacketOverMulticast();

// Write a single byte into the packet
size_t write(uint8_t) override;
// Write size bytes from buffer into the packet
Expand Down
74 changes: 58 additions & 16 deletions libraries/ESP8266WiFi/src/include/UdpContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ class UdpContext
return size;
}

bool send(CONST ip_addr_t* addr = 0, uint16_t port = 0)
bool send(CONST ip_addr_t* addr = 0, uint16_t port = 0, bool release_source = true)
{
size_t data_size = _tx_buf_offset;
pbuf* tx_copy = pbuf_alloc(PBUF_TRANSPORT, data_size, PBUF_RAM);
Expand All @@ -435,39 +435,81 @@ class UdpContext
data_size -= will_copy;
}
}
if (_tx_buf_head)
pbuf_free(_tx_buf_head);
_tx_buf_head = 0;
_tx_buf_cur = 0;
_tx_buf_offset = 0;
if (release_source) {
reset_send_buffer();
}
if(!tx_copy){
return false;
}


if (!addr) {
addr = &_pcb->remote_ip;
port = _pcb->remote_port;
}
#ifdef LWIP_MAYBE_XCC
uint16_t old_ttl = _pcb->ttl;
if (ip_addr_ismulticast(addr)) {
_pcb->ttl = _mcast_ttl;
}
#endif

err_t err = udp_sendto(_pcb, tx_copy, addr, port);
if (err != ERR_OK) {
DEBUGV(":ust rc=%d\r\n", (int) err);
}
#ifdef LWIP_MAYBE_XCC
_pcb->ttl = old_ttl;
#endif

pbuf_free(tx_copy);
return err == ERR_OK;
}

bool send_multicast_all (CONST ip_addr_t* addr = 0, uint16_t port = 0)
{
if (!addr) {
addr = &_pcb->remote_ip;
port = _pcb->remote_port;
}
if (!ip_addr_ismulticast(addr))
{
return false;
}

// backup PCB multicast settings

// backup multicast IPv4 address
ip4_addr_t backup_mcast_addr;
ip4_addr_set(&backup_mcast_addr, udp_get_multicast_netif_addr(_pcb));
// reset it in PCB (may be useless, interface setting is used first (i set)))
ip4_addr_set_any(udp_get_multicast_netif_addr(_pcb));
// backup multicast interface (will be overwritten)
u8_t backup_mcast_index = udp_get_multicast_netif_index(_pcb);

// loop on all interfaces and send

bool ret = false;
for (netif* nif = netif_list; nif; nif = nif->next)
if (netif_is_up(nif))
{
// change multicast interface
setMulticastInterface(nif);
ret = ret || send(addr, port, false);
}

// release source
reset_send_buffer();
// ^^ optimization path: avoid tx_copy multiple times in ::send(,,false)

// restore PCB multicast settings
udp_set_multicast_netif_index(_pcb, backup_mcast_index);
udp_set_multicast_netif_addr(_pcb, &backup_mcast_addr);

return ret;
}

private:

void reset_send_buffer ()
{
if (_tx_buf_head)
pbuf_free(_tx_buf_head);
_tx_buf_head = 0;
_tx_buf_cur = 0;
_tx_buf_offset = 0;
}

size_t _processSize (const pbuf* pb)
{
size_t ret = 0;
Expand Down
89 changes: 16 additions & 73 deletions libraries/ESP8266mDNS/src/LEAmDNS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,10 @@ MDNSResponder::MDNSResponder(void)
m_pServiceQueries(0),
m_fnServiceTxtCallback(0),
#ifdef ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE
m_bPassivModeEnabled(true),
m_bPassivModeEnabled(true)
#else
m_bPassivModeEnabled(false),
m_bPassivModeEnabled(false)
#endif
m_netif(nullptr)
{
}

Expand Down Expand Up @@ -95,89 +94,33 @@ MDNSResponder::~MDNSResponder(void)
bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& p_IPAddress, uint32_t p_u32TTL)
{

(void)p_IPAddress;
(void)p_u32TTL; // ignored
bool bResult = false;

if (0 == m_pUDPContext)
{
if (_setHostname(p_pcHostname))
{

//// select interface

m_netif = nullptr;
IPAddress ipAddress = p_IPAddress;

if (!ipAddress.isSet())
{

IPAddress sta = WiFi.localIP();
IPAddress ap = WiFi.softAPIP();

if (sta.isSet())
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] STA interface selected\n")));
ipAddress = sta;
}
else if (ap.isSet())
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] AP interface selected\n")));
ipAddress = ap;
}
else
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] standard interfaces are not up, please specify one in ::begin()\n")));
return false;
}

// continue to ensure interface is UP
}

// check existence of this IP address in the interface list
bool found = false;
m_netif = nullptr;
for (auto a : addrList)
if (ipAddress == a.addr())
{
if (a.ifUp())
{
found = true;
m_netif = a.interface();
break;
}
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] found interface for IP '%s' but it is not UP\n"), ipAddress.toString().c_str()););
}
if (!found)
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] interface defined by IP '%s' not found\n"), ipAddress.toString().c_str()););
return false;
}

//// done selecting the interface

if (m_netif->num == STATION_IF)
m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & pEvent)
{

m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & pEvent)
(void) pEvent;
// Ensure that _restart() runs in USER context
schedule_function([this]()
{
(void) pEvent;
// Ensure that _restart() runs in USER context
schedule_function([this]()
{
MDNSResponder::_restart();
});
MDNSResponder::_restart();
});
});

m_DisconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & pEvent)
m_DisconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & pEvent)
{
(void) pEvent;
// Ensure that _restart() runs in USER context
schedule_function([this]()
{
(void) pEvent;
// Ensure that _restart() runs in USER context
schedule_function([this]()
{
MDNSResponder::_restart();
});
MDNSResponder::_restart();
});
}
});

bResult = _restart();
}
Expand Down
3 changes: 1 addition & 2 deletions libraries/ESP8266mDNS/src/LEAmDNS.h
Original file line number Diff line number Diff line change
Expand Up @@ -1203,7 +1203,6 @@ class MDNSResponder
MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback;
bool m_bPassivModeEnabled;
stcProbeInformation m_HostProbeInformation;
CONST netif* m_netif; // network interface to run on

/** CONTROL **/
/* MAINTENANCE */
Expand Down Expand Up @@ -1260,7 +1259,7 @@ class MDNSResponder

const IPAddress _getResponseMulticastInterface() const
{
return IPAddress(m_netif->ip_addr);
return IPAddress(IP4_ADDR_ANY);
}

uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader,
Expand Down
8 changes: 2 additions & 6 deletions libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ bool MDNSResponder::_process(bool p_bUserContext)
}
else
{
bResult = (m_netif != nullptr) &&
(m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running
_updateProbeStatus() && // Probing
bResult = _updateProbeStatus() && // Probing
_checkServiceQueryCache(); // Service query cache check
}
return bResult;
Expand All @@ -98,9 +96,7 @@ bool MDNSResponder::_process(bool p_bUserContext)
bool MDNSResponder::_restart(void)
{

return ((m_netif != nullptr) &&
(m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running
(_resetProbeStatus(true)) && // Stop and restart probing
return ((_resetProbeStatus(true)) && // Stop and restart probing
(_allocUDPContext())); // Restart UDP
}

Expand Down
2 changes: 1 addition & 1 deletion libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ bool MDNSResponder::_allocUDPContext(void)
//TODO: set multicast address (lwip_joingroup() is IPv4 only at the time of writing)
multicast_addr.addr = DNS_MQUERY_IPV6_GROUP_INIT;
#endif
if (ERR_OK == igmp_joingroup(ip_2_ip4(&m_netif->ip_addr), ip_2_ip4(&multicast_addr)))
if (ERR_OK == igmp_joingroup(IP4_ADDR_ANY4, ip_2_ip4(&multicast_addr)))
{
m_pUDPContext = new UdpContext;
m_pUDPContext->ref();
Expand Down
2 changes: 1 addition & 1 deletion libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ bool MDNSResponder::_sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParamet
#endif
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: Will send to '%s'.\n"), toMulticastAddress.toString().c_str()););
bResult = ((_prepareMDNSMessage(p_rSendParameter, fromIPAddress)) &&
(m_pUDPContext->send(toMulticastAddress, DNS_MQUERY_PORT)));
(m_pUDPContext->send_multicast_all(toMulticastAddress, DNS_MQUERY_PORT)));

DEBUG_EX_ERR(if (!bResult)
{
Expand Down