1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

MDNS MultiInterface (#7636)

* MDNS MultiInterface
* Move strlcat & strlcpy to __cplusplus
* Add LwipIntfCB.cpp to Makefile
This commit is contained in:
hreintke 2020-10-15 19:39:55 +02:00 committed by GitHub
parent 1c624dd76a
commit 9003b02889
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 189 additions and 177 deletions

View File

@ -27,7 +27,8 @@
#include "ESP8266mDNS.h"
#include "LEAmDNS_Priv.h"
#include <LwipIntf.h> // LwipIntf::stateUpCB()
#include "lwip/igmp.h"
namespace esp8266
{
@ -61,13 +62,7 @@ MDNSResponder::MDNSResponder(void)
m_pUDPContext(0),
m_pcHostname(0),
m_pServiceQueries(0),
m_fnServiceTxtCallback(0),
#ifdef ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE
m_bPassivModeEnabled(true),
#else
m_bPassivModeEnabled(false),
#endif
m_netif(nullptr)
m_fnServiceTxtCallback(0)
{
}
@ -93,104 +88,29 @@ MDNSResponder::~MDNSResponder(void)
Finally the responder is (re)started
*/
bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& p_IPAddress, uint32_t p_u32TTL)
bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& /*p_IPAddress*/, uint32_t /*p_u32TTL*/)
{
(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)
{
(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();
}
LwipIntf::stateUpCB
(
[this](netif * intf)
{
(void)intf;
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] new Interface '%c%c' is UP! restarting\n"), intf->name[0], intf->name[1]));
_restart();
}
);
DEBUG_EX_ERR(if (!bResult)
{
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: FAILED for '%s'!\n"), (p_pcHostname ? : "-"));
});
}
else
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: Ignoring multiple calls to begin (Ignored host domain: '%s')!\n"), (p_pcHostname ? : "-")););
}
return bResult;
}
@ -207,9 +127,6 @@ bool MDNSResponder::close(void)
if (0 != m_pUDPContext)
{
m_GotIPHandler.reset(); // reset WiFi event callbacks.
m_DisconnectedHandler.reset();
_announce(false, true);
_resetProbeStatus(false); // Stop probing
_releaseServiceQueries();
@ -1329,11 +1246,6 @@ bool MDNSResponder::notifyAPChange(void)
*/
bool MDNSResponder::update(void)
{
if (m_bPassivModeEnabled)
{
m_bPassivModeEnabled = false;
}
return _process(true);
}
@ -1374,6 +1286,94 @@ MDNSResponder::hMDNSService MDNSResponder::enableArduino(uint16_t p_u16Port,
return hService;
}
/*
MULTICAST GROUPS
*/
/*
MDNSResponder::_joinMulticastGroups
*/
bool MDNSResponder::_joinMulticastGroups(void)
{
bool bResult = false;
// Join multicast group(s)
for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next)
{
if (netif_is_up(pNetIf))
{
#ifdef MDNS_IPV4_SUPPORT
ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT;
if (!(pNetIf->flags & NETIF_FLAG_IGMP))
{
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _createHost: Setting flag: flags & NETIF_FLAG_IGMP\n")););
pNetIf->flags |= NETIF_FLAG_IGMP;
if (ERR_OK != igmp_start(pNetIf))
{
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _createHost: igmp_start FAILED!\n")););
}
}
if ((ERR_OK == igmp_joingroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4))))
{
bResult = true;
}
else
{
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _createHost: igmp_joingroup_netif(" NETIFID_STR ": %s) FAILED!\n"),
NETIFID_VAL(pNetIf), IPAddress(multicast_addr_V4).toString().c_str()););
}
#endif
#ifdef MDNS_IPV6_SUPPORT
ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT;
bResult = ((bResult) &&
(ERR_OK == mld6_joingroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6))));
DEBUG_EX_ERR_IF(!bResult, DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _createHost: mld6_joingroup_netif (" NETIFID_STR ") FAILED!\n"),
NETIFID_VAL(pNetIf)));
#endif
}
}
return bResult;
}
/*
clsLEAmDNS2_Host::_leaveMulticastGroups
*/
bool MDNSResponder::_leaveMulticastGroups()
{
bool bResult = false;
for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next)
{
if (netif_is_up(pNetIf))
{
bResult = true;
// Leave multicast group(s)
#ifdef MDNS_IPV4_SUPPORT
ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT;
if (ERR_OK != igmp_leavegroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4)))
{
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n")););
}
#endif
#ifdef MDNS_IPV6_SUPPORT
ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT;
if (ERR_OK != mld6_leavegroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)/*&(multicast_addr_V6.u_addr.ip6)*/))
{
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n")););
}
#endif
}
}
return bResult;
}
} //namespace MDNSImplementation

View File

@ -164,6 +164,10 @@ namespace MDNSImplementation
*/
#define MDNS_QUERYSERVICES_WAIT_TIME 1000
/*
Timeout for udpContext->sendtimeout()
*/
#define MDNS_UDPCONTEXT_TIMEOUT 50
/**
MDNSResponder
@ -185,6 +189,8 @@ public:
{
return begin(p_strHostname.c_str(), p_IPAddress, p_u32TTL);
}
bool _joinMulticastGroups(void);
bool _leaveMulticastGroups(void);
// Finish MDNS processing
bool close(void);
@ -1184,6 +1190,7 @@ protected:
~stcMDNSSendParameter(void);
bool clear(void);
bool clearCachedNames(void);
bool shiftOffset(uint16_t p_u16Shift);
@ -1199,12 +1206,8 @@ protected:
UdpContext* m_pUDPContext;
char* m_pcHostname;
stcMDNSServiceQuery* m_pServiceQueries;
WiFiEventHandler m_DisconnectedHandler;
WiFiEventHandler m_GotIPHandler;
MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback;
bool m_bPassivModeEnabled;
stcProbeInformation m_HostProbeInformation;
const netif* m_netif; // network interface to run on
/** CONTROL **/
/* MAINTENANCE */
@ -1259,11 +1262,6 @@ protected:
uint16_t p_u16QueryType,
stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers = 0);
const IPAddress _getResponseMulticastInterface() const
{
return IPAddress(m_netif->ip_addr);
}
uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader,
bool* p_pbFullNameMatch = 0) const;
uint8_t _replyMaskForService(const stcMDNS_RRHeader& p_RRHeader,

View File

@ -85,9 +85,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;
@ -99,13 +97,10 @@ 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
}
/**
RECEIVING
*/
@ -192,8 +187,7 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea
{
// Define host replies, BUT only answer queries after probing is done
u8HostOrServiceReplies =
sendParameter.m_u8HostReplyMask |= (((m_bPassivModeEnabled) ||
(ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus))
sendParameter.m_u8HostReplyMask |= (((ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus))
? _replyMaskForHost(questionRR.m_Header, 0)
: 0);
DEBUG_EX_INFO(if (u8HostOrServiceReplies)
@ -222,8 +216,7 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea
for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext)
{
// Define service replies, BUT only answer queries after probing is done
uint8_t u8ReplyMaskForQuestion = (((m_bPassivModeEnabled) ||
(ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus))
uint8_t u8ReplyMaskForQuestion = (((ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus))
? _replyMaskForService(questionRR.m_Header, *pService, 0)
: 0);
u8HostOrServiceReplies |= (pService->m_u8ReplyMask |= u8ReplyMaskForQuestion);
@ -364,9 +357,8 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea
// IP4 address was asked for
#ifdef MDNS_IP4_SUPPORT
if ((AnswerType_A == pKnownRRAnswer->answerType()) &&
(((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == _getResponseMulticastInterface()))
(((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == m_pUDPContext->getInputNetif()->ip_addr))
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP4 address already known... skipping!\n")););
sendParameter.m_u8HostReplyMask &= ~ContentFlag_A;
} // else: RData NOT IP4 length !!
@ -399,7 +391,8 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea
#ifdef MDNS_IP4_SUPPORT
if (AnswerType_A == pKnownRRAnswer->answerType())
{
IPAddress localIPAddress(_getResponseMulticastInterface());
IPAddress localIPAddress(m_pUDPContext->getInputNetif()->ip_addr);
if (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == localIPAddress)
{
// SAME IP address -> We've received an old message from ourselfs (same IP)
@ -1221,9 +1214,7 @@ bool MDNSResponder::_updateProbeStatus(void)
//
// Probe host domain
if ((ProbingStatus_ReadyToStart == m_HostProbeInformation.m_ProbingStatus) && // Ready to get started AND
//TODO: Fix the following to allow Ethernet shield or other interfaces
(_getResponseMulticastInterface() != IPAddress())) // Has IP address
if (ProbingStatus_ReadyToStart == m_HostProbeInformation.m_ProbingStatus)
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Starting host probing...\n")););
@ -2007,12 +1998,18 @@ uint8_t MDNSResponder::_replyMaskForHost(const MDNSResponder::stcMDNS_RRHeader&
// PTR request
#ifdef MDNS_IP4_SUPPORT
stcMDNS_RRDomain reverseIP4Domain;
if ((_buildDomainForReverseIP4(_getResponseMulticastInterface(), reverseIP4Domain)) &&
for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next)
{
if (netif_is_up(pNetIf))
{
if ((_buildDomainForReverseIP4(pNetIf->ip_addr, reverseIP4Domain)) &&
(p_RRHeader.m_Domain == reverseIP4Domain))
{
// Reverse domain match
u8ReplyMask |= ContentFlag_PTR_IP4;
}
}
}
#endif
#ifdef MDNS_IP6_SUPPORT
// TODO

View File

@ -168,19 +168,9 @@ bool MDNSResponder::_allocUDPContext(void)
{
DEBUG_EX_INFO(DEBUG_OUTPUT.println("[MDNSResponder] _allocUDPContext"););
bool bResult = false;
_releaseUDPContext();
_joinMulticastGroups();
#ifdef MDNS_IP4_SUPPORT
ip_addr_t multicast_addr = DNS_MQUERY_IPV4_GROUP_INIT;
#endif
#ifdef MDNS_IP6_SUPPORT
//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)))
{
m_pUDPContext = new UdpContext;
m_pUDPContext->ref();
@ -188,11 +178,13 @@ bool MDNSResponder::_allocUDPContext(void)
{
m_pUDPContext->setMulticastTTL(MDNS_MULTICAST_TTL);
m_pUDPContext->onRx(std::bind(&MDNSResponder::_callProcess, this));
}
else
{
return false;
}
bResult = m_pUDPContext->connect(&multicast_addr, DNS_MQUERY_PORT);
}
}
return bResult;
return true;
}
/*
@ -205,6 +197,7 @@ bool MDNSResponder::_releaseUDPContext(void)
{
m_pUDPContext->unref();
m_pUDPContext = 0;
_leaveMulticastGroups();
}
return true;
}

View File

@ -2408,12 +2408,25 @@ bool MDNSResponder::stcMDNSSendParameter::clear(void)
delete m_pQuestions;
m_pQuestions = pNext;
}
return clearCachedNames();;
}
/*
MDNSResponder::stcMDNSSendParameter::clear cached names
*/
bool MDNSResponder::stcMDNSSendParameter::clearCachedNames(void)
{
m_u16Offset = 0;
while (m_pDomainCacheItems)
{
stcDomainCacheItem* pNext = m_pDomainCacheItems->m_pNext;
delete m_pDomainCacheItems;
m_pDomainCacheItems = pNext;
}
m_pDomainCacheItems = nullptr;
return true;
}

View File

@ -89,8 +89,8 @@ bool MDNSResponder::_sendMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_rSen
});
IPAddress ipRemote;
ipRemote = m_pUDPContext->getRemoteAddress();
bResult = ((_prepareMDNSMessage(p_rSendParameter, _getResponseMulticastInterface())) &&
(m_pUDPContext->send(ipRemote, m_pUDPContext->getRemotePort())));
bResult = ((_prepareMDNSMessage(p_rSendParameter, m_pUDPContext->getInputNetif()->ip_addr)) &&
(m_pUDPContext->sendTimeout(ipRemote, m_pUDPContext->getRemotePort(), MDNS_UDPCONTEXT_TIMEOUT)));
}
else // Multicast response
{
@ -121,8 +121,13 @@ bool MDNSResponder::_sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParamet
bool bResult = false;
for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next)
{
if (netif_is_up(pNetIf))
{
IPAddress fromIPAddress;
fromIPAddress = _getResponseMulticastInterface();
//fromIPAddress = _getResponseMulticastInterface();
fromIPAddress = pNetIf->ip_addr;
m_pUDPContext->setMulticastInterface(fromIPAddress);
#ifdef MDNS_IP4_SUPPORT
@ -134,12 +139,14 @@ 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->sendTimeout(toMulticastAddress, DNS_MQUERY_PORT, MDNS_UDPCONTEXT_TIMEOUT)));
DEBUG_EX_ERR(if (!bResult)
{
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: FAILED!\n"));
});
}
}
return bResult;
}
@ -157,6 +164,7 @@ bool MDNSResponder::_prepareMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_r
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage\n")););
bool bResult = true;
p_rSendParameter.clearCachedNames(); // Need to remove cached names, p_SendParameter might have been used before on other interface
// Prepare header; count answers
stcMDNS_MsgHeader msgHeader(p_rSendParameter.m_u16ID, p_rSendParameter.m_bResponse, 0, p_rSendParameter.m_bAuthorative);

View File

@ -268,6 +268,7 @@ ARDUINO_LIBS := \
IPAddress.cpp \
Updater.cpp \
base64.cpp \
LwipIntfCB.cpp \
) \
$(addprefix ../../libraries/ESP8266WiFi/src/,\
ESP8266WiFi.cpp \

View File

@ -62,13 +62,15 @@ extern "C" {
// TODO: #include <stdlib_noniso.h> ?
char* itoa (int val, char *s, int radix);
char* ltoa (long val, char *s, int radix);
#ifdef __cplusplus
}
#endif
size_t strlcat(char *dst, const char *src, size_t size);
size_t strlcpy(char *dst, const char *src, size_t size);
#ifdef __cplusplus
}
#endif
// exotic typedefs used in the sdk
#include <stdint.h>