Skip to content

Commit

Permalink
MDNS: fix random crash on startup (esp8266#6261)
Browse files Browse the repository at this point in the history
* mDNS debug option + AP address is used by default when STA is also present

* mDNS: store network interface, checking it is up

* igmp: force on selected interface (avoid crash *sometimes*)

* fix for all lwip2 ipv4 ipv6 & lwip1

* mdns: IPAddress is not needed to reference associated interface

* mdns: debug: fix print warnings

* emulation: add ets_strncpy

* emulation: truly emulate AddrList (remove fake one)
  • Loading branch information
d-a-v authored and earlephilhower committed Sep 5, 2019
1 parent 273f400 commit 5ca0bde
Show file tree
Hide file tree
Showing 12 changed files with 289 additions and 316 deletions.
300 changes: 180 additions & 120 deletions boards.txt

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions cores/esp8266/AddrList.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ struct netifWrapper
const char* ifmac () const { return (const char*)_netif->hwaddr; }
int ifnumber () const { return _netif->num; }
bool ifUp () const { return !!(_netif->flags & NETIF_FLAG_UP); }
CONST netif* interface () const { return _netif; }

const ip_addr_t* ipFromNetifNum () const
{
Expand Down
85 changes: 70 additions & 15 deletions libraries/ESP8266mDNS/src/LEAmDNS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/

#include <Schedule.h>
#include <AddrList.h>

#include "LEAmDNS_Priv.h"

Expand Down Expand Up @@ -59,11 +60,11 @@ 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,20 +96,74 @@ bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& p_IPAddress
if (0 == m_pUDPContext) {
if (_setHostname(p_pcHostname)) {

m_IPAddress = p_IPAddress;
//// select interface

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

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

if (!ipAddress.isSet()) {

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

if (!sta.isSet() && !ap.isSet()) {

DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] internal interfaces (STA, AP) are not set (none was specified)\n")));
return false;
}

if (ap.isSet()) {

if (sta.isSet())
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface AP selected over STA (none was specified)\n")));
else
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface AP selected\n")));
ipAddress = ap;

} else {

DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface STA selected (none was specified)\n")));
ipAddress = sta;

}

// 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) {
(void) pEvent;
// Ensure that _restart() runs in USER context
schedule_function([this]() { MDNSResponder::_restart(); });
});

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

bResult = _restart();
}
DEBUG_EX_ERR(if (!bResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: FAILED for '%s'!\n"), (p_pcHostname ?: "-")); } );
Expand Down Expand Up @@ -642,7 +697,7 @@ uint32_t MDNSResponder::queryService(const char* p_pcService,
}
}
else {
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService: INVALID input data!\n"), p_pcService, p_pcProtocol););
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService: INVALID input data!\n")););
}
return u32Result;
}
Expand Down
4 changes: 2 additions & 2 deletions libraries/ESP8266mDNS/src/LEAmDNS.h
Original file line number Diff line number Diff line change
Expand Up @@ -1148,7 +1148,7 @@ class MDNSResponder {
MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback;
bool m_bPassivModeEnabled;
stcProbeInformation m_HostProbeInformation;
IPAddress m_IPAddress;
CONST netif* m_netif; // network interface to run on

/** CONTROL **/
/* MAINTENANCE */
Expand Down Expand Up @@ -1203,7 +1203,7 @@ class MDNSResponder {
uint16_t p_u16QueryType,
stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers = 0);

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

uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader,
bool* p_pbFullNameMatch = 0) const;
Expand Down
71 changes: 14 additions & 57 deletions libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ bool MDNSResponder::_process(bool p_bUserContext) {
}
}
else {
bResult = ((WiFi.isConnected() || // Either station is connected
WiFi.softAPgetStationNum()>0) && // Or AP has stations connected
(_updateProbeStatus()) && // Probing
(_checkServiceQueryCache())); // Service query cache check
bResult = (m_netif != nullptr) &&
(m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running
_updateProbeStatus() && // Probing
_checkServiceQueryCache(); // Service query cache check
}
return bResult;
}
Expand All @@ -91,53 +91,10 @@ bool MDNSResponder::_process(bool p_bUserContext) {
*/
bool MDNSResponder::_restart(void) {

// check m_IPAddress
if (!m_IPAddress.isSet()) {

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

if (!sta.isSet() && !ap.isSet()) {

DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] internal interfaces (STA, AP) are not set (none was specified)\n")));
return false;
}

if (sta.isSet()) {

if (ap.isSet())
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface STA selected over AP (none was specified)\n")));
else
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface STA selected\n")));
m_IPAddress = sta;

} else {

DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface AP selected (none was specified)\n")));
m_IPAddress = ap;

}

// continue to ensure interface is UP
}

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

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


Expand Down Expand Up @@ -797,7 +754,7 @@ bool MDNSResponder::_processPTRAnswer(const MDNSResponder::stcMDNS_RRAnswerPTR*
if (p_pPTRAnswer->m_u32TTL) { // Received update message
pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); // Update TTL tag
DEBUG_EX_INFO(
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Updated TTL(%lu) for "), p_pPTRAnswer->m_u32TTL);
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Updated TTL(%d) for "), (int)p_pPTRAnswer->m_u32TTL);
_printRRDomain(pSQAnswer->m_ServiceDomain);
DEBUG_OUTPUT.printf_P(PSTR("\n"));
);
Expand Down Expand Up @@ -851,7 +808,7 @@ bool MDNSResponder::_processSRVAnswer(const MDNSResponder::stcMDNS_RRAnswerSRV*
if (p_pSRVAnswer->m_u32TTL) { // First or update message (TTL != 0)
pSQAnswer->m_TTLHostDomainAndPort.set(p_pSRVAnswer->m_u32TTL); // Update TTL tag
DEBUG_EX_INFO(
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: Updated TTL(%lu) for "), p_pSRVAnswer->m_u32TTL);
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: Updated TTL(%d) for "), (int)p_pSRVAnswer->m_u32TTL);
_printRRDomain(pSQAnswer->m_ServiceDomain);
DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n"));
);
Expand Down Expand Up @@ -904,7 +861,7 @@ bool MDNSResponder::_processTXTAnswer(const MDNSResponder::stcMDNS_RRAnswerTXT*
if (p_pTXTAnswer->m_u32TTL) { // First or update message
pSQAnswer->m_TTLTxts.set(p_pTXTAnswer->m_u32TTL); // Update TTL tag
DEBUG_EX_INFO(
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: Updated TTL(%lu) for "), p_pTXTAnswer->m_u32TTL);
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: Updated TTL(%d) for "), (int)p_pTXTAnswer->m_u32TTL);
_printRRDomain(pSQAnswer->m_ServiceDomain);
DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n"));
);
Expand Down Expand Up @@ -956,7 +913,7 @@ bool MDNSResponder::_processTXTAnswer(const MDNSResponder::stcMDNS_RRAnswerTXT*
if (p_pAAnswer->m_u32TTL) { // Valid TTL -> Update answers TTL
pIP4Address->m_TTL.set(p_pAAnswer->m_u32TTL);
DEBUG_EX_INFO(
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%lu) for "), p_pAAnswer->m_u32TTL);
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%d) for "), (int)p_pAAnswer->m_u32TTL);
_printRRDomain(pSQAnswer->m_ServiceDomain);
DEBUG_OUTPUT.printf_P(PSTR(" IP4Address (%s)\n"), pIP4Address->m_IPAddress.toString().c_str());
);
Expand Down Expand Up @@ -1123,7 +1080,7 @@ bool MDNSResponder::_updateProbeStatus(void) {

if (MDNS_ANNOUNCE_COUNT > m_HostProbeInformation.m_u8SentCount) {
m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY);
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing host (%lu).\n\n"), m_HostProbeInformation.m_u8SentCount););
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing host (%d).\n\n"), m_HostProbeInformation.m_u8SentCount););
}
else {
m_HostProbeInformation.m_Timeout.resetToNeverExpires();
Expand Down Expand Up @@ -1171,7 +1128,7 @@ bool MDNSResponder::_updateProbeStatus(void) {

if (MDNS_ANNOUNCE_COUNT > pService->m_ProbeInformation.m_u8SentCount) {
pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY);
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing service %s.%s.%s (%lu)\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_ProbeInformation.m_u8SentCount););
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing service %s.%s.%s (%d)\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_ProbeInformation.m_u8SentCount););
}
else {
pService->m_ProbeInformation.m_Timeout.resetToNeverExpires();
Expand Down
4 changes: 2 additions & 2 deletions libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ namespace MDNSImplementation {
*/

bool MDNSResponder::_callProcess(void) {
DEBUG_EX_INFO(DEBUG_OUTPUT.printf("[MDNSResponder] _callProcess (%lu, triggered by: %s)\n", millis(), m_pUDPContext->getRemoteAddress().toString().c_str()););
DEBUG_EX_INFO(DEBUG_OUTPUT.printf("[MDNSResponder] _callProcess (%lu, triggered by: %s)\n", millis(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()););

return _process(false);
}
Expand Down Expand Up @@ -199,7 +199,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(IP4_ADDR_ANY4, ip_2_ip4(&multicast_addr))) {
if (ERR_OK == igmp_joingroup(ip_2_ip4(&m_netif->ip_addr), ip_2_ip4(&multicast_addr))) {
m_pUDPContext = new UdpContext;
m_pUDPContext->ref();

Expand Down
3 changes: 3 additions & 0 deletions libraries/ESP8266mDNS/src/LEAmDNS_Priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ namespace MDNSImplementation {
#define ESP_8266_MDNS_INCLUDE
//#define DEBUG_ESP_MDNS_RESPONDER

#if !defined(DEBUG_ESP_MDNS_RESPONDER) && defined(DEBUG_ESP_MDNS)
#define DEBUG_ESP_MDNS_RESPONDER
#endif

#ifndef LWIP_OPEN_SRC
#define LWIP_OPEN_SRC
Expand Down
Loading

0 comments on commit 5ca0bde

Please sign in to comment.