Skip to content

Commit

Permalink
Move MinMdns to single udp endpoint.
Browse files Browse the repository at this point in the history
  • Loading branch information
andy31415 authored and andreilitvin committed Jun 13, 2023
1 parent 643f7aa commit cebf2ed
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 483 deletions.
4 changes: 2 additions & 2 deletions examples/minimal-mdns/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ class QuerySplitter
std::vector<std::string> mStorage;
};

void BroadcastPacket(mdns::Minimal::ServerBase * server)
void BroadcastPacket(mdns::Minimal::Server * server)
{
System::PacketBufferHandle buffer = System::PacketBufferHandle::New(kMdnsMaxPacketSize);
VerifyOrDie(!buffer.IsNull());
Expand Down Expand Up @@ -295,7 +295,7 @@ void BroadcastPacket(mdns::Minimal::ServerBase * server)
}
}

mdns::Minimal::Server<20> gMdnsServer;
mdns::Minimal::Server gMdnsServer;

} // namespace

Expand Down
6 changes: 3 additions & 3 deletions examples/minimal-mdns/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ class ReplyDelegate : public mdns::Minimal::ServerDelegate, public mdns::Minimal
uint16_t mMessageId = 0;
};

mdns::Minimal::Server<10 /* endpoints */> gMdnsServer;
mdns::Minimal::Server gMdnsServer;

void StopSignalHandler(int signal)
{
Expand Down Expand Up @@ -217,11 +217,11 @@ int main(int argc, char ** args)
mdns::Minimal::QueryResponder<16 /* maxRecords */> queryResponder;

mdns::Minimal::QNamePart tcpServiceName[] = { Dnssd::kOperationalServiceName, Dnssd::kOperationalProtocol,
Dnssd::kLocalDomain };
Dnssd::kLocalDomain };
mdns::Minimal::QNamePart tcpServerServiceName[] = { gOptions.instanceName, Dnssd::kOperationalServiceName,
Dnssd::kOperationalProtocol, Dnssd::kLocalDomain };
mdns::Minimal::QNamePart udpServiceName[] = { Dnssd::kCommissionableServiceName, Dnssd::kCommissionProtocol,
Dnssd::kLocalDomain };
Dnssd::kLocalDomain };
mdns::Minimal::QNamePart udpServerServiceName[] = { gOptions.instanceName, Dnssd::kCommissionableServiceName,
Dnssd::kCommissionProtocol, Dnssd::kLocalDomain };

Expand Down
169 changes: 78 additions & 91 deletions src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,8 @@ class AdvertiserMinMdns : public ServiceAdvertiser,
/// removes all records by advertising a 0 TTL)
void AdvertiseRecords(BroadcastAdvertiseType type);

/// Determine if advertisement on the specified interface/address is ok given the
/// interfaces on which the mDNS server is listening
bool ShouldAdvertiseOn(const chip::Inet::InterfaceId id, const chip::Inet::IPAddress & addr);
// Clears the internal broadcast throttle
void ResetBroadcastThrottle();

FullQName GetCommissioningTxtEntries(const CommissionAdvertisingParameters & params);
FullQName GetOperationalTxtEntries(OperationalQueryAllocator::Allocator * allocator,
Expand Down Expand Up @@ -300,6 +299,34 @@ class AdvertiserMinMdns : public ServiceAdvertiser,
};
};

/// Finds the first ip address of the given address type on the given interface
CHIP_ERROR GetFirstIpAddress(Inet::InterfaceId interfaceId, Inet::IPAddressType addressType, Inet::IPAddress & address)
{
UniquePtr<IpAddressIterator> allIps = GetAddressPolicy()->GetIpAddressesForEndpoint(interfaceId, addressType);

if (!allIps)
{
return CHIP_ERROR_NOT_FOUND;
}

if (!allIps->Next(address))
{
return CHIP_ERROR_NOT_FOUND;
}

return CHIP_NO_ERROR;
}

void AdvertiserMinMdns::ResetBroadcastThrottle()
{
for (auto & it : mOperationalResponders)
{
it.GetAllocator()->GetQueryResponder()->ClearBroadcastThrottle();
}
mQueryResponderAllocatorCommissionable.GetQueryResponder()->ClearBroadcastThrottle();
mQueryResponderAllocatorCommissioner.GetQueryResponder()->ClearBroadcastThrottle();
}

void AdvertiserMinMdns::OnMdnsPacketData(const BytesRange & data, const chip::Inet::IPPacketInfo * info)
{
#ifdef DETAIL_LOGGING
Expand Down Expand Up @@ -856,35 +883,6 @@ FullQName AdvertiserMinMdns::GetCommissioningTxtEntries(const CommissionAdvertis
return allocator->AllocateQNameFromArray(txtFields, numTxtFields);
}

bool AdvertiserMinMdns::ShouldAdvertiseOn(const chip::Inet::InterfaceId id, const chip::Inet::IPAddress & addr)
{
auto & server = GlobalMinimalMdnsServer::Server();

bool result = false;

server.ForEachEndPoints([&](auto * info) {
if (info->mListenUdp == nullptr)
{
return chip::Loop::Continue;
}

if (info->mInterfaceId != id)
{
return chip::Loop::Continue;
}

if (info->mAddressType != addr.Type())
{
return chip::Loop::Continue;
}

result = true;
return chip::Loop::Break;
});

return result;
}

void AdvertiserMinMdns::AdvertiseRecords(BroadcastAdvertiseType type)
{
ResponseConfiguration responseConfiguration;
Expand All @@ -902,73 +900,62 @@ void AdvertiserMinMdns::AdvertiseRecords(BroadcastAdvertiseType type)

while (allInterfaces->Next(&interfaceId, &addressType))
{
UniquePtr<IpAddressIterator> allIps = GetAddressPolicy()->GetIpAddressesForEndpoint(interfaceId, addressType);
VerifyOrDieWithMsg(allIps != nullptr, Discovery, "Failed to allocate memory for ip addresses.");
chip::Inet::IPPacketInfo packetInfo;

Inet::IPAddress ipAddress;
while (allIps->Next(ipAddress))
{
if (!ShouldAdvertiseOn(interfaceId, ipAddress))
{
continue;
}
packetInfo.Clear();

chip::Inet::IPPacketInfo packetInfo;
// Attempt to get a "Real" IP address since `Type()` on a broadcast address
// always returns IPAddressType::kAny
CHIP_ERROR err = GetFirstIpAddress(interfaceId, addressType, packetInfo.SrcAddress);

packetInfo.Clear();
packetInfo.SrcAddress = ipAddress;
if (ipAddress.IsIPv4())
{
BroadcastIpAddresses::GetIpv4Into(packetInfo.DestAddress);
}
else
{
BroadcastIpAddresses::GetIpv6Into(packetInfo.DestAddress);
}
packetInfo.SrcPort = kMdnsPort;
packetInfo.DestPort = kMdnsPort;
packetInfo.Interface = interfaceId;

// Advertise all records
//
// TODO: Consider advertising delta changes.
//
// Current advertisement does not have a concept of "delta" to only
// advertise changes. Current implementation is to always
// 1. advertise TTL=0 (clear all caches)
// 2. advertise available records (with longer TTL)
//
// It would be nice if we could selectively advertise what changes, like
// send TTL=0 for anything removed/about to be removed (and only those),
// then only advertise new items added.
//
// This optimization likely will take more logic and state storage, so
// for now it is not done.
QueryData queryData(QType::PTR, QClass::IN, false /* unicast */);
queryData.SetIsInternalBroadcast(true);

for (auto & it : mOperationalResponders)
{
it.GetAllocator()->GetQueryResponder()->ClearBroadcastThrottle();
}
mQueryResponderAllocatorCommissionable.GetQueryResponder()->ClearBroadcastThrottle();
mQueryResponderAllocatorCommissioner.GetQueryResponder()->ClearBroadcastThrottle();
if (err != CHIP_NO_ERROR)
{
ChipLogError(Discovery, "Failed to find a suitable IP address to advertise: %" CHIP_ERROR_FORMAT,
err.Format());
continue;
}

CHIP_ERROR err = mResponseSender.Respond(0, queryData, &packetInfo, responseConfiguration);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Discovery, "Failed to advertise records: %" CHIP_ERROR_FORMAT, err.Format());
}
if (addressType != chip::Inet::IPAddressType::kIPv6)
{
BroadcastIpAddresses::GetIpv4Into(packetInfo.DestAddress);
}
else
{
BroadcastIpAddresses::GetIpv6Into(packetInfo.DestAddress);
}
packetInfo.SrcPort = kMdnsPort;
packetInfo.DestPort = kMdnsPort;
packetInfo.Interface = interfaceId;

// Advertise all records
//
// TODO: Consider advertising delta changes.
//
// Current advertisement does not have a concept of "delta" to only
// advertise changes. Current implementation is to always
// 1. advertise TTL=0 (clear all caches)
// 2. advertise available records (with longer TTL)
//
// It would be nice if we could selectively advertise what changes, like
// send TTL=0 for anything removed/about to be removed (and only those),
// then only advertise new items added.
//
// This optimization likely will take more logic and state storage, so
// for now it is not done.
QueryData queryData(QType::PTR, QClass::IN, false /* unicast */);
queryData.SetIsInternalBroadcast(true);

ResetBroadcastThrottle();

err = mResponseSender.Respond(0, queryData, &packetInfo, responseConfiguration);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Discovery, "Failed to advertise records: %" CHIP_ERROR_FORMAT, err.Format());
}
}

// Once all automatic broadcasts are done, allow immediate replies once.
for (auto & it : mOperationalResponders)
{
it.GetAllocator()->GetQueryResponder()->ClearBroadcastThrottle();
}
mQueryResponderAllocatorCommissionable.GetQueryResponder()->ClearBroadcastThrottle();
mQueryResponderAllocatorCommissioner.GetQueryResponder()->ClearBroadcastThrottle();
ResetBroadcastThrottle();
}

AdvertiserMinMdns gAdvertiser;
Expand Down
14 changes: 6 additions & 8 deletions src/lib/dnssd/MinimalMdnsServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,12 @@ class MdnsPacketDelegate
class GlobalMinimalMdnsServer : public mdns::Minimal::ServerDelegate
{
public:
static constexpr size_t kMaxEndPoints = 30;

using ServerType = mdns::Minimal::Server<kMaxEndPoints>;
using ServerType = mdns::Minimal::Server;

GlobalMinimalMdnsServer();

static GlobalMinimalMdnsServer & Instance();
static mdns::Minimal::ServerBase & Server()
static mdns::Minimal::Server & Server()
{
if (Instance().mReplacementServer != nullptr)
{
Expand Down Expand Up @@ -77,13 +75,13 @@ class GlobalMinimalMdnsServer : public mdns::Minimal::ServerDelegate
}
}

void SetReplacementServer(mdns::Minimal::ServerBase * server) { mReplacementServer = server; }
void SetReplacementServer(mdns::Minimal::Server * server) { mReplacementServer = server; }

private:
ServerType mServer;
mdns::Minimal::ServerBase * mReplacementServer = nullptr;
MdnsPacketDelegate * mQueryDelegate = nullptr;
MdnsPacketDelegate * mResponseDelegate = nullptr;
mdns::Minimal::Server * mReplacementServer = nullptr;
MdnsPacketDelegate * mQueryDelegate = nullptr;
MdnsPacketDelegate * mResponseDelegate = nullptr;
};

} // namespace Dnssd
Expand Down
10 changes: 9 additions & 1 deletion src/lib/dnssd/minimal_mdns/ResponseSender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,15 @@ CHIP_ERROR ResponseSender::FlushReply()
else
{
#if CHIP_MINMDNS_HIGH_VERBOSITY
ChipLogDetail(Discovery, "Broadcasting mDns reply for query from %s", srcAddressString);
char interfaceName[chip::Inet::InterfaceId::kMaxIfNameLength];
mSendState.GetSourceInterfaceId().GetInterfaceName(interfaceName, sizeof(interfaceName));

const char * interfaceType = mSendState.GetSourceAddress().Type() == chip::Inet::IPAddressType::kIPv4
? "IPv4"
: (mSendState.GetSourceAddress().Type() == chip::Inet::IPAddressType::kIPv6 ? "IPv6" : "???");

ChipLogDetail(Discovery, "Broadcasting mDns reply for query from %s to %s / %s", srcAddressString, interfaceName,
interfaceType);
#endif
ReturnErrorOnFailure(mServer->BroadcastSend(mResponseBuilder.ReleasePacket(), kMdnsStandardPort,
mSendState.GetSourceInterfaceId(), mSendState.GetSourceAddress().Type()));
Expand Down
6 changes: 3 additions & 3 deletions src/lib/dnssd/minimal_mdns/ResponseSender.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class ResponseSendingState
class ResponseSender : public ResponderDelegate
{
public:
ResponseSender(ServerBase * server) : mServer(server) {}
ResponseSender(Server * server) : mServer(server) {}

CHIP_ERROR AddQueryResponder(QueryResponderBase * queryResponder);
CHIP_ERROR RemoveQueryResponder(QueryResponderBase * queryResponder);
Expand All @@ -118,13 +118,13 @@ class ResponseSender : public ResponderDelegate
// Implementation of ResponderDelegate
void AddResponse(const ResourceRecord & record) override;

void SetServer(ServerBase * server) { mServer = server; }
void SetServer(Server * server) { mServer = server; }

private:
CHIP_ERROR FlushReply();
CHIP_ERROR PrepareNewReplyPacket();

ServerBase * mServer;
Server * mServer;
QueryResponderPtrPool mResponders = {};

/// Current send state
Expand Down
Loading

0 comments on commit cebf2ed

Please sign in to comment.