1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-22 21:23:07 +03:00
david gauchard f9009b8a5e
mDNS: restriction to a single interface (#6224)
Default interface is STA (or AP if available and STA is unavailable).
An interface can also be specified in ::begin() by its IP address.
MDNS will not cross interfaces (there is currently no notion of "bridged interfaces")

Multiple instances should be working, this is not tested in this commit.
2019-06-27 09:30:12 +02:00

1404 lines
58 KiB
C++

/*
* LEAmDNS.h
* (c) 2018, LaborEtArs
*
* Version 0.9 beta
*
* Some notes (from LaborEtArs, 2018):
* Essentially, this is an rewrite of the original EPS8266 Multicast DNS code (ESP8266mDNS).
* The target of this rewrite was to keep the existing interface as stable as possible while
* adding and extending the supported set of mDNS features.
* A lot of the additions were basicly taken from Erik Ekman's lwIP mdns app code.
*
* Supported mDNS features (in some cases somewhat limited):
* - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service
* - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented
* - Probing host and service domains for uniqueness in the local network
* - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak)
* - Announcing available services after successful probing
* - Using fixed service TXT items or
* - Using dynamic service TXT items for presented services (via callback)
* - Remove services (and un-announcing them to the observers by sending goodbye-messages)
* - Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period)
* - Dynamic queries for DNS-SD services with cached and updated answers and user notifications
*
*
* Usage:
* In most cases, this implementation should work as a 'drop-in' replacement for the original
* ESP8266 Multicast DNS code. Adjustments to the existing code would only be needed, if some
* of the new features should be used.
*
* For presenting services:
* In 'setup()':
* Install a callback for the probing of host (and service) domains via 'MDNS.setProbeResultCallback(probeResultCallback, &userData);'
* Register DNS-SD services with 'MDNSResponder::hMDNSService hService = MDNS.addService("MyESP", "http", "tcp", 5000);'
* (Install additional callbacks for the probing of these service domains via 'MDNS.setServiceProbeResultCallback(hService, probeResultCallback, &userData);')
* Add service TXT items with 'MDNS.addServiceTxt(hService, "c#", "1");' or by installing a service TXT callback
* using 'MDNS.setDynamicServiceTxtCallback(dynamicServiceTxtCallback, &userData);' or service specific
* 'MDNS.setDynamicServiceTxtCallback(hService, dynamicServiceTxtCallback, &userData);'
* Call MDNS.begin("MyHostname");
*
* In 'probeResultCallback(MDNSResponder* p_MDNSResponder, const char* p_pcDomain, MDNSResponder:hMDNSService p_hService, bool p_bProbeResult, void* p_pUserdata)':
* Check the probe result and update the host or service domain name if the probe failed
*
* In 'dynamicServiceTxtCallback(MDNSResponder* p_MDNSResponder, const hMDNSService p_hService, void* p_pUserdata)':
* Add dynamic TXT items by calling 'MDNS.addDynamicServiceTxt(p_hService, "c#", "1");'
*
* In loop():
* Call 'MDNS.update();'
*
*
* For querying services:
* Static:
* Call 'uint32_t u32AnswerCount = MDNS.queryService("http", "tcp");'
* Iterate answers by: 'for (uint32_t u=0; u<u32AnswerCount; ++u) { const char* pHostname = MDNS.answerHostname(u); }'
* You should call MDNS.removeQuery() sometimes later (when the answers are nott needed anymore)
*
* Dynamic:
* Install a dynamic query by calling 'DNSResponder::hMDNSServiceQuery hServiceQuery = MDNS.installServiceQuery("http", "tcp", serviceQueryCallback, &userData);'
* The callback 'serviceQueryCallback(MDNSResponder* p_MDNSResponder, const hMDNSServiceQuery p_hServiceQuery, uint32_t p_u32AnswerIndex,
* enuServiceQueryAnswerType p_ServiceQueryAnswerType, bool p_bSetContent, void* p_pUserdata)'
* is called for any change in the answer set.
* Call 'MDNS.removeServiceQuery(hServiceQuery);' when the answers are not needed anymore
*
*
* Reference:
* Used mDNS messages:
* A (0x01): eg. esp8266.local A OP TTL 123.456.789.012
* AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90
* PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local
* PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local
* PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local
* PTR (0x0C, IP6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local
* SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local
* TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1
*
* Some NOT used message types:
* OPT (0x29): eDNS
* NSEC (0x2F): DNSSEC
*
*
* 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.
*
*/
#ifndef MDNS_H
#define MDNS_H
#include <functional> // for UdpContext.h
#include "WiFiUdp.h"
#include "lwip/udp.h"
#include "debug.h"
#include "include/UdpContext.h"
#include <limits>
#include <PolledTimeout.h>
#include <map>
#include "ESP8266WiFi.h"
namespace esp8266 {
/**
* LEAmDNS
*/
namespace MDNSImplementation {
//this should be defined at build time
#ifndef ARDUINO_BOARD
#define ARDUINO_BOARD "generic"
#endif
#define MDNS_IP4_SUPPORT
//#define MDNS_IP6_SUPPORT
#ifdef MDNS_IP4_SUPPORT
#define MDNS_IP4_SIZE 4
#endif
#ifdef MDNS_IP6_SUPPORT
#define MDNS_IP6_SIZE 16
#endif
/*
* Maximum length for all service txts for one service
*/
#define MDNS_SERVICE_TXT_MAXLENGTH 1300
/*
* Maximum length for a full domain name eg. MyESP._http._tcp.local
*/
#define MDNS_DOMAIN_MAXLENGTH 256
/*
* Maximum length of on label in a domain name (length info fits into 6 bits)
*/
#define MDNS_DOMAIN_LABEL_MAXLENGTH 63
/*
* Maximum length of a service name eg. http
*/
#define MDNS_SERVICE_NAME_LENGTH 15
/*
* Maximum length of a service protocol name eg. tcp
*/
#define MDNS_SERVICE_PROTOCOL_LENGTH 3
/*
* Default timeout for static service queries
*/
#define MDNS_QUERYSERVICES_WAIT_TIME 1000
/**
* MDNSResponder
*/
class MDNSResponder {
public:
/* INTERFACE */
MDNSResponder(void);
virtual ~MDNSResponder(void);
// Start the MDNS responder by setting the default hostname
// Later call MDNS::update() in every 'loop' to run the process loop
// (probing, announcing, responding, ...)
// if interfaceAddress is not specified, default interface is STA, or AP when STA is not set
bool begin(const char* p_pcHostname, const IPAddress& p_IPAddress = INADDR_ANY, uint32_t p_u32TTL = 120 /*ignored*/);
bool begin(const String& p_strHostname, const IPAddress& p_IPAddress = INADDR_ANY, uint32_t p_u32TTL = 120 /*ignored*/) {return begin(p_strHostname.c_str(), p_IPAddress, p_u32TTL);}
// Finish MDNS processing
bool close(void);
// for esp32 compatability
bool end(void);
// Change hostname (probing is restarted)
bool setHostname(const char* p_pcHostname);
// for compatibility...
bool setHostname(String p_strHostname);
/**
* hMDNSService (opaque handle to access the service)
*/
typedef const void* hMDNSService;
// Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0)
// the current hostname is used. If the hostname is changed later, the instance names for
// these 'auto-named' services are changed to the new name also (and probing is restarted).
// The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given.
hMDNSService addService(const char* p_pcName,
const char* p_pcService,
const char* p_pcProtocol,
uint16_t p_u16Port);
// Removes a service from the MDNS responder
bool removeService(const hMDNSService p_hService);
bool removeService(const char* p_pcInstanceName,
const char* p_pcServiceName,
const char* p_pcProtocol);
// for compatibility...
bool addService(String p_strServiceName,
String p_strProtocol,
uint16_t p_u16Port);
// Change the services instance name (and restart probing).
bool setServiceName(const hMDNSService p_hService,
const char* p_pcInstanceName);
//for compatibility
//Warning: this has the side effect of changing the hostname.
//TODO: implement instancename different from hostname
void setInstanceName(const char* p_pcHostname) {setHostname(p_pcHostname);}
// for esp32 compatibilty
void setInstanceName(const String& s_pcHostname) {setInstanceName(s_pcHostname.c_str());}
/**
* hMDNSTxt (opaque handle to access the TXT items)
*/
typedef void* hMDNSTxt;
// Add a (static) MDNS TXT item ('key' = 'value') to the service
hMDNSTxt addServiceTxt(const hMDNSService p_hService,
const char* p_pcKey,
const char* p_pcValue);
hMDNSTxt addServiceTxt(const hMDNSService p_hService,
const char* p_pcKey,
uint32_t p_u32Value);
hMDNSTxt addServiceTxt(const hMDNSService p_hService,
const char* p_pcKey,
uint16_t p_u16Value);
hMDNSTxt addServiceTxt(const hMDNSService p_hService,
const char* p_pcKey,
uint8_t p_u8Value);
hMDNSTxt addServiceTxt(const hMDNSService p_hService,
const char* p_pcKey,
int32_t p_i32Value);
hMDNSTxt addServiceTxt(const hMDNSService p_hService,
const char* p_pcKey,
int16_t p_i16Value);
hMDNSTxt addServiceTxt(const hMDNSService p_hService,
const char* p_pcKey,
int8_t p_i8Value);
// Remove an existing (static) MDNS TXT item from the service
bool removeServiceTxt(const hMDNSService p_hService,
const hMDNSTxt p_hTxt);
bool removeServiceTxt(const hMDNSService p_hService,
const char* p_pcKey);
bool removeServiceTxt(const char* p_pcinstanceName,
const char* p_pcServiceName,
const char* p_pcProtocol,
const char* p_pcKey);
// for compatibility...
bool addServiceTxt(const char* p_pcService,
const char* p_pcProtocol,
const char* p_pcKey,
const char* p_pcValue);
bool addServiceTxt(String p_strService,
String p_strProtocol,
String p_strKey,
String p_strValue);
/**
* MDNSDynamicServiceTxtCallbackFn
* Callback function for dynamic MDNS TXT items
*/
typedef std::function<void(const hMDNSService p_hService)> MDNSDynamicServiceTxtCallbackFunc;
// Set a global callback for dynamic MDNS TXT items. The callback function is called
// every time, a TXT item is needed for one of the installed services.
bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFunc p_fnCallback);
// Set a service specific callback for dynamic MDNS TXT items. The callback function
// is called every time, a TXT item is needed for the given service.
bool setDynamicServiceTxtCallback(const hMDNSService p_hService,
MDNSDynamicServiceTxtCallbackFunc p_fnCallback);
// Add a (dynamic) MDNS TXT item ('key' = 'value') to the service
// Dynamic TXT items are removed right after one-time use. So they need to be added
// every time the value s needed (via callback).
hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService,
const char* p_pcKey,
const char* p_pcValue);
hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService,
const char* p_pcKey,
uint32_t p_u32Value);
hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService,
const char* p_pcKey,
uint16_t p_u16Value);
hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService,
const char* p_pcKey,
uint8_t p_u8Value);
hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService,
const char* p_pcKey,
int32_t p_i32Value);
hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService,
const char* p_pcKey,
int16_t p_i16Value);
hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService,
const char* p_pcKey,
int8_t p_i8Value);
// Perform a (static) service query. The function returns after p_u16Timeout milliseconds
// The answers (the number of received answers is returned) can be retrieved by calling
// - answerHostname (or hostname)
// - answerIP (or IP)
// - answerPort (or port)
uint32_t queryService(const char* p_pcService,
const char* p_pcProtocol,
const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME);
bool removeQuery(void);
// for compatibility...
uint32_t queryService(String p_strService,
String p_strProtocol);
const char* answerHostname(const uint32_t p_u32AnswerIndex);
IPAddress answerIP(const uint32_t p_u32AnswerIndex);
uint16_t answerPort(const uint32_t p_u32AnswerIndex);
// for compatibility...
String hostname(const uint32_t p_u32AnswerIndex);
IPAddress IP(const uint32_t p_u32AnswerIndex);
uint16_t port(const uint32_t p_u32AnswerIndex);
/**
* hMDNSServiceQuery (opaque handle to access dynamic service queries)
*/
typedef const void* hMDNSServiceQuery;
/**
* enuServiceQueryAnswerType
*/
typedef enum _enuServiceQueryAnswerType {
ServiceQueryAnswerType_ServiceDomain = (1 << 0), // Service instance name
ServiceQueryAnswerType_HostDomainAndPort = (1 << 1), // Host domain and service port
ServiceQueryAnswerType_Txts = (1 << 2), // TXT items
#ifdef MDNS_IP4_SUPPORT
ServiceQueryAnswerType_IP4Address = (1 << 3), // IP4 address
#endif
#ifdef MDNS_IP6_SUPPORT
ServiceQueryAnswerType_IP6Address = (1 << 4), // IP6 address
#endif
} enuServiceQueryAnswerType;
enum class AnswerType : uint32_t {
Unknown = 0,
ServiceDomain = ServiceQueryAnswerType_ServiceDomain,
HostDomainAndPort = ServiceQueryAnswerType_HostDomainAndPort,
Txt = ServiceQueryAnswerType_Txts,
#ifdef MDNS_IP4_SUPPORT
IP4Address = ServiceQueryAnswerType_IP4Address,
#endif
#ifdef MDNS_IP6_SUPPORT
IP6Address = ServiceQueryAnswerType_IP6Address,
#endif
};
/**
* MDNSServiceQueryCallbackFn
* Callback function for received answers for dynamic service queries
*/
struct MDNSServiceInfo; // forward declaration
typedef std::function<void(const MDNSServiceInfo& mdnsServiceInfo,
AnswerType answerType , // flag for the updated answer item
bool p_bSetContent // true: Answer component set, false: component deleted
)> MDNSServiceQueryCallbackFunc;
// Install a dynamic service query. For every received answer (part) the given callback
// function is called. The query will be updated every time, the TTL for an answer
// has timed-out.
// The answers can also be retrieved by calling
// - answerCount
// - answerServiceDomain
// - hasAnswerHostDomain/answerHostDomain
// - hasAnswerIP4Address/answerIP4Address
// - hasAnswerIP6Address/answerIP6Address
// - hasAnswerPort/answerPort
// - hasAnswerTxts/answerTxts
hMDNSServiceQuery installServiceQuery(const char* p_pcService,
const char* p_pcProtocol,
MDNSServiceQueryCallbackFunc p_fnCallback);
// Remove a dynamic service query
bool removeServiceQuery(hMDNSServiceQuery p_hServiceQuery);
uint32_t answerCount(const hMDNSServiceQuery p_hServiceQuery);
std::vector<MDNSResponder::MDNSServiceInfo> answerInfo (const MDNSResponder::hMDNSServiceQuery p_hServiceQuery);
const char* answerServiceDomain(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
bool hasAnswerHostDomain(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
const char* answerHostDomain(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
#ifdef MDNS_IP4_SUPPORT
bool hasAnswerIP4Address(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
uint32_t answerIP4AddressCount(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
IPAddress answerIP4Address(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex,
const uint32_t p_u32AddressIndex);
#endif
#ifdef MDNS_IP6_SUPPORT
bool hasAnswerIP6Address(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
uint32_t answerIP6AddressCount(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
IPAddress answerIP6Address(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex,
const uint32_t p_u32AddressIndex);
#endif
bool hasAnswerPort(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
uint16_t answerPort(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
bool hasAnswerTxts(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
// Get the TXT items as a ';'-separated string
const char* answerTxts(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
/**
* MDNSProbeResultCallbackFn
* Callback function for (host and service domain) probe results
*/
typedef std::function<void(const char* p_pcDomainName,
bool p_bProbeResult)> MDNSHostProbeFn;
typedef std::function<void(MDNSResponder& resp,
const char* p_pcDomainName,
bool p_bProbeResult)> MDNSHostProbeFn1;
typedef std::function<void(const char* p_pcServiceName,
const hMDNSService p_hMDNSService,
bool p_bProbeResult)> MDNSServiceProbeFn;
typedef std::function<void(MDNSResponder& resp,
const char* p_pcServiceName,
const hMDNSService p_hMDNSService,
bool p_bProbeResult)> MDNSServiceProbeFn1;
// Set a global callback function for host and service probe results
// The callback function is called, when the probing for the host domain
// (or a service domain, which hasn't got a service specific callback)
// Succeeds or fails.
// In case of failure, the failed domain name should be changed.
bool setHostProbeResultCallback(MDNSHostProbeFn p_fnCallback);
bool setHostProbeResultCallback(MDNSHostProbeFn1 p_fnCallback);
// Set a service specific probe result callback
bool setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService,
MDNSServiceProbeFn p_fnCallback);
bool setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService,
MDNSServiceProbeFn1 p_fnCallback);
// Application should call this whenever AP is configured/disabled
bool notifyAPChange(void);
// 'update' should be called in every 'loop' to run the MDNS processing
bool update(void);
// 'announce' can be called every time, the configuration of some service
// changes. Mainly, this would be changed content of TXT items.
bool announce(void);
// Enable OTA update
hMDNSService enableArduino(uint16_t p_u16Port,
bool p_bAuthUpload = false);
// Domain name helper
static bool indexDomain(char*& p_rpcDomain,
const char* p_pcDivider = "-",
const char* p_pcDefaultDomain = 0);
/** STRUCTS **/
public:
/**
* MDNSServiceInfo, used in application callbacks
*/
struct MDNSServiceInfo
{
MDNSServiceInfo(MDNSResponder& p_pM,MDNSResponder::hMDNSServiceQuery p_hS,uint32_t p_u32A)
: p_pMDNSResponder(p_pM),
p_hServiceQuery(p_hS),
p_u32AnswerIndex(p_u32A)
{};
struct CompareKey
{
bool operator()(char const *a, char const *b) const
{
return strcmp(a, b) < 0;
}
};
using KeyValueMap = std::map<const char*, const char*, CompareKey>;
protected:
MDNSResponder& p_pMDNSResponder;
MDNSResponder::hMDNSServiceQuery p_hServiceQuery;
uint32_t p_u32AnswerIndex;
KeyValueMap keyValueMap;
public:
const char* serviceDomain(){
return p_pMDNSResponder.answerServiceDomain(p_hServiceQuery, p_u32AnswerIndex);
};
bool hostDomainAvailable()
{
return (p_pMDNSResponder.hasAnswerHostDomain(p_hServiceQuery, p_u32AnswerIndex));
}
const char* hostDomain(){
return (hostDomainAvailable()) ?
p_pMDNSResponder.answerHostDomain(p_hServiceQuery, p_u32AnswerIndex) : nullptr;
};
bool hostPortAvailable()
{
return (p_pMDNSResponder.hasAnswerPort(p_hServiceQuery, p_u32AnswerIndex));
}
uint16_t hostPort(){
return (hostPortAvailable()) ?
p_pMDNSResponder.answerPort(p_hServiceQuery, p_u32AnswerIndex) : 0;
};
bool IP4AddressAvailable()
{
return (p_pMDNSResponder.hasAnswerIP4Address(p_hServiceQuery,p_u32AnswerIndex ));
}
std::vector<IPAddress> IP4Adresses(){
std::vector<IPAddress> internalIP;
if (IP4AddressAvailable()) {
uint16_t cntIP4Adress = p_pMDNSResponder.answerIP4AddressCount(p_hServiceQuery, p_u32AnswerIndex);
for (uint32_t u2 = 0; u2 < cntIP4Adress; ++u2) {
internalIP.emplace_back(p_pMDNSResponder.answerIP4Address(p_hServiceQuery, p_u32AnswerIndex, u2));
}
}
return internalIP;
};
bool txtAvailable()
{
return (p_pMDNSResponder.hasAnswerTxts(p_hServiceQuery, p_u32AnswerIndex));
}
const char* strKeyValue (){
return (txtAvailable()) ?
p_pMDNSResponder.answerTxts(p_hServiceQuery, p_u32AnswerIndex) : nullptr;
};
const KeyValueMap& keyValues()
{
if (txtAvailable() && keyValueMap.size() == 0)
{
for (auto kv = p_pMDNSResponder._answerKeyValue(p_hServiceQuery, p_u32AnswerIndex);kv != nullptr;kv = kv->m_pNext) {
keyValueMap.emplace(std::pair<const char*,const char*>(kv->m_pcKey,kv->m_pcValue));
}
}
return keyValueMap;
}
const char* value(const char* key)
{
char* result = nullptr;
for (stcMDNSServiceTxt* pTxt=p_pMDNSResponder._answerKeyValue(p_hServiceQuery, p_u32AnswerIndex); pTxt; pTxt=pTxt->m_pNext) {
if ((key) &&
(0 == strcmp(pTxt->m_pcKey, key))) {
result = pTxt->m_pcValue;
break;
}
}
return result;
}
};
protected:
/**
* stcMDNSServiceTxt
*/
struct stcMDNSServiceTxt {
stcMDNSServiceTxt* m_pNext;
char* m_pcKey;
char* m_pcValue;
bool m_bTemp;
stcMDNSServiceTxt(const char* p_pcKey = 0,
const char* p_pcValue = 0,
bool p_bTemp = false);
stcMDNSServiceTxt(const stcMDNSServiceTxt& p_Other);
~stcMDNSServiceTxt(void);
stcMDNSServiceTxt& operator=(const stcMDNSServiceTxt& p_Other);
bool clear(void);
char* allocKey(size_t p_stLength);
bool setKey(const char* p_pcKey,
size_t p_stLength);
bool setKey(const char* p_pcKey);
bool releaseKey(void);
char* allocValue(size_t p_stLength);
bool setValue(const char* p_pcValue,
size_t p_stLength);
bool setValue(const char* p_pcValue);
bool releaseValue(void);
bool set(const char* p_pcKey,
const char* p_pcValue,
bool p_bTemp = false);
bool update(const char* p_pcValue);
size_t length(void) const;
};
/**
* stcMDNSTxts
*/
struct stcMDNSServiceTxts {
stcMDNSServiceTxt* m_pTxts;
stcMDNSServiceTxts(void);
stcMDNSServiceTxts(const stcMDNSServiceTxts& p_Other);
~stcMDNSServiceTxts(void);
stcMDNSServiceTxts& operator=(const stcMDNSServiceTxts& p_Other);
bool clear(void);
bool add(stcMDNSServiceTxt* p_pTxt);
bool remove(stcMDNSServiceTxt* p_pTxt);
bool removeTempTxts(void);
stcMDNSServiceTxt* find(const char* p_pcKey);
const stcMDNSServiceTxt* find(const char* p_pcKey) const;
stcMDNSServiceTxt* find(const stcMDNSServiceTxt* p_pTxt);
uint16_t length(void) const;
size_t c_strLength(void) const;
bool c_str(char* p_pcBuffer);
size_t bufferLength(void) const;
bool buffer(char* p_pcBuffer);
bool compare(const stcMDNSServiceTxts& p_Other) const;
bool operator==(const stcMDNSServiceTxts& p_Other) const;
bool operator!=(const stcMDNSServiceTxts& p_Other) const;
};
/**
* enuContentFlags
*/
typedef enum _enuContentFlags {
// Host
ContentFlag_A = 0x01,
ContentFlag_PTR_IP4 = 0x02,
ContentFlag_PTR_IP6 = 0x04,
ContentFlag_AAAA = 0x08,
// Service
ContentFlag_PTR_TYPE = 0x10,
ContentFlag_PTR_NAME = 0x20,
ContentFlag_TXT = 0x40,
ContentFlag_SRV = 0x80,
} enuContentFlags;
/**
* stcMDNS_MsgHeader
*/
struct stcMDNS_MsgHeader {
uint16_t m_u16ID; // Identifier
bool m_1bQR : 1; // Query/Response flag
unsigned char m_4bOpcode : 4; // Operation code
bool m_1bAA : 1; // Authoritative Answer flag
bool m_1bTC : 1; // Truncation flag
bool m_1bRD : 1; // Recursion desired
bool m_1bRA : 1; // Recursion available
unsigned char m_3bZ : 3; // Zero
unsigned char m_4bRCode : 4; // Response code
uint16_t m_u16QDCount; // Question count
uint16_t m_u16ANCount; // Answer count
uint16_t m_u16NSCount; // Authority Record count
uint16_t m_u16ARCount; // Additional Record count
stcMDNS_MsgHeader(uint16_t p_u16ID = 0,
bool p_bQR = false,
unsigned char p_ucOpcode = 0,
bool p_bAA = false,
bool p_bTC = false,
bool p_bRD = false,
bool p_bRA = false,
unsigned char p_ucRCode = 0,
uint16_t p_u16QDCount = 0,
uint16_t p_u16ANCount = 0,
uint16_t p_u16NSCount = 0,
uint16_t p_u16ARCount = 0);
};
/**
* stcMDNS_RRDomain
*/
struct stcMDNS_RRDomain {
char m_acName[MDNS_DOMAIN_MAXLENGTH]; // Encoded domain name
uint16_t m_u16NameLength; // Length (incl. '\0')
stcMDNS_RRDomain(void);
stcMDNS_RRDomain(const stcMDNS_RRDomain& p_Other);
stcMDNS_RRDomain& operator=(const stcMDNS_RRDomain& p_Other);
bool clear(void);
bool addLabel(const char* p_pcLabel,
bool p_bPrependUnderline = false);
bool compare(const stcMDNS_RRDomain& p_Other) const;
bool operator==(const stcMDNS_RRDomain& p_Other) const;
bool operator!=(const stcMDNS_RRDomain& p_Other) const;
bool operator>(const stcMDNS_RRDomain& p_Other) const;
size_t c_strLength(void) const;
bool c_str(char* p_pcBuffer);
};
/**
* stcMDNS_RRAttributes
*/
struct stcMDNS_RRAttributes {
uint16_t m_u16Type; // Type
uint16_t m_u16Class; // Class, nearly always 'IN'
stcMDNS_RRAttributes(uint16_t p_u16Type = 0,
uint16_t p_u16Class = 1 /*DNS_RRCLASS_IN Internet*/);
stcMDNS_RRAttributes(const stcMDNS_RRAttributes& p_Other);
stcMDNS_RRAttributes& operator=(const stcMDNS_RRAttributes& p_Other);
};
/**
* stcMDNS_RRHeader
*/
struct stcMDNS_RRHeader {
stcMDNS_RRDomain m_Domain;
stcMDNS_RRAttributes m_Attributes;
stcMDNS_RRHeader(void);
stcMDNS_RRHeader(const stcMDNS_RRHeader& p_Other);
stcMDNS_RRHeader& operator=(const stcMDNS_RRHeader& p_Other);
bool clear(void);
};
/**
* stcMDNS_RRQuestion
*/
struct stcMDNS_RRQuestion {
stcMDNS_RRQuestion* m_pNext;
stcMDNS_RRHeader m_Header;
bool m_bUnicast; // Unicast reply requested
stcMDNS_RRQuestion(void);
};
/**
* enuAnswerType
*/
typedef enum _enuAnswerType {
AnswerType_A,
AnswerType_PTR,
AnswerType_TXT,
AnswerType_AAAA,
AnswerType_SRV,
AnswerType_Generic
} enuAnswerType;
/**
* stcMDNS_RRAnswer
*/
struct stcMDNS_RRAnswer {
stcMDNS_RRAnswer* m_pNext;
const enuAnswerType m_AnswerType;
stcMDNS_RRHeader m_Header;
bool m_bCacheFlush; // Cache flush command bit
uint32_t m_u32TTL; // Validity time in seconds
virtual ~stcMDNS_RRAnswer(void);
enuAnswerType answerType(void) const;
bool clear(void);
protected:
stcMDNS_RRAnswer(enuAnswerType p_AnswerType,
const stcMDNS_RRHeader& p_Header,
uint32_t p_u32TTL);
};
#ifdef MDNS_IP4_SUPPORT
/**
* stcMDNS_RRAnswerA
*/
struct stcMDNS_RRAnswerA : public stcMDNS_RRAnswer {
IPAddress m_IPAddress;
stcMDNS_RRAnswerA(const stcMDNS_RRHeader& p_Header,
uint32_t p_u32TTL);
~stcMDNS_RRAnswerA(void);
bool clear(void);
};
#endif
/**
* stcMDNS_RRAnswerPTR
*/
struct stcMDNS_RRAnswerPTR : public stcMDNS_RRAnswer {
stcMDNS_RRDomain m_PTRDomain;
stcMDNS_RRAnswerPTR(const stcMDNS_RRHeader& p_Header,
uint32_t p_u32TTL);
~stcMDNS_RRAnswerPTR(void);
bool clear(void);
};
/**
* stcMDNS_RRAnswerTXT
*/
struct stcMDNS_RRAnswerTXT : public stcMDNS_RRAnswer {
stcMDNSServiceTxts m_Txts;
stcMDNS_RRAnswerTXT(const stcMDNS_RRHeader& p_Header,
uint32_t p_u32TTL);
~stcMDNS_RRAnswerTXT(void);
bool clear(void);
};
#ifdef MDNS_IP6_SUPPORT
/**
* stcMDNS_RRAnswerAAAA
*/
struct stcMDNS_RRAnswerAAAA : public stcMDNS_RRAnswer {
//TODO: IP6Address m_IPAddress;
stcMDNS_RRAnswerAAAA(const stcMDNS_RRHeader& p_Header,
uint32_t p_u32TTL);
~stcMDNS_RRAnswerAAAA(void);
bool clear(void);
};
#endif
/**
* stcMDNS_RRAnswerSRV
*/
struct stcMDNS_RRAnswerSRV : public stcMDNS_RRAnswer {
uint16_t m_u16Priority;
uint16_t m_u16Weight;
uint16_t m_u16Port;
stcMDNS_RRDomain m_SRVDomain;
stcMDNS_RRAnswerSRV(const stcMDNS_RRHeader& p_Header,
uint32_t p_u32TTL);
~stcMDNS_RRAnswerSRV(void);
bool clear(void);
};
/**
* stcMDNS_RRAnswerGeneric
*/
struct stcMDNS_RRAnswerGeneric : public stcMDNS_RRAnswer {
uint16_t m_u16RDLength; // Length of variable answer
uint8_t* m_pu8RDData; // Offset of start of variable answer in packet
stcMDNS_RRAnswerGeneric(const stcMDNS_RRHeader& p_Header,
uint32_t p_u32TTL);
~stcMDNS_RRAnswerGeneric(void);
bool clear(void);
};
/**
* enuProbingStatus
*/
typedef enum _enuProbingStatus {
ProbingStatus_WaitingForData,
ProbingStatus_ReadyToStart,
ProbingStatus_InProgress,
ProbingStatus_Done
} enuProbingStatus;
/**
* stcProbeInformation
*/
struct stcProbeInformation {
enuProbingStatus m_ProbingStatus;
uint8_t m_u8SentCount; // Used for probes and announcements
esp8266::polledTimeout::oneShotMs m_Timeout; // Used for probes and announcements
//clsMDNSTimeFlag m_TimeFlag; // Used for probes and announcements
bool m_bConflict;
bool m_bTiebreakNeeded;
MDNSHostProbeFn m_fnHostProbeResultCallback;
MDNSServiceProbeFn m_fnServiceProbeResultCallback;
stcProbeInformation(void);
bool clear(bool p_bClearUserdata = false);
};
/**
* stcMDNSService
*/
struct stcMDNSService {
stcMDNSService* m_pNext;
char* m_pcName;
bool m_bAutoName; // Name was set automatically to hostname (if no name was supplied)
char* m_pcService;
char* m_pcProtocol;
uint16_t m_u16Port;
uint8_t m_u8ReplyMask;
stcMDNSServiceTxts m_Txts;
MDNSDynamicServiceTxtCallbackFunc m_fnTxtCallback;
stcProbeInformation m_ProbeInformation;
stcMDNSService(const char* p_pcName = 0,
const char* p_pcService = 0,
const char* p_pcProtocol = 0);
~stcMDNSService(void);
bool setName(const char* p_pcName);
bool releaseName(void);
bool setService(const char* p_pcService);
bool releaseService(void);
bool setProtocol(const char* p_pcProtocol);
bool releaseProtocol(void);
};
/**
* stcMDNSServiceQuery
*/
struct stcMDNSServiceQuery {
/**
* stcAnswer
*/
struct stcAnswer {
/**
* stcTTL
*/
struct stcTTL {
/**
* timeoutLevel_t
*/
typedef uint8_t timeoutLevel_t;
/**
* TIMEOUTLEVELs
*/
const timeoutLevel_t TIMEOUTLEVEL_UNSET = 0;
const timeoutLevel_t TIMEOUTLEVEL_BASE = 80;
const timeoutLevel_t TIMEOUTLEVEL_INTERVAL = 5;
const timeoutLevel_t TIMEOUTLEVEL_FINAL = 100;
uint32_t m_u32TTL;
esp8266::polledTimeout::oneShotMs m_TTLTimeout;
timeoutLevel_t m_timeoutLevel;
stcTTL(void);
bool set(uint32_t p_u32TTL);
bool flagged(void);
bool restart(void);
bool prepareDeletion(void);
bool finalTimeoutLevel(void) const;
unsigned long timeout(void) const;
};
#ifdef MDNS_IP4_SUPPORT
/**
* stcIP4Address
*/
struct stcIP4Address {
stcIP4Address* m_pNext;
IPAddress m_IPAddress;
stcTTL m_TTL;
stcIP4Address(IPAddress p_IPAddress,
uint32_t p_u32TTL = 0);
};
#endif
#ifdef MDNS_IP6_SUPPORT
/**
* stcIP6Address
*/
struct stcIP6Address {
stcIP6Address* m_pNext;
IP6Address m_IPAddress;
stcTTL m_TTL;
stcIP6Address(IPAddress p_IPAddress,
uint32_t p_u32TTL = 0);
};
#endif
stcAnswer* m_pNext;
// The service domain is the first 'answer' (from PTR answer, using service and protocol) to be set
// Defines the key for additional answer, like host domain, etc.
stcMDNS_RRDomain m_ServiceDomain; // 1. level answer (PTR), eg. MyESP._http._tcp.local
char* m_pcServiceDomain;
stcTTL m_TTLServiceDomain;
stcMDNS_RRDomain m_HostDomain; // 2. level answer (SRV, using service domain), eg. esp8266.local
char* m_pcHostDomain;
uint16_t m_u16Port; // 2. level answer (SRV, using service domain), eg. 5000
stcTTL m_TTLHostDomainAndPort;
stcMDNSServiceTxts m_Txts; // 2. level answer (TXT, using service domain), eg. c#=1
char* m_pcTxts;
stcTTL m_TTLTxts;
#ifdef MDNS_IP4_SUPPORT
stcIP4Address* m_pIP4Addresses; // 3. level answer (A, using host domain), eg. 123.456.789.012
#endif
#ifdef MDNS_IP6_SUPPORT
stcIP6Address* m_pIP6Addresses; // 3. level answer (AAAA, using host domain), eg. 1234::09
#endif
uint32_t m_u32ContentFlags;
stcAnswer(void);
~stcAnswer(void);
bool clear(void);
char* allocServiceDomain(size_t p_stLength);
bool releaseServiceDomain(void);
char* allocHostDomain(size_t p_stLength);
bool releaseHostDomain(void);
char* allocTxts(size_t p_stLength);
bool releaseTxts(void);
#ifdef MDNS_IP4_SUPPORT
bool releaseIP4Addresses(void);
bool addIP4Address(stcIP4Address* p_pIP4Address);
bool removeIP4Address(stcIP4Address* p_pIP4Address);
const stcIP4Address* findIP4Address(const IPAddress& p_IPAddress) const;
stcIP4Address* findIP4Address(const IPAddress& p_IPAddress);
uint32_t IP4AddressCount(void) const;
const stcIP4Address* IP4AddressAtIndex(uint32_t p_u32Index) const;
stcIP4Address* IP4AddressAtIndex(uint32_t p_u32Index);
#endif
#ifdef MDNS_IP6_SUPPORT
bool releaseIP6Addresses(void);
bool addIP6Address(stcIP6Address* p_pIP6Address);
bool removeIP6Address(stcIP6Address* p_pIP6Address);
const stcIP6Address* findIP6Address(const IPAddress& p_IPAddress) const;
stcIP6Address* findIP6Address(const IPAddress& p_IPAddress);
uint32_t IP6AddressCount(void) const;
const stcIP6Address* IP6AddressAtIndex(uint32_t p_u32Index) const;
stcIP6Address* IP6AddressAtIndex(uint32_t p_u32Index);
#endif
};
stcMDNSServiceQuery* m_pNext;
stcMDNS_RRDomain m_ServiceTypeDomain; // eg. _http._tcp.local
MDNSServiceQueryCallbackFunc m_fnCallback;
bool m_bLegacyQuery;
uint8_t m_u8SentCount;
esp8266::polledTimeout::oneShotMs m_ResendTimeout;
bool m_bAwaitingAnswers;
stcAnswer* m_pAnswers;
stcMDNSServiceQuery(void);
~stcMDNSServiceQuery(void);
bool clear(void);
uint32_t answerCount(void) const;
const stcAnswer* answerAtIndex(uint32_t p_u32Index) const;
stcAnswer* answerAtIndex(uint32_t p_u32Index);
uint32_t indexOfAnswer(const stcAnswer* p_pAnswer) const;
bool addAnswer(stcAnswer* p_pAnswer);
bool removeAnswer(stcAnswer* p_pAnswer);
stcAnswer* findAnswerForServiceDomain(const stcMDNS_RRDomain& p_ServiceDomain);
stcAnswer* findAnswerForHostDomain(const stcMDNS_RRDomain& p_HostDomain);
};
/**
* stcMDNSSendParameter
*/
struct stcMDNSSendParameter {
protected:
/**
* stcDomainCacheItem
*/
struct stcDomainCacheItem {
stcDomainCacheItem* m_pNext;
const void* m_pHostnameOrService; // Opaque id for host or service domain (pointer)
bool m_bAdditionalData; // Opaque flag for special info (service domain included)
uint16_t m_u16Offset; // Offset in UDP output buffer
stcDomainCacheItem(const void* p_pHostnameOrService,
bool p_bAdditionalData,
uint32_t p_u16Offset);
};
public:
uint16_t m_u16ID; // Query ID (used only in lagacy queries)
stcMDNS_RRQuestion* m_pQuestions; // A list of queries
uint8_t m_u8HostReplyMask; // Flags for reply components/answers
bool m_bLegacyQuery; // Flag: Legacy query
bool m_bResponse; // Flag: Response to a query
bool m_bAuthorative; // Flag: Authorative (owner) response
bool m_bCacheFlush; // Flag: Clients should flush their caches
bool m_bUnicast; // Flag: Unicast response
bool m_bUnannounce; // Flag: Unannounce service
uint16_t m_u16Offset; // Current offset in UDP write buffer (mainly for domain cache)
stcDomainCacheItem* m_pDomainCacheItems; // Cached host and service domains
stcMDNSSendParameter(void);
~stcMDNSSendParameter(void);
bool clear(void);
bool shiftOffset(uint16_t p_u16Shift);
bool addDomainCacheItem(const void* p_pHostnameOrService,
bool p_bAdditionalData,
uint16_t p_u16Offset);
uint16_t findCachedDomainOffset(const void* p_pHostnameOrService,
bool p_bAdditionalData) const;
};
// Instance variables
stcMDNSService* m_pServices;
UdpContext* m_pUDPContext;
char* m_pcHostname;
stcMDNSServiceQuery* m_pServiceQueries;
WiFiEventHandler m_DisconnectedHandler;
WiFiEventHandler m_GotIPHandler;
MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback;
bool m_bPassivModeEnabled;
stcProbeInformation m_HostProbeInformation;
IPAddress m_IPAddress;
/** CONTROL **/
/* MAINTENANCE */
bool _process(bool p_bUserContext);
bool _restart(void);
/* RECEIVING */
bool _parseMessage(void);
bool _parseQuery(const stcMDNS_MsgHeader& p_Header);
bool _parseResponse(const stcMDNS_MsgHeader& p_Header);
bool _processAnswers(const stcMDNS_RRAnswer* p_pPTRAnswers);
bool _processPTRAnswer(const stcMDNS_RRAnswerPTR* p_pPTRAnswer,
bool& p_rbFoundNewKeyAnswer);
bool _processSRVAnswer(const stcMDNS_RRAnswerSRV* p_pSRVAnswer,
bool& p_rbFoundNewKeyAnswer);
bool _processTXTAnswer(const stcMDNS_RRAnswerTXT* p_pTXTAnswer);
#ifdef MDNS_IP4_SUPPORT
bool _processAAnswer(const stcMDNS_RRAnswerA* p_pAAnswer);
#endif
#ifdef MDNS_IP6_SUPPORT
bool _processAAAAAnswer(const stcMDNS_RRAnswerAAAA* p_pAAAAAnswer);
#endif
/* PROBING */
bool _updateProbeStatus(void);
bool _resetProbeStatus(bool p_bRestart = true);
bool _hasProbesWaitingForAnswers(void) const;
bool _sendHostProbe(void);
bool _sendServiceProbe(stcMDNSService& p_rService);
bool _cancelProbingForHost(void);
bool _cancelProbingForService(stcMDNSService& p_rService);
/* ANNOUNCE */
bool _announce(bool p_bAnnounce,
bool p_bIncludeServices);
bool _announceService(stcMDNSService& p_rService,
bool p_bAnnounce = true);
/* SERVICE QUERY CACHE */
bool _hasServiceQueriesWaitingForAnswers(void) const;
bool _checkServiceQueryCache(void);
/** TRANSFER **/
/* SENDING */
bool _sendMDNSMessage(stcMDNSSendParameter& p_SendParameter);
bool _sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParameter& p_rSendParameter);
bool _prepareMDNSMessage(stcMDNSSendParameter& p_SendParameter,
IPAddress p_IPAddress);
bool _sendMDNSServiceQuery(const stcMDNSServiceQuery& p_ServiceQuery);
bool _sendMDNSQuery(const stcMDNS_RRDomain& p_QueryDomain,
uint16_t p_u16QueryType,
stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers = 0);
const IPAddress& _getResponseMulticastInterface() const { return m_IPAddress; }
uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader,
bool* p_pbFullNameMatch = 0) const;
uint8_t _replyMaskForService(const stcMDNS_RRHeader& p_RRHeader,
const stcMDNSService& p_Service,
bool* p_pbFullNameMatch = 0) const;
/* RESOURCE RECORD */
bool _readRRQuestion(stcMDNS_RRQuestion& p_rQuestion);
bool _readRRAnswer(stcMDNS_RRAnswer*& p_rpAnswer);
#ifdef MDNS_IP4_SUPPORT
bool _readRRAnswerA(stcMDNS_RRAnswerA& p_rRRAnswerA,
uint16_t p_u16RDLength);
#endif
bool _readRRAnswerPTR(stcMDNS_RRAnswerPTR& p_rRRAnswerPTR,
uint16_t p_u16RDLength);
bool _readRRAnswerTXT(stcMDNS_RRAnswerTXT& p_rRRAnswerTXT,
uint16_t p_u16RDLength);
#ifdef MDNS_IP6_SUPPORT
bool _readRRAnswerAAAA(stcMDNS_RRAnswerAAAA& p_rRRAnswerAAAA,
uint16_t p_u16RDLength);
#endif
bool _readRRAnswerSRV(stcMDNS_RRAnswerSRV& p_rRRAnswerSRV,
uint16_t p_u16RDLength);
bool _readRRAnswerGeneric(stcMDNS_RRAnswerGeneric& p_rRRAnswerGeneric,
uint16_t p_u16RDLength);
bool _readRRHeader(stcMDNS_RRHeader& p_rHeader);
bool _readRRDomain(stcMDNS_RRDomain& p_rRRDomain);
bool _readRRDomain_Loop(stcMDNS_RRDomain& p_rRRDomain,
uint8_t p_u8Depth);
bool _readRRAttributes(stcMDNS_RRAttributes& p_rAttributes);
/* DOMAIN NAMES */
bool _buildDomainForHost(const char* p_pcHostname,
stcMDNS_RRDomain& p_rHostDomain) const;
bool _buildDomainForDNSSD(stcMDNS_RRDomain& p_rDNSSDDomain) const;
bool _buildDomainForService(const stcMDNSService& p_Service,
bool p_bIncludeName,
stcMDNS_RRDomain& p_rServiceDomain) const;
bool _buildDomainForService(const char* p_pcService,
const char* p_pcProtocol,
stcMDNS_RRDomain& p_rServiceDomain) const;
#ifdef MDNS_IP4_SUPPORT
bool _buildDomainForReverseIP4(IPAddress p_IP4Address,
stcMDNS_RRDomain& p_rReverseIP4Domain) const;
#endif
#ifdef MDNS_IP6_SUPPORT
bool _buildDomainForReverseIP6(IPAddress p_IP4Address,
stcMDNS_RRDomain& p_rReverseIP6Domain) const;
#endif
/* UDP */
bool _udpReadBuffer(unsigned char* p_pBuffer,
size_t p_stLength);
bool _udpRead8(uint8_t& p_ru8Value);
bool _udpRead16(uint16_t& p_ru16Value);
bool _udpRead32(uint32_t& p_ru32Value);
bool _udpAppendBuffer(const unsigned char* p_pcBuffer,
size_t p_stLength);
bool _udpAppend8(uint8_t p_u8Value);
bool _udpAppend16(uint16_t p_u16Value);
bool _udpAppend32(uint32_t p_u32Value);
#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER
bool _udpDump(bool p_bMovePointer = false);
bool _udpDump(unsigned p_uOffset,
unsigned p_uLength);
#endif
/* READ/WRITE MDNS STRUCTS */
bool _readMDNSMsgHeader(stcMDNS_MsgHeader& p_rMsgHeader);
bool _write8(uint8_t p_u8Value,
stcMDNSSendParameter& p_rSendParameter);
bool _write16(uint16_t p_u16Value,
stcMDNSSendParameter& p_rSendParameter);
bool _write32(uint32_t p_u32Value,
stcMDNSSendParameter& p_rSendParameter);
bool _writeMDNSMsgHeader(const stcMDNS_MsgHeader& p_MsgHeader,
stcMDNSSendParameter& p_rSendParameter);
bool _writeMDNSRRAttributes(const stcMDNS_RRAttributes& p_Attributes,
stcMDNSSendParameter& p_rSendParameter);
bool _writeMDNSRRDomain(const stcMDNS_RRDomain& p_Domain,
stcMDNSSendParameter& p_rSendParameter);
bool _writeMDNSHostDomain(const char* m_pcHostname,
bool p_bPrependRDLength,
stcMDNSSendParameter& p_rSendParameter);
bool _writeMDNSServiceDomain(const stcMDNSService& p_Service,
bool p_bIncludeName,
bool p_bPrependRDLength,
stcMDNSSendParameter& p_rSendParameter);
bool _writeMDNSQuestion(stcMDNS_RRQuestion& p_Question,
stcMDNSSendParameter& p_rSendParameter);
#ifdef MDNS_IP4_SUPPORT
bool _writeMDNSAnswer_A(IPAddress p_IPAddress,
stcMDNSSendParameter& p_rSendParameter);
bool _writeMDNSAnswer_PTR_IP4(IPAddress p_IPAddress,
stcMDNSSendParameter& p_rSendParameter);
#endif
bool _writeMDNSAnswer_PTR_TYPE(stcMDNSService& p_rService,
stcMDNSSendParameter& p_rSendParameter);
bool _writeMDNSAnswer_PTR_NAME(stcMDNSService& p_rService,
stcMDNSSendParameter& p_rSendParameter);
bool _writeMDNSAnswer_TXT(stcMDNSService& p_rService,
stcMDNSSendParameter& p_rSendParameter);
#ifdef MDNS_IP6_SUPPORT
bool _writeMDNSAnswer_AAAA(IPAddress p_IPAddress,
stcMDNSSendParameter& p_rSendParameter);
bool _writeMDNSAnswer_PTR_IP6(IPAddress p_IPAddress,
stcMDNSSendParameter& p_rSendParameter);
#endif
bool _writeMDNSAnswer_SRV(stcMDNSService& p_rService,
stcMDNSSendParameter& p_rSendParameter);
/** HELPERS **/
/* UDP CONTEXT */
bool _callProcess(void);
bool _allocUDPContext(void);
bool _releaseUDPContext(void);
/* SERVICE QUERY */
stcMDNSServiceQuery* _allocServiceQuery(void);
bool _removeServiceQuery(stcMDNSServiceQuery* p_pServiceQuery);
bool _removeLegacyServiceQuery(void);
stcMDNSServiceQuery* _findServiceQuery(hMDNSServiceQuery p_hServiceQuery);
stcMDNSServiceQuery* _findLegacyServiceQuery(void);
bool _releaseServiceQueries(void);
stcMDNSServiceQuery* _findNextServiceQueryByServiceType(const stcMDNS_RRDomain& p_ServiceDomain,
const stcMDNSServiceQuery* p_pPrevServiceQuery);
/* HOSTNAME */
bool _setHostname(const char* p_pcHostname);
bool _releaseHostname(void);
/* SERVICE */
stcMDNSService* _allocService(const char* p_pcName,
const char* p_pcService,
const char* p_pcProtocol,
uint16_t p_u16Port);
bool _releaseService(stcMDNSService* p_pService);
bool _releaseServices(void);
stcMDNSService* _findService(const char* p_pcName,
const char* p_pcService,
const char* p_pcProtocol);
stcMDNSService* _findService(const hMDNSService p_hService);
size_t _countServices(void) const;
/* SERVICE TXT */
stcMDNSServiceTxt* _allocServiceTxt(stcMDNSService* p_pService,
const char* p_pcKey,
const char* p_pcValue,
bool p_bTemp);
bool _releaseServiceTxt(stcMDNSService* p_pService,
stcMDNSServiceTxt* p_pTxt);
stcMDNSServiceTxt* _updateServiceTxt(stcMDNSService* p_pService,
stcMDNSServiceTxt* p_pTxt,
const char* p_pcValue,
bool p_bTemp);
stcMDNSServiceTxt* _findServiceTxt(stcMDNSService* p_pService,
const char* p_pcKey);
stcMDNSServiceTxt* _findServiceTxt(stcMDNSService* p_pService,
const hMDNSTxt p_hTxt);
stcMDNSServiceTxt* _addServiceTxt(stcMDNSService* p_pService,
const char* p_pcKey,
const char* p_pcValue,
bool p_bTemp);
stcMDNSServiceTxt* _answerKeyValue(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex);
bool _collectServiceTxts(stcMDNSService& p_rService);
bool _releaseTempServiceTxts(stcMDNSService& p_rService);
const stcMDNSServiceTxt* _serviceTxts(const char* p_pcName,
const char* p_pcService,
const char* p_pcProtocol);
/* MISC */
#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER
bool _printRRDomain(const stcMDNS_RRDomain& p_rRRDomain) const;
bool _printRRAnswer(const MDNSResponder::stcMDNS_RRAnswer& p_RRAnswer) const;
#endif
};
}// namespace MDNSImplementation
}// namespace esp8266
#endif // MDNS_H