mirror of
https://github.com/esp8266/Arduino.git
synced 2025-05-03 20:44:46 +03:00
2219 lines
60 KiB
C++
2219 lines
60 KiB
C++
/*
|
|
* LEAmDNS_Structs.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 "LEAmDNS_Priv.h"
|
|
#include "LEAmDNS_lwIPdefs.h"
|
|
|
|
namespace esp8266 {
|
|
|
|
/*
|
|
* LEAmDNS
|
|
*/
|
|
namespace MDNSImplementation {
|
|
|
|
/**
|
|
* STRUCTS
|
|
*/
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSServiceTxt
|
|
*
|
|
* One MDNS TXT item.
|
|
* m_pcValue may be '\0'.
|
|
* Objects can be chained together (list, m_pNext).
|
|
* A 'm_bTemp' flag differentiates between static and dynamic items.
|
|
* Output as byte array 'c#=1' is supported.
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt constructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt(const char* p_pcKey /*= 0*/,
|
|
const char* p_pcValue /*= 0*/,
|
|
bool p_bTemp /*= false*/)
|
|
: m_pNext(0),
|
|
m_pcKey(0),
|
|
m_pcValue(0),
|
|
m_bTemp(p_bTemp) {
|
|
|
|
setKey(p_pcKey);
|
|
setValue(p_pcValue);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt copy-constructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt(const MDNSResponder::stcMDNSServiceTxt& p_Other)
|
|
: m_pNext(0),
|
|
m_pcKey(0),
|
|
m_pcValue(0),
|
|
m_bTemp(false) {
|
|
|
|
operator=(p_Other);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::~stcMDNSServiceTxt destructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceTxt::~stcMDNSServiceTxt(void) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::operator=
|
|
*/
|
|
MDNSResponder::stcMDNSServiceTxt& MDNSResponder::stcMDNSServiceTxt::operator=(const MDNSResponder::stcMDNSServiceTxt& p_Other) {
|
|
|
|
if (&p_Other != this) {
|
|
clear();
|
|
set(p_Other.m_pcKey, p_Other.m_pcValue, p_Other.m_bTemp);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxt::clear(void) {
|
|
|
|
releaseKey();
|
|
releaseValue();
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::allocKey
|
|
*/
|
|
char* MDNSResponder::stcMDNSServiceTxt::allocKey(size_t p_stLength) {
|
|
|
|
releaseKey();
|
|
if (p_stLength) {
|
|
m_pcKey = new char[p_stLength + 1];
|
|
}
|
|
return m_pcKey;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::setKey
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxt::setKey(const char* p_pcKey,
|
|
size_t p_stLength) {
|
|
|
|
bool bResult = false;
|
|
|
|
releaseKey();
|
|
if (p_stLength) {
|
|
if (allocKey(p_stLength)) {
|
|
strncpy(m_pcKey, p_pcKey, p_stLength);
|
|
m_pcKey[p_stLength] = 0;
|
|
bResult = true;
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::setKey
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxt::setKey(const char* p_pcKey) {
|
|
|
|
return setKey(p_pcKey, (p_pcKey ? strlen(p_pcKey) : 0));
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::releaseKey
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxt::releaseKey(void) {
|
|
|
|
if (m_pcKey) {
|
|
delete[] m_pcKey;
|
|
m_pcKey = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::allocValue
|
|
*/
|
|
char* MDNSResponder::stcMDNSServiceTxt::allocValue(size_t p_stLength) {
|
|
|
|
releaseValue();
|
|
if (p_stLength) {
|
|
m_pcValue = new char[p_stLength + 1];
|
|
}
|
|
return m_pcValue;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::setValue
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxt::setValue(const char* p_pcValue,
|
|
size_t p_stLength) {
|
|
|
|
bool bResult = false;
|
|
|
|
releaseValue();
|
|
if (p_stLength) {
|
|
if (allocValue(p_stLength)) {
|
|
strncpy(m_pcValue, p_pcValue, p_stLength);
|
|
m_pcValue[p_stLength] = 0;
|
|
bResult = true;
|
|
}
|
|
}
|
|
else { // No value -> also OK
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::setValue
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxt::setValue(const char* p_pcValue) {
|
|
|
|
return setValue(p_pcValue, (p_pcValue ? strlen(p_pcValue) : 0));
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::releaseValue
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxt::releaseValue(void) {
|
|
|
|
if (m_pcValue) {
|
|
delete[] m_pcValue;
|
|
m_pcValue = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::set
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxt::set(const char* p_pcKey,
|
|
const char* p_pcValue,
|
|
bool p_bTemp /*= false*/) {
|
|
|
|
m_bTemp = p_bTemp;
|
|
return ((setKey(p_pcKey)) &&
|
|
(setValue(p_pcValue)));
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::update
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxt::update(const char* p_pcValue) {
|
|
|
|
return setValue(p_pcValue);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxt::length
|
|
*
|
|
* length of eg. 'c#=1' without any closing '\0'
|
|
*/
|
|
size_t MDNSResponder::stcMDNSServiceTxt::length(void) const {
|
|
|
|
size_t stLength = 0;
|
|
if (m_pcKey) {
|
|
stLength += strlen(m_pcKey); // Key
|
|
stLength += 1; // '='
|
|
stLength += (m_pcValue ? strlen(m_pcValue) : 0); // Value
|
|
}
|
|
return stLength;
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSServiceTxts
|
|
*
|
|
* A list of zero or more MDNS TXT items.
|
|
* Dynamic TXT items can be removed by 'removeTempTxts'.
|
|
* A TXT item can be looke up by its 'key' member.
|
|
* Export as ';'-separated byte array is supported.
|
|
* Export as 'length byte coded' byte array is supported.
|
|
* Comparision ((all A TXT items in B and equal) AND (all B TXT items in A and equal)) is supported.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts contructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts(void)
|
|
: m_pTxts(0) {
|
|
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts copy-constructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts(const stcMDNSServiceTxts& p_Other)
|
|
: m_pTxts(0) {
|
|
|
|
operator=(p_Other);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::~stcMDNSServiceTxts destructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceTxts::~stcMDNSServiceTxts(void) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::operator=
|
|
*/
|
|
MDNSResponder::stcMDNSServiceTxts& MDNSResponder::stcMDNSServiceTxts::operator=(const stcMDNSServiceTxts& p_Other) {
|
|
|
|
if (this != &p_Other) {
|
|
clear();
|
|
|
|
for (stcMDNSServiceTxt* pOtherTxt=p_Other.m_pTxts; pOtherTxt; pOtherTxt=pOtherTxt->m_pNext) {
|
|
add(new stcMDNSServiceTxt(*pOtherTxt));
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxts::clear(void) {
|
|
|
|
while (m_pTxts) {
|
|
stcMDNSServiceTxt* pNext = m_pTxts->m_pNext;
|
|
delete m_pTxts;
|
|
m_pTxts = pNext;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::add
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxts::add(MDNSResponder::stcMDNSServiceTxt* p_pTxt) {
|
|
|
|
bool bResult = false;
|
|
|
|
if (p_pTxt) {
|
|
p_pTxt->m_pNext = m_pTxts;
|
|
m_pTxts = p_pTxt;
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::remove
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxts::remove(stcMDNSServiceTxt* p_pTxt) {
|
|
|
|
bool bResult = false;
|
|
|
|
if (p_pTxt) {
|
|
stcMDNSServiceTxt* pPred = m_pTxts;
|
|
while ((pPred) &&
|
|
(pPred->m_pNext != p_pTxt)) {
|
|
pPred = pPred->m_pNext;
|
|
}
|
|
if (pPred) {
|
|
pPred->m_pNext = p_pTxt->m_pNext;
|
|
delete p_pTxt;
|
|
bResult = true;
|
|
}
|
|
else if (m_pTxts == p_pTxt) { // No predecesor, but first item
|
|
m_pTxts = p_pTxt->m_pNext;
|
|
delete p_pTxt;
|
|
bResult = true;
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::removeTempTxts
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxts::removeTempTxts(void) {
|
|
|
|
bool bResult = true;
|
|
|
|
stcMDNSServiceTxt* pTxt = m_pTxts;
|
|
while ((bResult) &&
|
|
(pTxt)) {
|
|
stcMDNSServiceTxt* pNext = pTxt->m_pNext;
|
|
if (pTxt->m_bTemp) {
|
|
bResult = remove(pTxt);
|
|
}
|
|
pTxt = pNext;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::find
|
|
*/
|
|
MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const char* p_pcKey) {
|
|
|
|
stcMDNSServiceTxt* pResult = 0;
|
|
|
|
for (stcMDNSServiceTxt* pTxt=m_pTxts; pTxt; pTxt=pTxt->m_pNext) {
|
|
if ((p_pcKey) &&
|
|
(0 == strcmp(pTxt->m_pcKey, p_pcKey))) {
|
|
pResult = pTxt;
|
|
break;
|
|
}
|
|
}
|
|
return pResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::find
|
|
*/
|
|
const MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const char* p_pcKey) const {
|
|
|
|
const stcMDNSServiceTxt* pResult = 0;
|
|
|
|
for (const stcMDNSServiceTxt* pTxt=m_pTxts; pTxt; pTxt=pTxt->m_pNext) {
|
|
if ((p_pcKey) &&
|
|
(0 == strcmp(pTxt->m_pcKey, p_pcKey))) {
|
|
|
|
pResult = pTxt;
|
|
break;
|
|
}
|
|
}
|
|
return pResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::find
|
|
*/
|
|
MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const stcMDNSServiceTxt* p_pTxt) {
|
|
|
|
stcMDNSServiceTxt* pResult = 0;
|
|
|
|
for (stcMDNSServiceTxt* pTxt=m_pTxts; pTxt; pTxt=pTxt->m_pNext) {
|
|
if (p_pTxt == pTxt) {
|
|
pResult = pTxt;
|
|
break;
|
|
}
|
|
}
|
|
return pResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::length
|
|
*/
|
|
uint16_t MDNSResponder::stcMDNSServiceTxts::length(void) const {
|
|
|
|
uint16_t u16Length = 0;
|
|
|
|
stcMDNSServiceTxt* pTxt = m_pTxts;
|
|
while (pTxt) {
|
|
u16Length += 1; // Length byte
|
|
u16Length += pTxt->length(); // Text
|
|
pTxt = pTxt->m_pNext;
|
|
}
|
|
return u16Length;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::c_strLength
|
|
*
|
|
* (incl. closing '\0'). Length bytes place is used for delimiting ';' and closing '\0'
|
|
*/
|
|
size_t MDNSResponder::stcMDNSServiceTxts::c_strLength(void) const {
|
|
|
|
return length();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::c_str
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxts::c_str(char* p_pcBuffer) {
|
|
|
|
bool bResult = false;
|
|
|
|
if (p_pcBuffer) {
|
|
bResult = true;
|
|
|
|
*p_pcBuffer = 0;
|
|
for (stcMDNSServiceTxt* pTxt=m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) {
|
|
size_t stLength;
|
|
if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) {
|
|
if (pTxt != m_pTxts) {
|
|
*p_pcBuffer++ = ';';
|
|
}
|
|
strncpy(p_pcBuffer, pTxt->m_pcKey, stLength); p_pcBuffer[stLength] = 0;
|
|
p_pcBuffer += stLength;
|
|
*p_pcBuffer++ = '=';
|
|
if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) {
|
|
strncpy(p_pcBuffer, pTxt->m_pcValue, stLength); p_pcBuffer[stLength] = 0;
|
|
p_pcBuffer += stLength;
|
|
}
|
|
}
|
|
}
|
|
*p_pcBuffer++ = 0;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::bufferLength
|
|
*
|
|
* (incl. closing '\0').
|
|
*/
|
|
size_t MDNSResponder::stcMDNSServiceTxts::bufferLength(void) const {
|
|
|
|
return (length() + 1);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::toBuffer
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxts::buffer(char* p_pcBuffer) {
|
|
|
|
bool bResult = false;
|
|
|
|
if (p_pcBuffer) {
|
|
bResult = true;
|
|
|
|
*p_pcBuffer = 0;
|
|
for (stcMDNSServiceTxt* pTxt=m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) {
|
|
*(unsigned char*)p_pcBuffer++ = pTxt->length();
|
|
size_t stLength;
|
|
if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) {
|
|
memcpy(p_pcBuffer, pTxt->m_pcKey, stLength);
|
|
p_pcBuffer += stLength;
|
|
*p_pcBuffer++ = '=';
|
|
if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) {
|
|
memcpy(p_pcBuffer, pTxt->m_pcValue, stLength);
|
|
p_pcBuffer += stLength;
|
|
}
|
|
}
|
|
}
|
|
*p_pcBuffer++ = 0;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::compare
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxts::compare(const MDNSResponder::stcMDNSServiceTxts& p_Other) const {
|
|
|
|
bool bResult = false;
|
|
|
|
if ((bResult = (length() == p_Other.length()))) {
|
|
// Compare A->B
|
|
for (const stcMDNSServiceTxt* pTxt=m_pTxts; ((bResult) && (pTxt)); pTxt=pTxt->m_pNext) {
|
|
const stcMDNSServiceTxt* pOtherTxt = p_Other.find(pTxt->m_pcKey);
|
|
bResult = ((pOtherTxt) &&
|
|
(pTxt->m_pcValue) &&
|
|
(pOtherTxt->m_pcValue) &&
|
|
(strlen(pTxt->m_pcValue) == strlen(pOtherTxt->m_pcValue)) &&
|
|
(0 == strcmp(pTxt->m_pcValue, pOtherTxt->m_pcValue)));
|
|
}
|
|
// Compare B->A
|
|
for (const stcMDNSServiceTxt* pOtherTxt=p_Other.m_pTxts; ((bResult) && (pOtherTxt)); pOtherTxt=pOtherTxt->m_pNext) {
|
|
const stcMDNSServiceTxt* pTxt = find(pOtherTxt->m_pcKey);
|
|
bResult = ((pTxt) &&
|
|
(pOtherTxt->m_pcValue) &&
|
|
(pTxt->m_pcValue) &&
|
|
(strlen(pOtherTxt->m_pcValue) == strlen(pTxt->m_pcValue)) &&
|
|
(0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue)));
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::operator==
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxts::operator==(const stcMDNSServiceTxts& p_Other) const {
|
|
|
|
return compare(p_Other);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceTxts::operator!=
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceTxts::operator!=(const stcMDNSServiceTxts& p_Other) const {
|
|
|
|
return !compare(p_Other);
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_MsgHeader
|
|
*
|
|
* A MDNS message haeder.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_MsgHeader::stcMDNS_MsgHeader
|
|
*/
|
|
MDNSResponder::stcMDNS_MsgHeader::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*/)
|
|
: m_u16ID(p_u16ID),
|
|
m_1bQR(p_bQR), m_4bOpcode(p_ucOpcode), m_1bAA(p_bAA), m_1bTC(p_bTC), m_1bRD(p_bRD),
|
|
m_1bRA(p_bRA), m_3bZ(0), m_4bRCode(p_ucRCode),
|
|
m_u16QDCount(p_u16QDCount),
|
|
m_u16ANCount(p_u16ANCount),
|
|
m_u16NSCount(p_u16NSCount),
|
|
m_u16ARCount(p_u16ARCount) {
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_RRDomain
|
|
*
|
|
* A MDNS domain object.
|
|
* The labels of the domain are stored (DNS-like encoded) in 'm_acName':
|
|
* [length byte]varlength label[length byte]varlength label[0]
|
|
* 'm_u16NameLength' stores the used length of 'm_acName'.
|
|
* Dynamic label addition is supported.
|
|
* Comparison is supported.
|
|
* Export as byte array 'esp8266.local' is supported.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain(void)
|
|
: m_u16NameLength(0) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain copy-constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain(const stcMDNS_RRDomain& p_Other)
|
|
: m_u16NameLength(0) {
|
|
|
|
operator=(p_Other);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRDomain::operator =
|
|
*/
|
|
MDNSResponder::stcMDNS_RRDomain& MDNSResponder::stcMDNS_RRDomain::operator=(const stcMDNS_RRDomain& p_Other) {
|
|
|
|
if (&p_Other != this) {
|
|
memcpy(m_acName, p_Other.m_acName, sizeof(m_acName));
|
|
m_u16NameLength = p_Other.m_u16NameLength;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRDomain::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRDomain::clear(void) {
|
|
|
|
memset(m_acName, 0, sizeof(m_acName));
|
|
m_u16NameLength = 0;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRDomain::addLabel
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRDomain::addLabel(const char* p_pcLabel,
|
|
bool p_bPrependUnderline /*= false*/) {
|
|
|
|
bool bResult = false;
|
|
|
|
size_t stLength = (p_pcLabel
|
|
? (strlen(p_pcLabel) + (p_bPrependUnderline ? 1 : 0))
|
|
: 0);
|
|
if ((MDNS_DOMAIN_LABEL_MAXLENGTH >= stLength) &&
|
|
(MDNS_DOMAIN_MAXLENGTH >= (m_u16NameLength + (1 + stLength)))) {
|
|
// Length byte
|
|
m_acName[m_u16NameLength] = (unsigned char)stLength; // Might be 0!
|
|
++m_u16NameLength;
|
|
// Label
|
|
if (stLength) {
|
|
if (p_bPrependUnderline) {
|
|
m_acName[m_u16NameLength++] = '_';
|
|
--stLength;
|
|
}
|
|
strncpy(&(m_acName[m_u16NameLength]), p_pcLabel, stLength); m_acName[m_u16NameLength + stLength] = 0;
|
|
m_u16NameLength += stLength;
|
|
}
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRDomain::compare
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRDomain::compare(const stcMDNS_RRDomain& p_Other) const {
|
|
|
|
bool bResult = false;
|
|
|
|
if (m_u16NameLength == p_Other.m_u16NameLength) {
|
|
const char* pT = m_acName;
|
|
const char* pO = p_Other.m_acName;
|
|
while ((pT) &&
|
|
(pO) &&
|
|
(*((unsigned char*)pT) == *((unsigned char*)pO)) && // Same length AND
|
|
(0 == strncasecmp((pT + 1), (pO + 1), *((unsigned char*)pT)))) { // Same content
|
|
if (*((unsigned char*)pT)) { // Not 0
|
|
pT += (1 + *((unsigned char*)pT)); // Shift by length byte and lenght
|
|
pO += (1 + *((unsigned char*)pO));
|
|
}
|
|
else { // Is 0 -> Successfully reached the end
|
|
bResult = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRDomain::operator ==
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRDomain::operator==(const stcMDNS_RRDomain& p_Other) const {
|
|
|
|
return compare(p_Other);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRDomain::operator !=
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRDomain::operator!=(const stcMDNS_RRDomain& p_Other) const {
|
|
|
|
return !compare(p_Other);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRDomain::operator >
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRDomain::operator>(const stcMDNS_RRDomain& p_Other) const {
|
|
|
|
// TODO: Check, if this is a good idea...
|
|
return !compare(p_Other);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRDomain::c_strLength
|
|
*/
|
|
size_t MDNSResponder::stcMDNS_RRDomain::c_strLength(void) const {
|
|
|
|
size_t stLength = 0;
|
|
|
|
unsigned char* pucLabelLength = (unsigned char*)m_acName;
|
|
while (*pucLabelLength) {
|
|
stLength += (*pucLabelLength + 1 /* +1 for '.' or '\0'*/);
|
|
pucLabelLength += (*pucLabelLength + 1);
|
|
}
|
|
return stLength;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRDomain::c_str
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRDomain::c_str(char* p_pcBuffer) {
|
|
|
|
bool bResult = false;
|
|
|
|
if (p_pcBuffer) {
|
|
*p_pcBuffer = 0;
|
|
unsigned char* pucLabelLength = (unsigned char*)m_acName;
|
|
while (*pucLabelLength) {
|
|
memcpy(p_pcBuffer, (const char*)(pucLabelLength + 1), *pucLabelLength);
|
|
p_pcBuffer += *pucLabelLength;
|
|
pucLabelLength += (*pucLabelLength + 1);
|
|
*p_pcBuffer++ = (*pucLabelLength ? '.' : '\0');
|
|
}
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_RRAttributes
|
|
*
|
|
* A MDNS attributes object.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes(uint16_t p_u16Type /*= 0*/,
|
|
uint16_t p_u16Class /*= 1 DNS_RRCLASS_IN Internet*/)
|
|
: m_u16Type(p_u16Type),
|
|
m_u16Class(p_u16Class) {
|
|
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes copy-constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes(const MDNSResponder::stcMDNS_RRAttributes& p_Other) {
|
|
|
|
operator=(p_Other);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAttributes::operator =
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAttributes& MDNSResponder::stcMDNS_RRAttributes::operator=(const MDNSResponder::stcMDNS_RRAttributes& p_Other) {
|
|
|
|
if (&p_Other != this) {
|
|
m_u16Type = p_Other.m_u16Type;
|
|
m_u16Class = p_Other.m_u16Class;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_RRHeader
|
|
*
|
|
* A MDNS record header (domain and attributes) object.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader(void) {
|
|
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader copy-constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader(const stcMDNS_RRHeader& p_Other) {
|
|
|
|
operator=(p_Other);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRHeader::operator =
|
|
*/
|
|
MDNSResponder::stcMDNS_RRHeader& MDNSResponder::stcMDNS_RRHeader::operator=(const MDNSResponder::stcMDNS_RRHeader& p_Other) {
|
|
|
|
if (&p_Other != this) {
|
|
m_Domain = p_Other.m_Domain;
|
|
m_Attributes = p_Other.m_Attributes;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRHeader::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRHeader::clear(void) {
|
|
|
|
m_Domain.clear();
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_RRQuestion
|
|
*
|
|
* A MDNS question record object (header + question flags)
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRQuestion::stcMDNS_RRQuestion constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRQuestion::stcMDNS_RRQuestion(void)
|
|
: m_pNext(0),
|
|
m_bUnicast(false) {
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_RRAnswer
|
|
*
|
|
* A MDNS answer record object (header + answer content).
|
|
* This is a 'virtual' base class for all other MDNS answer classes.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswer::stcMDNS_RRAnswer constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswer::stcMDNS_RRAnswer(enuAnswerType p_AnswerType,
|
|
const MDNSResponder::stcMDNS_RRHeader& p_Header,
|
|
uint32_t p_u32TTL)
|
|
: m_pNext(0),
|
|
m_AnswerType(p_AnswerType),
|
|
m_Header(p_Header),
|
|
m_u32TTL(p_u32TTL) {
|
|
|
|
// Extract 'cache flush'-bit
|
|
m_bCacheFlush = (m_Header.m_Attributes.m_u16Class & 0x8000);
|
|
m_Header.m_Attributes.m_u16Class &= (~0x8000);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswer::~stcMDNS_RRAnswer destructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswer::~stcMDNS_RRAnswer(void) {
|
|
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswer::answerType
|
|
*/
|
|
MDNSResponder::enuAnswerType MDNSResponder::stcMDNS_RRAnswer::answerType(void) const {
|
|
|
|
return m_AnswerType;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswer::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRAnswer::clear(void) {
|
|
|
|
m_pNext = 0;
|
|
m_Header.clear();
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_RRAnswerA
|
|
*
|
|
* A MDNS A answer object.
|
|
* Extends the base class by an IP4 address member.
|
|
*
|
|
*/
|
|
|
|
#ifdef MDNS_IP4_SUPPORT
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA(const MDNSResponder::stcMDNS_RRHeader& p_Header,
|
|
uint32_t p_u32TTL)
|
|
: stcMDNS_RRAnswer(AnswerType_A, p_Header, p_u32TTL),
|
|
m_IPAddress(0, 0, 0, 0) {
|
|
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA destructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerA::~stcMDNS_RRAnswerA(void) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerA::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRAnswerA::clear(void) {
|
|
|
|
m_IPAddress = IPAddress(0, 0, 0, 0);
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_RRAnswerPTR
|
|
*
|
|
* A MDNS PTR answer object.
|
|
* Extends the base class by a MDNS domain member.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerPTR::stcMDNS_RRAnswerPTR constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerPTR::stcMDNS_RRAnswerPTR(const MDNSResponder::stcMDNS_RRHeader& p_Header,
|
|
uint32_t p_u32TTL)
|
|
: stcMDNS_RRAnswer(AnswerType_PTR, p_Header, p_u32TTL) {
|
|
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerPTR::~stcMDNS_RRAnswerPTR destructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerPTR::~stcMDNS_RRAnswerPTR(void) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerPTR::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRAnswerPTR::clear(void) {
|
|
|
|
m_PTRDomain.clear();
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_RRAnswerTXT
|
|
*
|
|
* A MDNS TXT answer object.
|
|
* Extends the base class by a MDNS TXT items list member.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerTXT::stcMDNS_RRAnswerTXT constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerTXT::stcMDNS_RRAnswerTXT(const MDNSResponder::stcMDNS_RRHeader& p_Header,
|
|
uint32_t p_u32TTL)
|
|
: stcMDNS_RRAnswer(AnswerType_TXT, p_Header, p_u32TTL) {
|
|
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerTXT::~stcMDNS_RRAnswerTXT destructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerTXT::~stcMDNS_RRAnswerTXT(void) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerTXT::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRAnswerTXT::clear(void) {
|
|
|
|
m_Txts.clear();
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_RRAnswerAAAA
|
|
*
|
|
* A MDNS AAAA answer object.
|
|
* (Should) extend the base class by an IP6 address member.
|
|
*
|
|
*/
|
|
|
|
#ifdef MDNS_IP6_SUPPORT
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerAAAA::stcMDNS_RRAnswerAAAA constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerAAAA::stcMDNS_RRAnswerAAAA(const MDNSResponder::stcMDNS_RRHeader& p_Header,
|
|
uint32_t p_u32TTL)
|
|
: stcMDNS_RRAnswer(AnswerType_AAAA, p_Header, p_u32TTL) {
|
|
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerAAAA::~stcMDNS_RRAnswerAAAA destructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerAAAA::~stcMDNS_RRAnswerAAAA(void) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerAAAA::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRAnswerAAAA::clear(void) {
|
|
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_RRAnswerSRV
|
|
*
|
|
* A MDNS SRV answer object.
|
|
* Extends the base class by a port member.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerSRV::stcMDNS_RRAnswerSRV constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerSRV::stcMDNS_RRAnswerSRV(const MDNSResponder::stcMDNS_RRHeader& p_Header,
|
|
uint32_t p_u32TTL)
|
|
: stcMDNS_RRAnswer(AnswerType_SRV, p_Header, p_u32TTL),
|
|
m_u16Priority(0),
|
|
m_u16Weight(0),
|
|
m_u16Port(0) {
|
|
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerSRV::~stcMDNS_RRAnswerSRV destructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerSRV::~stcMDNS_RRAnswerSRV(void) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerSRV::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRAnswerSRV::clear(void) {
|
|
|
|
m_u16Priority = 0;
|
|
m_u16Weight = 0;
|
|
m_u16Port = 0;
|
|
m_SRVDomain.clear();
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNS_RRAnswerGeneric
|
|
*
|
|
* An unknown (generic) MDNS answer object.
|
|
* Extends the base class by a RDATA buffer member.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerGeneric::stcMDNS_RRAnswerGeneric constructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerGeneric::stcMDNS_RRAnswerGeneric(const stcMDNS_RRHeader& p_Header,
|
|
uint32_t p_u32TTL)
|
|
: stcMDNS_RRAnswer(AnswerType_Generic, p_Header, p_u32TTL),
|
|
m_u16RDLength(0),
|
|
m_pu8RDData(0) {
|
|
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerGeneric::~stcMDNS_RRAnswerGeneric destructor
|
|
*/
|
|
MDNSResponder::stcMDNS_RRAnswerGeneric::~stcMDNS_RRAnswerGeneric(void) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNS_RRAnswerGeneric::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNS_RRAnswerGeneric::clear(void) {
|
|
|
|
if (m_pu8RDData) {
|
|
delete[] m_pu8RDData;
|
|
m_pu8RDData = 0;
|
|
}
|
|
m_u16RDLength = 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcProbeInformation
|
|
*
|
|
* Probing status information for a host or service domain
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcProbeInformation::stcProbeInformation constructor
|
|
*/
|
|
MDNSResponder::stcProbeInformation::stcProbeInformation(void)
|
|
: m_ProbingStatus(ProbingStatus_WaitingForData),
|
|
m_u8SentCount(0),
|
|
m_Timeout(esp8266::polledTimeout::oneShotMs::neverExpires),
|
|
m_bConflict(false),
|
|
m_bTiebreakNeeded(false),
|
|
m_fnHostProbeResultCallback(0),
|
|
m_fnServiceProbeResultCallback(0) {
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcProbeInformation::clear
|
|
*/
|
|
bool MDNSResponder::stcProbeInformation::clear(bool p_bClearUserdata /*= false*/) {
|
|
|
|
m_ProbingStatus = ProbingStatus_WaitingForData;
|
|
m_u8SentCount = 0;
|
|
m_Timeout.resetToNeverExpires();
|
|
m_bConflict = false;
|
|
m_bTiebreakNeeded = false;
|
|
if (p_bClearUserdata) {
|
|
m_fnHostProbeResultCallback = 0;
|
|
m_fnServiceProbeResultCallback = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSService
|
|
*
|
|
* A MDNS service object (to be announced by the MDNS responder)
|
|
* The service instance may be '\0'; in this case the hostname is used
|
|
* and the flag m_bAutoName is set. If the hostname changes, all 'auto-
|
|
* named' services are renamed also.
|
|
* m_u8Replymask is used while preparing a response to a MDNS query. It is
|
|
* resetted in '_sendMDNSMessage' afterwards.
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSService::stcMDNSService constructor
|
|
*/
|
|
MDNSResponder::stcMDNSService::stcMDNSService(const char* p_pcName /*= 0*/,
|
|
const char* p_pcService /*= 0*/,
|
|
const char* p_pcProtocol /*= 0*/)
|
|
: m_pNext(0),
|
|
m_pcName(0),
|
|
m_bAutoName(false),
|
|
m_pcService(0),
|
|
m_pcProtocol(0),
|
|
m_u16Port(0),
|
|
m_u8ReplyMask(0),
|
|
m_fnTxtCallback(0) {
|
|
|
|
setName(p_pcName);
|
|
setService(p_pcService);
|
|
setProtocol(p_pcProtocol);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSService::~stcMDNSService destructor
|
|
*/
|
|
MDNSResponder::stcMDNSService::~stcMDNSService(void) {
|
|
|
|
releaseName();
|
|
releaseService();
|
|
releaseProtocol();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSService::setName
|
|
*/
|
|
bool MDNSResponder::stcMDNSService::setName(const char* p_pcName) {
|
|
|
|
bool bResult = false;
|
|
|
|
releaseName();
|
|
size_t stLength = (p_pcName ? strlen(p_pcName) : 0);
|
|
if (stLength) {
|
|
if ((bResult = (0 != (m_pcName = new char[stLength + 1])))) {
|
|
strncpy(m_pcName, p_pcName, stLength);
|
|
m_pcName[stLength] = 0;
|
|
}
|
|
}
|
|
else {
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSService::releaseName
|
|
*/
|
|
bool MDNSResponder::stcMDNSService::releaseName(void) {
|
|
|
|
if (m_pcName) {
|
|
delete[] m_pcName;
|
|
m_pcName = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSService::setService
|
|
*/
|
|
bool MDNSResponder::stcMDNSService::setService(const char* p_pcService) {
|
|
|
|
bool bResult = false;
|
|
|
|
releaseService();
|
|
size_t stLength = (p_pcService ? strlen(p_pcService) : 0);
|
|
if (stLength) {
|
|
if ((bResult = (0 != (m_pcService = new char[stLength + 1])))) {
|
|
strncpy(m_pcService, p_pcService, stLength);
|
|
m_pcService[stLength] = 0;
|
|
}
|
|
}
|
|
else {
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSService::releaseService
|
|
*/
|
|
bool MDNSResponder::stcMDNSService::releaseService(void) {
|
|
|
|
if (m_pcService) {
|
|
delete[] m_pcService;
|
|
m_pcService = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSService::setProtocol
|
|
*/
|
|
bool MDNSResponder::stcMDNSService::setProtocol(const char* p_pcProtocol) {
|
|
|
|
bool bResult = false;
|
|
|
|
releaseProtocol();
|
|
size_t stLength = (p_pcProtocol ? strlen(p_pcProtocol) : 0);
|
|
if (stLength) {
|
|
if ((bResult = (0 != (m_pcProtocol = new char[stLength + 1])))) {
|
|
strncpy(m_pcProtocol, p_pcProtocol, stLength);
|
|
m_pcProtocol[stLength] = 0;
|
|
}
|
|
}
|
|
else {
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSService::releaseProtocol
|
|
*/
|
|
bool MDNSResponder::stcMDNSService::releaseProtocol(void) {
|
|
|
|
if (m_pcProtocol) {
|
|
delete[] m_pcProtocol;
|
|
m_pcProtocol = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSServiceQuery
|
|
*
|
|
* A MDNS service query object.
|
|
* Service queries may be static or dynamic.
|
|
* As the static service query is processed in the blocking function 'queryService',
|
|
* only one static service service may exist. The processing of the answers is done
|
|
* on the WiFi-stack side of the ESP stack structure (via 'UDPContext.onRx(_update)').
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer
|
|
*
|
|
* One answer for a service query.
|
|
* Every answer must contain
|
|
* - a service instance entry (pivot),
|
|
* and may contain
|
|
* - a host domain,
|
|
* - a port
|
|
* - an IP4 address
|
|
* (- an IP6 address)
|
|
* - a MDNS TXTs
|
|
* The existance of a component is flaged in 'm_u32ContentFlags'.
|
|
* For every answer component a TTL value is maintained.
|
|
* Answer objects can be connected to a linked list.
|
|
*
|
|
* For the host domain, service domain and TXTs components, a char array
|
|
* representation can be retrieved (which is created on demand).
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL
|
|
*
|
|
* The TTL (Time-To-Live) for an specific answer content.
|
|
* The 80% and outdated states are calculated based on the current time (millis)
|
|
* and the 'set' time (also millis).
|
|
* If the answer is scheduled for an update, the corresponding flag should be set.
|
|
*
|
|
* /
|
|
|
|
/ *
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL constructor
|
|
* /
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(uint32_t p_u32TTL / *= 0* /)
|
|
: m_bUpdateScheduled(false) {
|
|
|
|
set(p_u32TTL * 1000);
|
|
}
|
|
|
|
/ *
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set
|
|
* /
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) {
|
|
|
|
m_TTLTimeFlag.restart(p_u32TTL * 1000);
|
|
m_bUpdateScheduled = false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/ *
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::has80Percent
|
|
* /
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::has80Percent(void) const {
|
|
|
|
return ((m_TTLTimeFlag.getTimeout()) &&
|
|
(!m_bUpdateScheduled) &&
|
|
(m_TTLTimeFlag.hypotheticalTimeout((m_TTLTimeFlag.getTimeout() * 800) / 1000)));
|
|
}
|
|
|
|
/ *
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated
|
|
* /
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated(void) const {
|
|
|
|
return ((m_TTLTimeFlag.getTimeout()) &&
|
|
(m_TTLTimeFlag.flagged()));
|
|
}*/
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL
|
|
*
|
|
* The TTL (Time-To-Live) for an specific answer content.
|
|
* The 80% and outdated states are calculated based on the current time (millis)
|
|
* and the 'set' time (also millis).
|
|
* If the answer is scheduled for an update, the corresponding flag should be set.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL constructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(void)
|
|
: m_u32TTL(0),
|
|
m_TTLTimeout(esp8266::polledTimeout::oneShotMs::neverExpires),
|
|
m_timeoutLevel(TIMEOUTLEVEL_UNSET) {
|
|
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) {
|
|
|
|
m_u32TTL = p_u32TTL;
|
|
if (m_u32TTL) {
|
|
m_timeoutLevel = TIMEOUTLEVEL_BASE; // Set to 80%
|
|
m_TTLTimeout.reset(timeout());
|
|
}
|
|
else {
|
|
m_timeoutLevel = TIMEOUTLEVEL_UNSET; // undef
|
|
m_TTLTimeout.resetToNeverExpires();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged(void) {
|
|
|
|
return ((m_u32TTL) &&
|
|
(TIMEOUTLEVEL_UNSET != m_timeoutLevel) &&
|
|
(m_TTLTimeout.expired()));
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::restart
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::restart(void) {
|
|
|
|
bool bResult = true;
|
|
|
|
if ((TIMEOUTLEVEL_BASE <= m_timeoutLevel) && // >= 80% AND
|
|
(TIMEOUTLEVEL_FINAL > m_timeoutLevel)) { // < 100%
|
|
|
|
m_timeoutLevel += TIMEOUTLEVEL_INTERVAL; // increment by 5%
|
|
m_TTLTimeout.reset(timeout());
|
|
}
|
|
else {
|
|
bResult = false;
|
|
m_TTLTimeout.resetToNeverExpires();
|
|
m_timeoutLevel = TIMEOUTLEVEL_UNSET;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::prepareDeletion
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::prepareDeletion(void) {
|
|
|
|
m_timeoutLevel = TIMEOUTLEVEL_FINAL;
|
|
m_TTLTimeout.reset(1 * 1000); // See RFC 6762, 10.1
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::finalTimeoutLevel
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::finalTimeoutLevel(void) const {
|
|
|
|
return (TIMEOUTLEVEL_FINAL == m_timeoutLevel);
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout
|
|
*/
|
|
unsigned long MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout(void) const {
|
|
|
|
uint32_t u32Timeout = esp8266::polledTimeout::oneShotMs::neverExpires;
|
|
|
|
if (TIMEOUTLEVEL_BASE == m_timeoutLevel) { // 80%
|
|
u32Timeout = (m_u32TTL * 800); // to milliseconds
|
|
}
|
|
else if ((TIMEOUTLEVEL_BASE < m_timeoutLevel) && // >80% AND
|
|
(TIMEOUTLEVEL_FINAL >= m_timeoutLevel)) { // <= 100%
|
|
|
|
u32Timeout = (m_u32TTL * 50);
|
|
} // else: invalid
|
|
return u32Timeout;
|
|
}
|
|
|
|
|
|
#ifdef MDNS_IP4_SUPPORT
|
|
/**
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address::stcIP4Address constructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address::stcIP4Address(IPAddress p_IPAddress,
|
|
uint32_t p_u32TTL /*= 0*/)
|
|
: m_pNext(0),
|
|
m_IPAddress(p_IPAddress) {
|
|
|
|
m_TTL.set(p_u32TTL);
|
|
}
|
|
#endif
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcAnswer constructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcAnswer(void)
|
|
: m_pNext(0),
|
|
m_pcServiceDomain(0),
|
|
m_pcHostDomain(0),
|
|
m_u16Port(0),
|
|
m_pcTxts(0),
|
|
#ifdef MDNS_IP4_SUPPORT
|
|
m_pIP4Addresses(0),
|
|
#endif
|
|
#ifdef MDNS_IP6_SUPPORT
|
|
m_pIP6Addresses(0),
|
|
#endif
|
|
m_u32ContentFlags(0) {
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::~stcAnswer destructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer::~stcAnswer(void) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::clear(void) {
|
|
|
|
return ((releaseTxts()) &&
|
|
#ifdef MDNS_IP4_SUPPORT
|
|
(releaseIP4Addresses()) &&
|
|
#endif
|
|
#ifdef MDNS_IP6_SUPPORT
|
|
(releaseIP6Addresses())
|
|
#endif
|
|
(releaseHostDomain()) &&
|
|
(releaseServiceDomain()));
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocServiceDomain
|
|
*
|
|
* Alloc memory for the char array representation of the service domain.
|
|
*
|
|
*/
|
|
char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocServiceDomain(size_t p_stLength) {
|
|
|
|
releaseServiceDomain();
|
|
if (p_stLength) {
|
|
m_pcServiceDomain = new char[p_stLength];
|
|
}
|
|
return m_pcServiceDomain;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseServiceDomain
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseServiceDomain(void) {
|
|
|
|
if (m_pcServiceDomain) {
|
|
delete[] m_pcServiceDomain;
|
|
m_pcServiceDomain = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocHostDomain
|
|
*
|
|
* Alloc memory for the char array representation of the host domain.
|
|
*
|
|
*/
|
|
char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocHostDomain(size_t p_stLength) {
|
|
|
|
releaseHostDomain();
|
|
if (p_stLength) {
|
|
m_pcHostDomain = new char[p_stLength];
|
|
}
|
|
return m_pcHostDomain;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseHostDomain
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseHostDomain(void) {
|
|
|
|
if (m_pcHostDomain) {
|
|
delete[] m_pcHostDomain;
|
|
m_pcHostDomain = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocTxts
|
|
*
|
|
* Alloc memory for the char array representation of the TXT items.
|
|
*
|
|
*/
|
|
char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocTxts(size_t p_stLength) {
|
|
|
|
releaseTxts();
|
|
if (p_stLength) {
|
|
m_pcTxts = new char[p_stLength];
|
|
}
|
|
return m_pcTxts;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseTxts
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseTxts(void) {
|
|
|
|
if (m_pcTxts) {
|
|
delete[] m_pcTxts;
|
|
m_pcTxts = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#ifdef MDNS_IP4_SUPPORT
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP4Addresses
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP4Addresses(void) {
|
|
|
|
while (m_pIP4Addresses) {
|
|
stcIP4Address* pNext = m_pIP4Addresses->m_pNext;
|
|
delete m_pIP4Addresses;
|
|
m_pIP4Addresses = pNext;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP4Address
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP4Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* p_pIP4Address) {
|
|
|
|
bool bResult = false;
|
|
|
|
if (p_pIP4Address) {
|
|
p_pIP4Address->m_pNext = m_pIP4Addresses;
|
|
m_pIP4Addresses = p_pIP4Address;
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP4Address
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP4Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* p_pIP4Address) {
|
|
|
|
bool bResult = false;
|
|
|
|
if (p_pIP4Address) {
|
|
stcIP4Address* pPred = m_pIP4Addresses;
|
|
while ((pPred) &&
|
|
(pPred->m_pNext != p_pIP4Address)) {
|
|
pPred = pPred->m_pNext;
|
|
}
|
|
if (pPred) {
|
|
pPred->m_pNext = p_pIP4Address->m_pNext;
|
|
delete p_pIP4Address;
|
|
bResult = true;
|
|
}
|
|
else if (m_pIP4Addresses == p_pIP4Address) { // No predecesor, but first item
|
|
m_pIP4Addresses = p_pIP4Address->m_pNext;
|
|
delete p_pIP4Address;
|
|
bResult = true;
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address (const)
|
|
*/
|
|
const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address(const IPAddress& p_IPAddress) const {
|
|
|
|
return (stcIP4Address*)(((const stcAnswer*)this)->findIP4Address(p_IPAddress));
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address(const IPAddress& p_IPAddress) {
|
|
|
|
stcIP4Address* pIP4Address = m_pIP4Addresses;
|
|
while (pIP4Address) {
|
|
if (pIP4Address->m_IPAddress == p_IPAddress) {
|
|
break;
|
|
}
|
|
pIP4Address = pIP4Address->m_pNext;
|
|
}
|
|
return pIP4Address;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressCount
|
|
*/
|
|
uint32_t MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressCount(void) const {
|
|
|
|
uint32_t u32Count = 0;
|
|
|
|
stcIP4Address* pIP4Address = m_pIP4Addresses;
|
|
while (pIP4Address) {
|
|
++u32Count;
|
|
pIP4Address = pIP4Address->m_pNext;
|
|
}
|
|
return u32Count;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex(uint32_t p_u32Index) {
|
|
|
|
return (stcIP4Address*)(((const stcAnswer*)this)->IP4AddressAtIndex(p_u32Index));
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex (const)
|
|
*/
|
|
const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex(uint32_t p_u32Index) const {
|
|
|
|
const stcIP4Address* pIP4Address = 0;
|
|
|
|
if (((uint32_t)(-1) != p_u32Index) &&
|
|
(m_pIP4Addresses)) {
|
|
|
|
uint32_t u32Index;
|
|
for (pIP4Address=m_pIP4Addresses, u32Index=0; ((pIP4Address) && (u32Index<p_u32Index)); pIP4Address=pIP4Address->m_pNext, ++u32Index);
|
|
}
|
|
return pIP4Address;
|
|
}
|
|
#endif
|
|
|
|
#ifdef MDNS_IP6_SUPPORT
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP6Addresses
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP6Addresses(void) {
|
|
|
|
while (m_pIP6Addresses) {
|
|
stcIP6Address* pNext = m_pIP6Addresses->m_pNext;
|
|
delete m_pIP6Addresses;
|
|
m_pIP6Addresses = pNext;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP6Address
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP6Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* p_pIP6Address) {
|
|
|
|
bool bResult = false;
|
|
|
|
if (p_pIP6Address) {
|
|
p_pIP6Address->m_pNext = m_pIP6Addresses;
|
|
m_pIP6Addresses = p_pIP6Address;
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP6Address
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP6Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* p_pIP6Address) {
|
|
|
|
bool bResult = false;
|
|
|
|
if (p_pIP6Address) {
|
|
stcIP6Address* pPred = m_pIP6Addresses;
|
|
while ((pPred) &&
|
|
(pPred->m_pNext != p_pIP6Address)) {
|
|
pPred = pPred->m_pNext;
|
|
}
|
|
if (pPred) {
|
|
pPred->m_pNext = p_pIP6Address->m_pNext;
|
|
delete p_pIP6Address;
|
|
bResult = true;
|
|
}
|
|
else if (m_pIP6Addresses == p_pIP6Address) { // No predecesor, but first item
|
|
m_pIP6Addresses = p_pIP6Address->m_pNext;
|
|
delete p_pIP6Address;
|
|
bResult = true;
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address(const IP6Address& p_IPAddress) {
|
|
|
|
return (stcIP6Address*)(((const stcAnswer*)this)->findIP6Address(p_IPAddress));
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address (const)
|
|
*/
|
|
const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address(const IPAddress& p_IPAddress) const {
|
|
|
|
const stcIP6Address* pIP6Address = m_pIP6Addresses;
|
|
while (pIP6Address) {
|
|
if (p_IP6Address->m_IPAddress == p_IPAddress) {
|
|
break;
|
|
}
|
|
pIP6Address = pIP6Address->m_pNext;
|
|
}
|
|
return pIP6Address;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressCount
|
|
*/
|
|
uint32_t MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressCount(void) const {
|
|
|
|
uint32_t u32Count = 0;
|
|
|
|
stcIP6Address* pIP6Address = m_pIP6Addresses;
|
|
while (pIP6Address) {
|
|
++u32Count;
|
|
pIP6Address = pIP6Address->m_pNext;
|
|
}
|
|
return u32Count;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex (const)
|
|
*/
|
|
const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex(uint32_t p_u32Index) const {
|
|
|
|
return (stcIP6Address*)(((const stcAnswer*)this)->IP6AddressAtIndex(p_u32Index));
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex(uint32_t p_u32Index) {
|
|
|
|
stcIP6Address* pIP6Address = 0;
|
|
|
|
if (((uint32_t)(-1) != p_u32Index) &&
|
|
(m_pIP6Addresses)) {
|
|
|
|
uint32_t u32Index;
|
|
for (pIP6Address=m_pIP6Addresses, u32Index=0; ((pIP6Address) && (u32Index<p_u32Index)); pIP6Address=pIP6Address->m_pNext, ++u32Index);
|
|
}
|
|
return pIP6Address;
|
|
}
|
|
#endif
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSServiceQuery
|
|
*
|
|
* A service query object.
|
|
* A static query is flaged via 'm_bLegacyQuery'; while the function 'queryService'
|
|
* is waiting for answers, the internal flag 'm_bAwaitingAnswers' is set. When the
|
|
* timeout is reached, the flag is removed. These two flags are only used for static
|
|
* service queries.
|
|
* All answers to the service query are stored in 'm_pAnswers' list.
|
|
* Individual answers may be addressed by index (in the list of answers).
|
|
* Every time a answer component is added (or changes) in a dynamic service query,
|
|
* the callback 'm_fnCallback' is called.
|
|
* The answer list may be searched by service and host domain.
|
|
*
|
|
* Service query object may be connected to a linked list.
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::stcMDNSServiceQuery constructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcMDNSServiceQuery(void)
|
|
: m_pNext(0),
|
|
m_fnCallback(0),
|
|
m_bLegacyQuery(false),
|
|
m_u8SentCount(0),
|
|
m_ResendTimeout(esp8266::polledTimeout::oneShotMs::neverExpires),
|
|
m_bAwaitingAnswers(true),
|
|
m_pAnswers(0) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::~stcMDNSServiceQuery destructor
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::~stcMDNSServiceQuery(void) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::clear(void) {
|
|
|
|
m_fnCallback = 0;
|
|
m_bLegacyQuery = false;
|
|
m_u8SentCount = 0;
|
|
m_ResendTimeout.resetToNeverExpires();
|
|
m_bAwaitingAnswers = true;
|
|
while (m_pAnswers) {
|
|
stcAnswer* pNext = m_pAnswers->m_pNext;
|
|
delete m_pAnswers;
|
|
m_pAnswers = pNext;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::answerCount
|
|
*/
|
|
uint32_t MDNSResponder::stcMDNSServiceQuery::answerCount(void) const {
|
|
|
|
uint32_t u32Count = 0;
|
|
|
|
stcAnswer* pAnswer = m_pAnswers;
|
|
while (pAnswer) {
|
|
++u32Count;
|
|
pAnswer = pAnswer->m_pNext;
|
|
}
|
|
return u32Count;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::answerAtIndex
|
|
*/
|
|
const MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::answerAtIndex(uint32_t p_u32Index) const {
|
|
|
|
const stcAnswer* pAnswer = 0;
|
|
|
|
if (((uint32_t)(-1) != p_u32Index) &&
|
|
(m_pAnswers)) {
|
|
|
|
uint32_t u32Index;
|
|
for (pAnswer=m_pAnswers, u32Index=0; ((pAnswer) && (u32Index<p_u32Index)); pAnswer=pAnswer->m_pNext, ++u32Index);
|
|
}
|
|
return pAnswer;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::answerAtIndex
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::answerAtIndex(uint32_t p_u32Index) {
|
|
|
|
return (stcAnswer*)(((const stcMDNSServiceQuery*)this)->answerAtIndex(p_u32Index));
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::indexOfAnswer
|
|
*/
|
|
uint32_t MDNSResponder::stcMDNSServiceQuery::indexOfAnswer(const MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) const {
|
|
|
|
uint32_t u32Index = 0;
|
|
|
|
for (const stcAnswer* pAnswer=m_pAnswers; pAnswer; pAnswer=pAnswer->m_pNext, ++u32Index) {
|
|
if (pAnswer == p_pAnswer) {
|
|
return u32Index;
|
|
}
|
|
}
|
|
return ((uint32_t)(-1));
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::addAnswer
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::addAnswer(MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) {
|
|
|
|
bool bResult = false;
|
|
|
|
if (p_pAnswer) {
|
|
p_pAnswer->m_pNext = m_pAnswers;
|
|
m_pAnswers = p_pAnswer;
|
|
bResult = true;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::removeAnswer
|
|
*/
|
|
bool MDNSResponder::stcMDNSServiceQuery::removeAnswer(MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) {
|
|
|
|
bool bResult = false;
|
|
|
|
if (p_pAnswer) {
|
|
stcAnswer* pPred = m_pAnswers;
|
|
while ((pPred) &&
|
|
(pPred->m_pNext != p_pAnswer)) {
|
|
pPred = pPred->m_pNext;
|
|
}
|
|
if (pPred) {
|
|
pPred->m_pNext = p_pAnswer->m_pNext;
|
|
delete p_pAnswer;
|
|
bResult = true;
|
|
}
|
|
else if (m_pAnswers == p_pAnswer) { // No predecesor, but first item
|
|
m_pAnswers = p_pAnswer->m_pNext;
|
|
delete p_pAnswer;
|
|
bResult = true;
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::findAnswerForServiceDomain
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::findAnswerForServiceDomain(const MDNSResponder::stcMDNS_RRDomain& p_ServiceDomain) {
|
|
|
|
stcAnswer* pAnswer = m_pAnswers;
|
|
while (pAnswer) {
|
|
if (pAnswer->m_ServiceDomain == p_ServiceDomain) {
|
|
break;
|
|
}
|
|
pAnswer = pAnswer->m_pNext;
|
|
}
|
|
return pAnswer;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSServiceQuery::findAnswerForHostDomain
|
|
*/
|
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::findAnswerForHostDomain(const MDNSResponder::stcMDNS_RRDomain& p_HostDomain) {
|
|
|
|
stcAnswer* pAnswer = m_pAnswers;
|
|
while (pAnswer) {
|
|
if (pAnswer->m_HostDomain == p_HostDomain) {
|
|
break;
|
|
}
|
|
pAnswer = pAnswer->m_pNext;
|
|
}
|
|
return pAnswer;
|
|
}
|
|
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSSendParameter
|
|
*
|
|
* A 'collection' of properties and flags for one MDNS query or response.
|
|
* Mainly managed by the 'Control' functions.
|
|
* The current offset in the UPD output buffer is tracked to be able to do
|
|
* a simple host or service domain compression.
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem
|
|
*
|
|
* A cached host or service domain, incl. the offset in the UDP output buffer.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem::stcDomainCacheItem constructor
|
|
*/
|
|
MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem::stcDomainCacheItem(const void* p_pHostnameOrService,
|
|
bool p_bAdditionalData,
|
|
uint32_t p_u16Offset)
|
|
: m_pNext(0),
|
|
m_pHostnameOrService(p_pHostnameOrService),
|
|
m_bAdditionalData(p_bAdditionalData),
|
|
m_u16Offset(p_u16Offset) {
|
|
|
|
}
|
|
|
|
/**
|
|
* MDNSResponder::stcMDNSSendParameter
|
|
*/
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSSendParameter::stcMDNSSendParameter constructor
|
|
*/
|
|
MDNSResponder::stcMDNSSendParameter::stcMDNSSendParameter(void)
|
|
: m_pQuestions(0),
|
|
m_pDomainCacheItems(0) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSSendParameter::~stcMDNSSendParameter destructor
|
|
*/
|
|
MDNSResponder::stcMDNSSendParameter::~stcMDNSSendParameter(void) {
|
|
|
|
clear();
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSSendParameter::clear
|
|
*/
|
|
bool MDNSResponder::stcMDNSSendParameter::clear(void) {
|
|
|
|
m_u16ID = 0;
|
|
m_u8HostReplyMask = 0;
|
|
m_u16Offset = 0;
|
|
|
|
m_bLegacyQuery = false;
|
|
m_bResponse = false;
|
|
m_bAuthorative = false;
|
|
m_bUnicast = false;
|
|
m_bUnannounce = false;
|
|
|
|
m_bCacheFlush = true;
|
|
|
|
while (m_pQuestions) {
|
|
stcMDNS_RRQuestion* pNext = m_pQuestions->m_pNext;
|
|
delete m_pQuestions;
|
|
m_pQuestions = pNext;
|
|
}
|
|
while (m_pDomainCacheItems) {
|
|
stcDomainCacheItem* pNext = m_pDomainCacheItems->m_pNext;
|
|
delete m_pDomainCacheItems;
|
|
m_pDomainCacheItems = pNext;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSSendParameter::shiftOffset
|
|
*/
|
|
bool MDNSResponder::stcMDNSSendParameter::shiftOffset(uint16_t p_u16Shift) {
|
|
|
|
m_u16Offset += p_u16Shift;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSSendParameter::addDomainCacheItem
|
|
*/
|
|
bool MDNSResponder::stcMDNSSendParameter::addDomainCacheItem(const void* p_pHostnameOrService,
|
|
bool p_bAdditionalData,
|
|
uint16_t p_u16Offset) {
|
|
|
|
bool bResult = false;
|
|
|
|
stcDomainCacheItem* pNewItem = 0;
|
|
if ((p_pHostnameOrService) &&
|
|
(p_u16Offset) &&
|
|
((pNewItem = new stcDomainCacheItem(p_pHostnameOrService, p_bAdditionalData, p_u16Offset)))) {
|
|
|
|
pNewItem->m_pNext = m_pDomainCacheItems;
|
|
bResult = ((m_pDomainCacheItems = pNewItem));
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* MDNSResponder::stcMDNSSendParameter::findCachedDomainOffset
|
|
*/
|
|
uint16_t MDNSResponder::stcMDNSSendParameter::findCachedDomainOffset(const void* p_pHostnameOrService,
|
|
bool p_bAdditionalData) const {
|
|
|
|
const stcDomainCacheItem* pCacheItem = m_pDomainCacheItems;
|
|
|
|
for (; pCacheItem; pCacheItem=pCacheItem->m_pNext) {
|
|
if ((pCacheItem->m_pHostnameOrService == p_pHostnameOrService) &&
|
|
(pCacheItem->m_bAdditionalData == p_bAdditionalData)) { // Found cache item
|
|
break;
|
|
}
|
|
}
|
|
return (pCacheItem ? pCacheItem->m_u16Offset : 0);
|
|
}
|
|
|
|
} // namespace MDNSImplementation
|
|
|
|
} // namespace esp8266
|
|
|
|
|
|
|