1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-22 21:23:07 +03:00
Allman-astyler eea9999dc5 Revert "Allman now (#6080)" (#6090)
This reverts commit 98125f88605cd7e46e9be4e1b3ad0600dd5d2b51.
2019-05-14 00:09:54 +02:00

1165 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 "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
}
/*
* 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) {
bool bResult = false;
if (0 == m_pUDPContext) {
if (_setHostname(p_pcHostname)) {
m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP& pEvent) {
(void) pEvent;
// Ensure that _restart() runs in USER context
schedule_function(std::bind(&MDNSResponder::_restart, this));
});
m_DisconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected& pEvent) {
(void) pEvent;
// Ensure that _restart() runs in USER context
schedule_function(std::bind(&MDNSResponder::_restart, this));
});
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::begin (LEGACY)
*/
bool MDNSResponder::begin(const char* p_pcHostname,
IPAddress p_IPAddress,
uint32_t p_u32TTL /*= 120*/) {
(void) p_IPAddress;
(void) p_u32TTL;
return begin(p_pcHostname);
}
/*
* MDNSResponder::close
*
* Ends the MDNS responder.
* Announced services are unannounced (by multicasting a goodbye message)
*
*/
bool MDNSResponder::close(void) {
m_GotIPHandler.reset(); // reset WiFi event callbacks.
m_DisconnectedHandler.reset();
_announce(false, true);
_resetProbeStatus(false); // Stop probing
_releaseServiceQueries();
_releaseUDPContext();
_releaseHostname();
return true;
}
/*
* 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(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(String p_strService,
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(String p_strService,
String p_strProtocol,
String p_strKey,
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*/) {
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"), p_pcService, p_pcProtocol););
}
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(String p_strService,
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(std::bind(pfn, std::ref(*this), _1, _2));
}
/*
* 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, std::bind(p_fnCallback, std::ref(*this), _1, _2, _3));
}
/*
* 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