mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
1382 lines
41 KiB
C++
1382 lines
41 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 "LEAmDNS_Priv.h"
|
|
|
|
|
|
namespace esp8266
|
|
{
|
|
|
|
/*
|
|
LEAmDNS
|
|
*/
|
|
namespace MDNSImplementation
|
|
{
|
|
|
|
/**
|
|
STRINGIZE
|
|
*/
|
|
#ifndef STRINGIZE
|
|
#define STRINGIZE(x) #x
|
|
#endif
|
|
#ifndef STRINGIZE_VALUE_OF
|
|
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
|
|
#endif
|
|
|
|
|
|
/**
|
|
INTERFACE
|
|
*/
|
|
|
|
/**
|
|
MDNSResponder::MDNSResponder
|
|
*/
|
|
MDNSResponder::MDNSResponder(void)
|
|
: m_pServices(0),
|
|
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)
|
|
{
|
|
}
|
|
|
|
/*
|
|
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)
|
|
{
|
|
|
|
(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();
|
|
}
|
|
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;
|
|
}
|
|
|
|
/*
|
|
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)
|
|
{
|
|
m_GotIPHandler.reset(); // reset WiFi event callbacks.
|
|
m_DisconnectedHandler.reset();
|
|
|
|
_announce(false, true);
|
|
_resetProbeStatus(false); // Stop probing
|
|
_releaseServiceQueries();
|
|
_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 alloced, 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)
|
|
failes or succeedes.
|
|
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 failes or succeedes.
|
|
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)
|
|
{
|
|
|
|
if (m_bPassivModeEnabled)
|
|
{
|
|
m_bPassivModeEnabled = false;
|
|
}
|
|
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", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) ||
|
|
(!addServiceTxt(hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no")))
|
|
{
|
|
|
|
removeService(hService);
|
|
hService = 0;
|
|
}
|
|
}
|
|
return hService;
|
|
}
|
|
|
|
|
|
} //namespace MDNSImplementation
|
|
|
|
} //namespace esp8266
|
|
|
|
|