mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
* Board ID as build flag When using IDE or `arduino-cli board list`, show full board name and FQBN ``` $ arduino-cli.exe board list Port Protocol Type Board Name FQBN Core xxx.xxx.x.xxx network Network Port LOLIN(WEMOS) D1 R2 & mini esp8266com:esp8266:d1_mini esp8266com:esp8266 ``` Also add `description` field to the mDNS response containing the original `{build.board}` string value. resolve #7759 * does not work with recent ide (?) * fixup! does not work with recent ide (?)
1367 lines
46 KiB
C++
1367 lines
46 KiB
C++
/*
|
|
LEAmDNS.cpp
|
|
|
|
License (MIT license):
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
#include <Schedule.h>
|
|
#include <AddrList.h>
|
|
|
|
#include "ESP8266mDNS.h"
|
|
#include "LEAmDNS_Priv.h"
|
|
#include <LwipIntf.h> // LwipIntf::stateUpCB()
|
|
#include <lwip/igmp.h>
|
|
#include <lwip/prot/dns.h>
|
|
|
|
// should be defined at build time
|
|
#ifndef ARDUINO_BOARD_ID
|
|
#define ARDUINO_BOARD_ID "generic"
|
|
#endif
|
|
|
|
namespace esp8266
|
|
{
|
|
|
|
/*
|
|
LEAmDNS
|
|
*/
|
|
namespace MDNSImplementation
|
|
{
|
|
|
|
/**
|
|
INTERFACE
|
|
*/
|
|
|
|
/**
|
|
MDNSResponder::MDNSResponder
|
|
*/
|
|
MDNSResponder::MDNSResponder(void) :
|
|
m_pServices(0), m_pUDPContext(0), m_pcHostname(0), m_pServiceQueries(0),
|
|
m_fnServiceTxtCallback(0)
|
|
{
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::~MDNSResponder
|
|
*/
|
|
MDNSResponder::~MDNSResponder(void)
|
|
{
|
|
_resetProbeStatus(false);
|
|
_releaseServiceQueries();
|
|
_releaseHostname();
|
|
_releaseUDPContext();
|
|
_releaseServices();
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::begin
|
|
|
|
Set the host domain (for probing) and install WiFi event handlers for
|
|
IP assignment and disconnection management. In both cases, the MDNS responder
|
|
is restarted (reset and restart probe status)
|
|
Finally the responder is (re)started
|
|
|
|
*/
|
|
bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& /*p_IPAddress*/,
|
|
uint32_t /*p_u32TTL*/)
|
|
{
|
|
bool bResult = false;
|
|
|
|
if (_setHostname(p_pcHostname))
|
|
{
|
|
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 ?: "-"));
|
|
});
|
|
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::close
|
|
|
|
Ends the MDNS responder.
|
|
Announced services are unannounced (by multicasting a goodbye message)
|
|
|
|
*/
|
|
bool MDNSResponder::close(void)
|
|
{
|
|
bool bResult = false;
|
|
|
|
if (0 != m_pUDPContext)
|
|
{
|
|
_announce(false, true);
|
|
_resetProbeStatus(false); // Stop probing
|
|
_releaseServiceQueries();
|
|
_releaseServices();
|
|
_releaseUDPContext();
|
|
_releaseHostname();
|
|
|
|
bResult = true;
|
|
}
|
|
else
|
|
{
|
|
DEBUG_EX_INFO(
|
|
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] close: Ignoring call to close!\n")););
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::end
|
|
|
|
Ends the MDNS responder.
|
|
for compatibility with esp32
|
|
|
|
*/
|
|
|
|
bool MDNSResponder::end(void)
|
|
{
|
|
return close();
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::setHostname
|
|
|
|
Replaces the current hostname and restarts probing.
|
|
For services without own instance name (when the host name was used a instance
|
|
name), the instance names are replaced also (and the probing is restarted).
|
|
|
|
*/
|
|
bool MDNSResponder::setHostname(const char* p_pcHostname)
|
|
{
|
|
bool bResult = false;
|
|
|
|
if (_setHostname(p_pcHostname))
|
|
{
|
|
m_HostProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart;
|
|
|
|
// Replace 'auto-set' service names
|
|
bResult = true;
|
|
for (stcMDNSService* pService = m_pServices; ((bResult) && (pService));
|
|
pService = pService->m_pNext)
|
|
{
|
|
if (pService->m_bAutoName)
|
|
{
|
|
bResult = pService->setName(p_pcHostname);
|
|
pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart;
|
|
}
|
|
}
|
|
}
|
|
DEBUG_EX_ERR(if (!bResult) {
|
|
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setHostname: FAILED for '%s'!\n"),
|
|
(p_pcHostname ?: "-"));
|
|
});
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::setHostname (LEGACY)
|
|
*/
|
|
bool MDNSResponder::setHostname(const String& p_strHostname)
|
|
{
|
|
return setHostname(p_strHostname.c_str());
|
|
}
|
|
|
|
/*
|
|
SERVICES
|
|
*/
|
|
|
|
/*
|
|
MDNSResponder::addService
|
|
|
|
Add service; using hostname if no name is explicitly provided for the service
|
|
The usual '_' underline, which is prepended to service and protocol, eg. _http,
|
|
may be given. If not, it is added automatically.
|
|
|
|
*/
|
|
MDNSResponder::hMDNSService MDNSResponder::addService(const char* p_pcName,
|
|
const char* p_pcService,
|
|
const char* p_pcProtocol,
|
|
uint16_t p_u16Port)
|
|
{
|
|
hMDNSService hResult = 0;
|
|
|
|
if (((!p_pcName) || // NO name OR
|
|
(MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcName)))
|
|
&& // Fitting name
|
|
(p_pcService) && (MDNS_SERVICE_NAME_LENGTH >= os_strlen(p_pcService)) && (p_pcProtocol)
|
|
&& ((MDNS_SERVICE_PROTOCOL_LENGTH - 1) != os_strlen(p_pcProtocol)) && (p_u16Port))
|
|
{
|
|
if (!_findService((p_pcName ?: m_pcHostname), p_pcService,
|
|
p_pcProtocol)) // Not already used
|
|
{
|
|
if (0
|
|
!= (hResult = (hMDNSService)_allocService(p_pcName, p_pcService, p_pcProtocol,
|
|
p_u16Port)))
|
|
{
|
|
// Start probing
|
|
((stcMDNSService*)hResult)->m_ProbeInformation.m_ProbingStatus
|
|
= ProbingStatus_ReadyToStart;
|
|
}
|
|
}
|
|
} // else: bad arguments
|
|
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(
|
|
PSTR("[MDNSResponder] addService: %s to add '%s.%s.%s'!\n"),
|
|
(hResult ? "Succeeded" : "FAILED"), (p_pcName ?: "-"), p_pcService, p_pcProtocol););
|
|
DEBUG_EX_ERR(if (!hResult) {
|
|
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addService: FAILED to add '%s.%s.%s'!\n"),
|
|
(p_pcName ?: "-"), p_pcService, p_pcProtocol);
|
|
});
|
|
return hResult;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::removeService
|
|
|
|
Unanounce a service (by sending a goodbye message) and remove it
|
|
from the MDNS responder
|
|
|
|
*/
|
|
bool MDNSResponder::removeService(const MDNSResponder::hMDNSService p_hService)
|
|
{
|
|
stcMDNSService* pService = 0;
|
|
bool bResult = (((pService = _findService(p_hService)))
|
|
&& (_announceService(*pService, false)) && (_releaseService(pService)));
|
|
DEBUG_EX_ERR(if (!bResult) {
|
|
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeService: FAILED!\n"));
|
|
});
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::removeService
|
|
*/
|
|
bool MDNSResponder::removeService(const char* p_pcName, const char* p_pcService,
|
|
const char* p_pcProtocol)
|
|
{
|
|
return removeService(
|
|
(hMDNSService)_findService((p_pcName ?: m_pcHostname), p_pcService, p_pcProtocol));
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addService (LEGACY)
|
|
*/
|
|
bool MDNSResponder::addService(const String& p_strService, const String& p_strProtocol,
|
|
uint16_t p_u16Port)
|
|
{
|
|
return (
|
|
0 != addService(m_pcHostname, p_strService.c_str(), p_strProtocol.c_str(), p_u16Port));
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::setServiceName
|
|
*/
|
|
bool MDNSResponder::setServiceName(const MDNSResponder::hMDNSService p_hService,
|
|
const char* p_pcInstanceName)
|
|
{
|
|
stcMDNSService* pService = 0;
|
|
bool bResult
|
|
= (((!p_pcInstanceName) || (MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcInstanceName)))
|
|
&& ((pService = _findService(p_hService))) && (pService->setName(p_pcInstanceName))
|
|
&& ((pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart)));
|
|
DEBUG_EX_ERR(if (!bResult) {
|
|
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setServiceName: FAILED for '%s'!\n"),
|
|
(p_pcInstanceName ?: "-"));
|
|
});
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
SERVICE TXT
|
|
*/
|
|
|
|
/*
|
|
MDNSResponder::addServiceTxt
|
|
|
|
Add a static service TXT item ('Key'='Value') to a service.
|
|
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
const char* p_pcValue)
|
|
{
|
|
hMDNSTxt hTxt = 0;
|
|
stcMDNSService* pService = _findService(p_hService);
|
|
if (pService)
|
|
{
|
|
hTxt = (hMDNSTxt)_addServiceTxt(pService, p_pcKey, p_pcValue, false);
|
|
}
|
|
DEBUG_EX_ERR(if (!hTxt) {
|
|
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addServiceTxt: FAILED for '%s=%s'!\n"),
|
|
(p_pcKey ?: "-"), (p_pcValue ?: "-"));
|
|
});
|
|
return hTxt;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addServiceTxt (uint32_t)
|
|
|
|
Formats: http://www.cplusplus.com/reference/cstdio/printf/
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
uint32_t p_u32Value)
|
|
{
|
|
char acBuffer[32];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%u", p_u32Value);
|
|
|
|
return addServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addServiceTxt (uint16_t)
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
uint16_t p_u16Value)
|
|
{
|
|
char acBuffer[16];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%hu", p_u16Value);
|
|
|
|
return addServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addServiceTxt (uint8_t)
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
uint8_t p_u8Value)
|
|
{
|
|
char acBuffer[8];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%hhu", p_u8Value);
|
|
|
|
return addServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addServiceTxt (int32_t)
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
int32_t p_i32Value)
|
|
{
|
|
char acBuffer[32];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%i", p_i32Value);
|
|
|
|
return addServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addServiceTxt (int16_t)
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
int16_t p_i16Value)
|
|
{
|
|
char acBuffer[16];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%hi", p_i16Value);
|
|
|
|
return addServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addServiceTxt (int8_t)
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
int8_t p_i8Value)
|
|
{
|
|
char acBuffer[8];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%hhi", p_i8Value);
|
|
|
|
return addServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::removeServiceTxt
|
|
|
|
Remove a static service TXT item from a service.
|
|
*/
|
|
bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hService,
|
|
const MDNSResponder::hMDNSTxt p_hTxt)
|
|
{
|
|
bool bResult = false;
|
|
|
|
stcMDNSService* pService = _findService(p_hService);
|
|
if (pService)
|
|
{
|
|
stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_hTxt);
|
|
if (pTxt)
|
|
{
|
|
bResult = _releaseServiceTxt(pService, pTxt);
|
|
}
|
|
}
|
|
DEBUG_EX_ERR(if (!bResult) {
|
|
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceTxt: FAILED!\n"));
|
|
});
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::removeServiceTxt
|
|
*/
|
|
bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hService,
|
|
const char* p_pcKey)
|
|
{
|
|
bool bResult = false;
|
|
|
|
stcMDNSService* pService = _findService(p_hService);
|
|
if (pService)
|
|
{
|
|
stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_pcKey);
|
|
if (pTxt)
|
|
{
|
|
bResult = _releaseServiceTxt(pService, pTxt);
|
|
}
|
|
}
|
|
DEBUG_EX_ERR(if (!bResult) {
|
|
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceTxt: FAILED for '%s'!\n"),
|
|
(p_pcKey ?: "-"));
|
|
});
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::removeServiceTxt
|
|
*/
|
|
bool MDNSResponder::removeServiceTxt(const char* p_pcName, const char* p_pcService,
|
|
const char* p_pcProtocol, const char* p_pcKey)
|
|
{
|
|
bool bResult = false;
|
|
|
|
stcMDNSService* pService
|
|
= _findService((p_pcName ?: m_pcHostname), p_pcService, p_pcProtocol);
|
|
if (pService)
|
|
{
|
|
stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_pcKey);
|
|
if (pTxt)
|
|
{
|
|
bResult = _releaseServiceTxt(pService, pTxt);
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addServiceTxt (LEGACY)
|
|
*/
|
|
bool MDNSResponder::addServiceTxt(const char* p_pcService, const char* p_pcProtocol,
|
|
const char* p_pcKey, const char* p_pcValue)
|
|
{
|
|
return (0
|
|
!= _addServiceTxt(_findService(m_pcHostname, p_pcService, p_pcProtocol), p_pcKey,
|
|
p_pcValue, false));
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addServiceTxt (LEGACY)
|
|
*/
|
|
bool MDNSResponder::addServiceTxt(const String& p_strService, const String& p_strProtocol,
|
|
const String& p_strKey, const String& p_strValue)
|
|
{
|
|
return (0
|
|
!= _addServiceTxt(
|
|
_findService(m_pcHostname, p_strService.c_str(), p_strProtocol.c_str()),
|
|
p_strKey.c_str(), p_strValue.c_str(), false));
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::setDynamicServiceTxtCallback (global)
|
|
|
|
Set a global callback for dynamic service TXT items. The callback is called, whenever
|
|
service TXT items are needed.
|
|
|
|
*/
|
|
bool MDNSResponder::setDynamicServiceTxtCallback(
|
|
MDNSResponder::MDNSDynamicServiceTxtCallbackFunc p_fnCallback)
|
|
{
|
|
m_fnServiceTxtCallback = p_fnCallback;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::setDynamicServiceTxtCallback (service specific)
|
|
|
|
Set a service specific callback for dynamic service TXT items. The callback is called,
|
|
whenever service TXT items are needed for the given service.
|
|
|
|
*/
|
|
bool MDNSResponder::setDynamicServiceTxtCallback(
|
|
MDNSResponder::hMDNSService p_hService,
|
|
MDNSResponder::MDNSDynamicServiceTxtCallbackFunc p_fnCallback)
|
|
{
|
|
bool bResult = false;
|
|
|
|
stcMDNSService* pService = _findService(p_hService);
|
|
if (pService)
|
|
{
|
|
pService->m_fnTxtCallback = p_fnCallback;
|
|
|
|
bResult = true;
|
|
}
|
|
DEBUG_EX_ERR(if (!bResult) {
|
|
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setDynamicServiceTxtCallback: FAILED!\n"));
|
|
});
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addDynamicServiceTxt
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
const char* p_pcValue)
|
|
{
|
|
// DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addDynamicServiceTxt
|
|
// (%s=%s)\n"), p_pcKey, p_pcValue););
|
|
|
|
hMDNSTxt hTxt = 0;
|
|
|
|
stcMDNSService* pService = _findService(p_hService);
|
|
if (pService)
|
|
{
|
|
hTxt = _addServiceTxt(pService, p_pcKey, p_pcValue, true);
|
|
}
|
|
DEBUG_EX_ERR(if (!hTxt) {
|
|
DEBUG_OUTPUT.printf_P(
|
|
PSTR("[MDNSResponder] addDynamicServiceTxt: FAILED for '%s=%s'!\n"),
|
|
(p_pcKey ?: "-"), (p_pcValue ?: "-"));
|
|
});
|
|
return hTxt;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addDynamicServiceTxt (uint32_t)
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
uint32_t p_u32Value)
|
|
{
|
|
char acBuffer[32];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%u", p_u32Value);
|
|
|
|
return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addDynamicServiceTxt (uint16_t)
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
uint16_t p_u16Value)
|
|
{
|
|
char acBuffer[16];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%hu", p_u16Value);
|
|
|
|
return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addDynamicServiceTxt (uint8_t)
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
uint8_t p_u8Value)
|
|
{
|
|
char acBuffer[8];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%hhu", p_u8Value);
|
|
|
|
return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addDynamicServiceTxt (int32_t)
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
int32_t p_i32Value)
|
|
{
|
|
char acBuffer[32];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%i", p_i32Value);
|
|
|
|
return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addDynamicServiceTxt (int16_t)
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
int16_t p_i16Value)
|
|
{
|
|
char acBuffer[16];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%hi", p_i16Value);
|
|
|
|
return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::addDynamicServiceTxt (int8_t)
|
|
*/
|
|
MDNSResponder::hMDNSTxt
|
|
MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, const char* p_pcKey,
|
|
int8_t p_i8Value)
|
|
{
|
|
char acBuffer[8];
|
|
*acBuffer = 0;
|
|
sprintf(acBuffer, "%hhi", p_i8Value);
|
|
|
|
return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer);
|
|
}
|
|
|
|
/**
|
|
STATIC SERVICE QUERY (LEGACY)
|
|
*/
|
|
|
|
/*
|
|
MDNSResponder::queryService
|
|
|
|
Perform a (blocking) static service query.
|
|
The arrived answers can be queried by calling:
|
|
- answerHostname (or 'hostname')
|
|
- answerIP (or 'IP')
|
|
- answerPort (or 'port')
|
|
|
|
*/
|
|
uint32_t
|
|
MDNSResponder::queryService(const char* p_pcService, const char* p_pcProtocol,
|
|
const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/)
|
|
{
|
|
if (0 == m_pUDPContext)
|
|
{
|
|
// safeguard against misuse
|
|
return 0;
|
|
}
|
|
|
|
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService '%s.%s'\n"),
|
|
p_pcService, p_pcProtocol););
|
|
|
|
uint32_t u32Result = 0;
|
|
|
|
stcMDNSServiceQuery* pServiceQuery = 0;
|
|
if ((p_pcService) && (os_strlen(p_pcService)) && (p_pcProtocol) && (os_strlen(p_pcProtocol))
|
|
&& (p_u16Timeout) && (_removeLegacyServiceQuery())
|
|
&& ((pServiceQuery = _allocServiceQuery()))
|
|
&& (_buildDomainForService(p_pcService, p_pcProtocol,
|
|
pServiceQuery->m_ServiceTypeDomain)))
|
|
{
|
|
pServiceQuery->m_bLegacyQuery = true;
|
|
|
|
if (_sendMDNSServiceQuery(*pServiceQuery))
|
|
{
|
|
// Wait for answers to arrive
|
|
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(
|
|
PSTR("[MDNSResponder] queryService: Waiting %u ms for answers...\n"),
|
|
p_u16Timeout););
|
|
delay(p_u16Timeout);
|
|
|
|
// All answers should have arrived by now -> stop adding new answers
|
|
pServiceQuery->m_bAwaitingAnswers = false;
|
|
u32Result = pServiceQuery->answerCount();
|
|
}
|
|
else // FAILED to send query
|
|
{
|
|
_removeServiceQuery(pServiceQuery);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(
|
|
PSTR("[MDNSResponder] queryService: INVALID input data!\n")););
|
|
}
|
|
return u32Result;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::removeQuery
|
|
|
|
Remove the last static service query (and all answers).
|
|
|
|
*/
|
|
bool MDNSResponder::removeQuery(void)
|
|
{
|
|
return _removeLegacyServiceQuery();
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::queryService (LEGACY)
|
|
*/
|
|
uint32_t MDNSResponder::queryService(const String& p_strService, const String& p_strProtocol)
|
|
{
|
|
return queryService(p_strService.c_str(), p_strProtocol.c_str());
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::answerHostname
|
|
*/
|
|
const char* MDNSResponder::answerHostname(const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery();
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
|
|
if ((pSQAnswer) && (pSQAnswer->m_HostDomain.m_u16NameLength)
|
|
&& (!pSQAnswer->m_pcHostDomain))
|
|
{
|
|
char* pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength());
|
|
if (pcHostDomain)
|
|
{
|
|
pSQAnswer->m_HostDomain.c_str(pcHostDomain);
|
|
}
|
|
}
|
|
return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0);
|
|
}
|
|
|
|
#ifdef MDNS_IP4_SUPPORT
|
|
/*
|
|
MDNSResponder::answerIP
|
|
*/
|
|
IPAddress MDNSResponder::answerIP(const uint32_t p_u32AnswerIndex)
|
|
{
|
|
const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery();
|
|
const stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
const stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address
|
|
= (((pSQAnswer) && (pSQAnswer->m_pIP4Addresses)) ? pSQAnswer->IP4AddressAtIndex(0) : 0);
|
|
return (pIP4Address ? pIP4Address->m_IPAddress : IPAddress());
|
|
}
|
|
#endif
|
|
|
|
#ifdef MDNS_IP6_SUPPORT
|
|
/*
|
|
MDNSResponder::answerIP6
|
|
*/
|
|
IPAddress MDNSResponder::answerIP6(const uint32_t p_u32AnswerIndex)
|
|
{
|
|
const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery();
|
|
const stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
const stcMDNSServiceQuery::stcAnswer::stcIP6Address* pIP6Address
|
|
= (((pSQAnswer) && (pSQAnswer->m_pIP6Addresses)) ? pSQAnswer->IP6AddressAtIndex(0) : 0);
|
|
return (pIP6Address ? pIP6Address->m_IPAddress : IP6Address());
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
MDNSResponder::answerPort
|
|
*/
|
|
uint16_t MDNSResponder::answerPort(const uint32_t p_u32AnswerIndex)
|
|
{
|
|
const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery();
|
|
const stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
return (pSQAnswer ? pSQAnswer->m_u16Port : 0);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::hostname (LEGACY)
|
|
*/
|
|
String MDNSResponder::hostname(const uint32_t p_u32AnswerIndex)
|
|
{
|
|
return String(answerHostname(p_u32AnswerIndex));
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::IP (LEGACY)
|
|
*/
|
|
IPAddress MDNSResponder::IP(const uint32_t p_u32AnswerIndex)
|
|
{
|
|
return answerIP(p_u32AnswerIndex);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::port (LEGACY)
|
|
*/
|
|
uint16_t MDNSResponder::port(const uint32_t p_u32AnswerIndex)
|
|
{
|
|
return answerPort(p_u32AnswerIndex);
|
|
}
|
|
|
|
/**
|
|
DYNAMIC SERVICE QUERY
|
|
*/
|
|
|
|
/*
|
|
MDNSResponder::installServiceQuery
|
|
|
|
Add a dynamic service query and a corresponding callback to the MDNS responder.
|
|
The callback will be called for every answer update.
|
|
The answers can also be queried by calling:
|
|
- answerServiceDomain
|
|
- answerHostDomain
|
|
- answerIP4Address/answerIP6Address
|
|
- answerPort
|
|
- answerTxts
|
|
|
|
*/
|
|
MDNSResponder::hMDNSServiceQuery
|
|
MDNSResponder::installServiceQuery(const char* p_pcService, const char* p_pcProtocol,
|
|
MDNSResponder::MDNSServiceQueryCallbackFunc p_fnCallback)
|
|
{
|
|
hMDNSServiceQuery hResult = 0;
|
|
|
|
stcMDNSServiceQuery* pServiceQuery = 0;
|
|
if ((p_pcService) && (os_strlen(p_pcService)) && (p_pcProtocol) && (os_strlen(p_pcProtocol))
|
|
&& (p_fnCallback) && ((pServiceQuery = _allocServiceQuery()))
|
|
&& (_buildDomainForService(p_pcService, p_pcProtocol,
|
|
pServiceQuery->m_ServiceTypeDomain)))
|
|
{
|
|
pServiceQuery->m_fnCallback = p_fnCallback;
|
|
pServiceQuery->m_bLegacyQuery = false;
|
|
|
|
if (_sendMDNSServiceQuery(*pServiceQuery))
|
|
{
|
|
pServiceQuery->m_u8SentCount = 1;
|
|
pServiceQuery->m_ResendTimeout.reset(MDNS_DYNAMIC_QUERY_RESEND_DELAY);
|
|
|
|
hResult = (hMDNSServiceQuery)pServiceQuery;
|
|
}
|
|
else
|
|
{
|
|
_removeServiceQuery(pServiceQuery);
|
|
}
|
|
}
|
|
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(
|
|
PSTR("[MDNSResponder] installServiceQuery: %s for '%s.%s'!\n\n"),
|
|
(hResult ? "Succeeded" : "FAILED"), (p_pcService ?: "-"), (p_pcProtocol ?: "-")););
|
|
DEBUG_EX_ERR(if (!hResult) {
|
|
DEBUG_OUTPUT.printf_P(
|
|
PSTR("[MDNSResponder] installServiceQuery: FAILED for '%s.%s'!\n\n"),
|
|
(p_pcService ?: "-"), (p_pcProtocol ?: "-"));
|
|
});
|
|
return hResult;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::removeServiceQuery
|
|
|
|
Remove a dynamic service query (and all collected answers) from the MDNS responder
|
|
|
|
*/
|
|
bool MDNSResponder::removeServiceQuery(MDNSResponder::hMDNSServiceQuery p_hServiceQuery)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = 0;
|
|
bool bResult = (((pServiceQuery = _findServiceQuery(p_hServiceQuery)))
|
|
&& (_removeServiceQuery(pServiceQuery)));
|
|
DEBUG_EX_ERR(if (!bResult) {
|
|
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceQuery: FAILED!\n"));
|
|
});
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::answerCount
|
|
*/
|
|
uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
return (pServiceQuery ? pServiceQuery->answerCount() : 0);
|
|
}
|
|
|
|
std::vector<MDNSResponder::MDNSServiceInfo>
|
|
MDNSResponder::answerInfo(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery)
|
|
{
|
|
std::vector<MDNSResponder::MDNSServiceInfo> tempVector;
|
|
for (uint32_t i = 0; i < answerCount(p_hServiceQuery); i++)
|
|
{
|
|
tempVector.emplace_back(*this, p_hServiceQuery, i);
|
|
}
|
|
return tempVector;
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::answerServiceDomain
|
|
|
|
Returns the domain for the given service.
|
|
If not already existing, the string is allocated, filled and attached to the answer.
|
|
|
|
*/
|
|
const char*
|
|
MDNSResponder::answerServiceDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
// Fill m_pcServiceDomain (if not already done)
|
|
if ((pSQAnswer) && (pSQAnswer->m_ServiceDomain.m_u16NameLength)
|
|
&& (!pSQAnswer->m_pcServiceDomain))
|
|
{
|
|
pSQAnswer->m_pcServiceDomain
|
|
= pSQAnswer->allocServiceDomain(pSQAnswer->m_ServiceDomain.c_strLength());
|
|
if (pSQAnswer->m_pcServiceDomain)
|
|
{
|
|
pSQAnswer->m_ServiceDomain.c_str(pSQAnswer->m_pcServiceDomain);
|
|
}
|
|
}
|
|
return (pSQAnswer ? pSQAnswer->m_pcServiceDomain : 0);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::hasAnswerHostDomain
|
|
*/
|
|
bool MDNSResponder::hasAnswerHostDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
return ((pSQAnswer)
|
|
&& (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostDomainAndPort));
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::answerHostDomain
|
|
|
|
Returns the host domain for the given service.
|
|
If not already existing, the string is allocated, filled and attached to the answer.
|
|
|
|
*/
|
|
const char*
|
|
MDNSResponder::answerHostDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
// Fill m_pcHostDomain (if not already done)
|
|
if ((pSQAnswer) && (pSQAnswer->m_HostDomain.m_u16NameLength)
|
|
&& (!pSQAnswer->m_pcHostDomain))
|
|
{
|
|
pSQAnswer->m_pcHostDomain
|
|
= pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength());
|
|
if (pSQAnswer->m_pcHostDomain)
|
|
{
|
|
pSQAnswer->m_HostDomain.c_str(pSQAnswer->m_pcHostDomain);
|
|
}
|
|
}
|
|
return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0);
|
|
}
|
|
|
|
#ifdef MDNS_IP4_SUPPORT
|
|
/*
|
|
MDNSResponder::hasAnswerIP4Address
|
|
*/
|
|
bool MDNSResponder::hasAnswerIP4Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
return ((pSQAnswer) && (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_IP4Address));
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::answerIP4AddressCount
|
|
*/
|
|
uint32_t
|
|
MDNSResponder::answerIP4AddressCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
return (pSQAnswer ? pSQAnswer->IP4AddressCount() : 0);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::answerIP4Address
|
|
*/
|
|
IPAddress
|
|
MDNSResponder::answerIP4Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex,
|
|
const uint32_t p_u32AddressIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address
|
|
= (pSQAnswer ? pSQAnswer->IP4AddressAtIndex(p_u32AddressIndex) : 0);
|
|
return (pIP4Address ? pIP4Address->m_IPAddress : IPAddress());
|
|
}
|
|
#endif
|
|
|
|
#ifdef MDNS_IP6_SUPPORT
|
|
/*
|
|
MDNSResponder::hasAnswerIP6Address
|
|
*/
|
|
bool MDNSResponder::hasAnswerIP6Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
return ((pSQAnswer)
|
|
&& (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostIP6Address));
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::answerIP6AddressCount
|
|
*/
|
|
uint32_t
|
|
MDNSResponder::answerIP6AddressCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
return (pSQAnswer ? pSQAnswer->IP6AddressCount() : 0);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::answerIP6Address
|
|
*/
|
|
IPAddress
|
|
MDNSResponder::answerIP6Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex,
|
|
const uint32_t p_u32AddressIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
stcMDNSServiceQuery::stcAnswer::stcIP6Address* pIP6Address
|
|
= (pSQAnswer ? pSQAnswer->IP6AddressAtIndex(p_u32AddressIndex) : 0);
|
|
return (pIP6Address ? pIP6Address->m_IPAddress : IPAddress());
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
MDNSResponder::hasAnswerPort
|
|
*/
|
|
bool MDNSResponder::hasAnswerPort(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
return ((pSQAnswer)
|
|
&& (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostDomainAndPort));
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::answerPort
|
|
*/
|
|
uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
return (pSQAnswer ? pSQAnswer->m_u16Port : 0);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::hasAnswerTxts
|
|
*/
|
|
bool MDNSResponder::hasAnswerTxts(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
return ((pSQAnswer) && (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_Txts));
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::answerTxts
|
|
|
|
Returns all TXT items for the given service as a ';'-separated string.
|
|
If not already existing; the string is allocated, filled and attached to the answer.
|
|
|
|
*/
|
|
const char* MDNSResponder::answerTxts(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery,
|
|
const uint32_t p_u32AnswerIndex)
|
|
{
|
|
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
|
|
stcMDNSServiceQuery::stcAnswer* pSQAnswer
|
|
= (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
|
|
// Fill m_pcTxts (if not already done)
|
|
if ((pSQAnswer) && (pSQAnswer->m_Txts.m_pTxts) && (!pSQAnswer->m_pcTxts))
|
|
{
|
|
pSQAnswer->m_pcTxts = pSQAnswer->allocTxts(pSQAnswer->m_Txts.c_strLength());
|
|
if (pSQAnswer->m_pcTxts)
|
|
{
|
|
pSQAnswer->m_Txts.c_str(pSQAnswer->m_pcTxts);
|
|
}
|
|
}
|
|
return (pSQAnswer ? pSQAnswer->m_pcTxts : 0);
|
|
}
|
|
|
|
/*
|
|
PROBING
|
|
*/
|
|
|
|
/*
|
|
MDNSResponder::setProbeResultCallback
|
|
|
|
Set a global callback for probe results. The callback is called, when probing
|
|
for the host domain (or a service domain, without specific probe result callback)
|
|
fails or succeeds.
|
|
In the case of failure, the domain name should be changed via 'setHostname' or
|
|
'setServiceName'. When succeeded, the host or service domain will be announced by the MDNS
|
|
responder.
|
|
|
|
*/
|
|
bool MDNSResponder::setHostProbeResultCallback(MDNSResponder::MDNSHostProbeFn p_fnCallback)
|
|
{
|
|
m_HostProbeInformation.m_fnHostProbeResultCallback = p_fnCallback;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MDNSResponder::setHostProbeResultCallback(MDNSHostProbeFn1 pfn)
|
|
{
|
|
using namespace std::placeholders;
|
|
return setHostProbeResultCallback(
|
|
[this, pfn](const char* p_pcDomainName, bool p_bProbeResult)
|
|
{
|
|
pfn(*this, p_pcDomainName, p_bProbeResult);
|
|
});
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::setServiceProbeResultCallback
|
|
|
|
Set a service specific callback for probe results. The callback is called, when probing
|
|
for the service domain fails or succeeds.
|
|
In the case of failure, the service name should be changed via 'setServiceName'.
|
|
When succeeded, the service domain will be announced by the MDNS responder.
|
|
|
|
*/
|
|
bool
|
|
MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService,
|
|
MDNSResponder::MDNSServiceProbeFn p_fnCallback)
|
|
{
|
|
bool bResult = false;
|
|
|
|
stcMDNSService* pService = _findService(p_hService);
|
|
if (pService)
|
|
{
|
|
pService->m_ProbeInformation.m_fnServiceProbeResultCallback = p_fnCallback;
|
|
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
bool
|
|
MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService,
|
|
MDNSResponder::MDNSServiceProbeFn1 p_fnCallback)
|
|
{
|
|
using namespace std::placeholders;
|
|
return setServiceProbeResultCallback(
|
|
p_hService,
|
|
[this, p_fnCallback](const char* p_pcServiceName, const hMDNSService p_hMDNSService,
|
|
bool p_bProbeResult)
|
|
{
|
|
p_fnCallback(*this, p_pcServiceName, p_hMDNSService, p_bProbeResult);
|
|
});
|
|
}
|
|
|
|
/*
|
|
MISC
|
|
*/
|
|
|
|
/*
|
|
MDNSResponder::notifyAPChange
|
|
|
|
Should be called, whenever the AP for the MDNS responder changes.
|
|
A bit of this is caught by the event callbacks installed in the constructor.
|
|
|
|
*/
|
|
bool MDNSResponder::notifyAPChange(void)
|
|
{
|
|
return _restart();
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::update
|
|
|
|
Should be called in every 'loop'.
|
|
|
|
*/
|
|
bool MDNSResponder::update(void)
|
|
{
|
|
return _process(true);
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::announce
|
|
|
|
Should be called, if the 'configuration' changes. Mainly this will be changes in the TXT
|
|
items...
|
|
*/
|
|
bool MDNSResponder::announce(void)
|
|
{
|
|
return (_announce(true, true));
|
|
}
|
|
|
|
/*
|
|
MDNSResponder::enableArduino
|
|
|
|
Enable the OTA update service.
|
|
|
|
*/
|
|
MDNSResponder::hMDNSService MDNSResponder::enableArduino(uint16_t p_u16Port,
|
|
bool p_bAuthUpload /*= false*/)
|
|
{
|
|
hMDNSService hService = addService(0, "arduino", "tcp", p_u16Port);
|
|
if (hService)
|
|
{
|
|
if ((!addServiceTxt(hService, "tcp_check", "no"))
|
|
|| (!addServiceTxt(hService, "ssh_upload", "no"))
|
|
|| (!addServiceTxt(hService, "board", ARDUINO_BOARD_ID))
|
|
|| (!addServiceTxt(hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no")))
|
|
{
|
|
removeService(hService);
|
|
hService = 0;
|
|
}
|
|
}
|
|
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_IP4_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_IP4_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
|
|
|
|
} // namespace esp8266
|