Skip to content

Commit

Permalink
Merge 49ddccf into 0bdeccb
Browse files Browse the repository at this point in the history
  • Loading branch information
Marty Leisner authored Aug 26, 2021
2 parents 0bdeccb + 49ddccf commit 4043411
Show file tree
Hide file tree
Showing 8 changed files with 407 additions and 2 deletions.
12 changes: 12 additions & 0 deletions src/lib/core/CHIPConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -2405,6 +2405,18 @@ extern const char CHIP_NON_PRODUCTION_MARKER[];
#define CHIP_COMMISSIONING_HINT_INDEX_PRESS_RESET_UNTIL_BLINK_WITH_POWER 11
#endif

/**
* @def CHIP_CONFIG_MDNS_CACHE_SIZE
*
* @brief
* Define the size of the MDNS cache
*
* If CHIP_CONFIG_MDNS_CACHE_SIZE is 0, the builtin cache is not used.
*
*/
#ifndef CHIP_CONFIG_MDNS_CACHE_SIZE
#define CHIP_CONFIG_MDNS_CACHE_SIZE 20
#endif
/**
* @name Interaction Model object pool configuration.
*
Expand Down
1 change: 1 addition & 0 deletions src/lib/mdns/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ static_library("mdns") {

sources = [
"Advertiser.h",
"MdnsCache.h",
"Resolver.h",
"ServiceNaming.cpp",
"ServiceNaming.h",
Expand Down
37 changes: 37 additions & 0 deletions src/lib/mdns/Discovery_ImplPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

#include "Discovery_ImplPlatform.h"
#include "MdnsCache.h"

#include <inttypes.h>

Expand All @@ -35,6 +36,9 @@ namespace chip {
namespace Mdns {

DiscoveryImplPlatform DiscoveryImplPlatform::sManager;
#if CHIP_CONFIG_MDNS_CACHE_SIZE > 0
MdnsCache<CHIP_CONFIG_MDNS_CACHE_SIZE> DiscoveryImplPlatform::sMdnsCache;
#endif

DiscoveryImplPlatform::DiscoveryImplPlatform() = default;

Expand Down Expand Up @@ -437,6 +441,28 @@ CHIP_ERROR DiscoveryImplPlatform::ResolveNodeId(const PeerId & peerId, Inet::IPA
{
ReturnErrorOnFailure(Init());

Inet::IPAddress addr;
uint16_t port;
Inet::InterfaceId iface;

/* see if the entry is cached and use it.... */

#if CHIP_CONFIG_MDNS_CACHE_SIZE > 0
if (sMdnsCache.Lookup(peerId, addr, port, iface) == CHIP_NO_ERROR)
{
ResolvedNodeData nodeData;

nodeData.mInterfaceId = iface;
nodeData.mPort = port;
nodeData.mAddress = addr;
nodeData.mPeerId = peerId;

mResolverDelegate->OnNodeIdResolved(nodeData);

return CHIP_NO_ERROR;
}
#endif

MdnsService service;

ReturnErrorOnFailure(MakeInstanceName(service.mName, sizeof(service.mName), peerId));
Expand Down Expand Up @@ -539,6 +565,17 @@ void DiscoveryImplPlatform::HandleNodeIdResolve(void * context, MdnsService * re
return;
}

#if CHIP_CONFIG_MDNS_CACHE_SIZE > 0
// TODO -- define appropriate TTL, for now use 2000 msec (rfc default)
// figure out way to use TTL value from mDNS packet in future update
error = mgr->sMdnsCache.Insert(nodeData.mPeerId, result->mAddress.Value(), result->mPort, result->mInterface, 2 * 1000);

if (CHIP_NO_ERROR != error)
{
ChipLogError(Discovery, "MdnsCache insert failed with %s", chip::ErrorStr(error));
}
#endif

Platform::CopyString(nodeData.mHostName, result->mHostName);
nodeData.mInterfaceId = result->mInterface;
nodeData.mAddress = result->mAddress.ValueOr({});
Expand Down
4 changes: 4 additions & 0 deletions src/lib/mdns/Discovery_ImplPlatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <lib/mdns/Resolver.h>
#include <lib/mdns/platform/Mdns.h>
#include <platform/CHIPDeviceConfig.h>
#include <lib/mdns/MdnsCache.h>

// Enable detailed mDNS logging for publish
#undef DETAIL_LOGGING
Expand Down Expand Up @@ -97,6 +98,9 @@ class DiscoveryImplPlatform : public ServiceAdvertiser, public Resolver
ResolverDelegate * mResolverDelegate = nullptr;

static DiscoveryImplPlatform sManager;
#if CHIP_CONFIG_MDNS_CACHE_SIZE > 0
static MdnsCache <CHIP_CONFIG_MDNS_CACHE_SIZE> sIPCache;
#endif
};

} // namespace Mdns
Expand Down
205 changes: 205 additions & 0 deletions src/lib/mdns/MdnsCache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <cstdint>

#include <core/CHIPError.h>
#include <core/PeerId.h>
#include <inet/IPAddress.h>
#include <inet/InetInterface.h>
#include <inet/InetLayer.h>
#include <system/SystemTimer.h>
#include <system/TimeSource.h>

// set MDNS_LOGGING to enable logging -- sometimes used in debug/test programs -- traces the behavior
#ifdef MDNS_LOGGING
#define MdnsLogProgress ChipLogProgress
#else
#define MdnsLogProgress(...)
#endif

namespace chip {
namespace Mdns {

template <size_t CACHE_SIZE>
class MdnsCache
{
public:
MdnsCache() : elementsUsed(CACHE_SIZE)
{
for (MdnsCacheEntry & e : mLookupTable)
{
// each unused entry decrements the count
MarkEntryUnused(e);
}
MdnsLogProgress(Discovery, "construct mdns cache of size %ld", CACHE_SIZE);
}

// insert this entry into the cache.
// return error if cache is full
// TODO: have an eviction policy so if the cache is full, an entry may be deleted.
// One policy may be Least-time-to-live
CHIP_ERROR Insert(PeerId peerId, const Inet::IPAddress & addr, uint16_t port, Inet::InterfaceId iface, uint32_t TTLms)
{
const uint64_t currentTime = mTimeSource.GetCurrentMonotonicTimeMs();

MdnsCacheEntry * entry;

entry = FindPeerId(peerId, currentTime);
if (entry)
{
// update timeout if found entry
entry->expiryTime = currentTime + TTLms;
entry->TTL = TTLms; // in case it changes */
return CHIP_NO_ERROR;
}

VerifyOrReturnError(entry = findSlot(currentTime), CHIP_ERROR_TOO_MANY_KEYS);

// have a free slot for this entry
entry->peerId = peerId;
entry->ipAddr = addr;
entry->port = port;
entry->ifaceId = iface;
entry->TTL = TTLms;
entry->expiryTime = currentTime + TTLms;
elementsUsed++;

return CHIP_NO_ERROR;
}

CHIP_ERROR Delete(PeerId peerId)
{
MdnsCacheEntry * pentry;
const uint64_t currentTime = mTimeSource.GetCurrentMonotonicTimeMs();

VerifyOrReturnError(pentry = FindPeerId(peerId, currentTime), CHIP_ERROR_KEY_NOT_FOUND);

MarkEntryUnused(*pentry);
return CHIP_NO_ERROR;
}

// given a peerId, find the parameters if its in the cache, or return error
CHIP_ERROR Lookup(PeerId peerId, Inet::IPAddress & addr, uint16_t & port, Inet::InterfaceId & iface)
{
MdnsCacheEntry * pentry;
const uint64_t currentTime = mTimeSource.GetCurrentMonotonicTimeMs();

VerifyOrReturnError(pentry = FindPeerId(peerId, currentTime), CHIP_ERROR_KEY_NOT_FOUND);

addr = pentry->ipAddr;
port = pentry->port;
iface = pentry->ifaceId;

return CHIP_NO_ERROR;
}

// only useful if MDNS_LOGGING is set. If not used, should be optimized out
void DumpCache()
{
int i = 0;

MdnsLogProgress(Discovery, "cache size = %d", elementsUsed);
for (MdnsCacheEntry & e : mLookupTable)
{
if (e.peerId == nullPeerId)
{
MdnsLogProgress(Discovery, "Entry %d unused", i);
}
else
{
char address[100];

e.ipAddr.ToString(address, sizeof address);
MdnsLogProgress(Discovery, "Entry %d: node %lx fabric %lx, port = %d, address = %s", i, e.peerId.GetNodeId(),
e.peerId.GetFabricId(), e.port, address);
}
i++;
}
}

private:
struct MdnsCacheEntry
{
PeerId peerId;
Inet::IPAddress ipAddr;
uint16_t port;
Inet::InterfaceId ifaceId;
uint64_t TTL; // from mdns record -- units?
uint64_t expiryTime; // units?
};
PeerId nullPeerId; // indicates a cache entry is unused
int elementsUsed; // running count of how many entries are used -- for a sanity check

MdnsCacheEntry mLookupTable[CACHE_SIZE];
Time::TimeSource<Time::Source::kSystem> mTimeSource;

MdnsCacheEntry * findSlot(uint64_t currentTime)
{
for (MdnsCacheEntry & entry : mLookupTable)
{
if (entry.peerId == nullPeerId)
return &entry;

if (entry.expiryTime <= currentTime)
{
MarkEntryUnused(entry);
return &entry;
}
}
return nullptr;
}

MdnsCacheEntry * FindPeerId(PeerId peerId, uint64_t current_time)
{
for (MdnsCacheEntry & entry : mLookupTable)
{
if (entry.peerId == peerId)
{
if (entry.expiryTime < current_time)
{
MarkEntryUnused(entry);
break; // return nullptr
}
else
return &entry;
}
if (entry.peerId != nullPeerId && entry.expiryTime < current_time)
{
MarkEntryUnused(entry);
}
}

return nullptr;
}

// have a method to mark ununused -- so its easy to change
void MarkEntryUnused(MdnsCacheEntry & pentry)
{
pentry.peerId = nullPeerId;
elementsUsed--;
}
};

#ifndef MDNS_LOGGING
#undef MdnsLogProgress
#endif

} // namespace Mdns
} // namespace chip
11 changes: 9 additions & 2 deletions src/lib/mdns/Resolver_ImplMinimalMdns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@
* limitations under the License.
*/

#include "MdnsCache.h"
#include "Resolver.h"

#include <limits>

#include "MinimalMdnsServer.h"
#include "ServiceNaming.h"

#include <core/CHIPConfig.h>

#include <mdns/TxtFields.h>
#include <mdns/minimal/Parser.h>
#include <mdns/minimal/QueryBuilder.h>
Expand Down Expand Up @@ -62,12 +65,13 @@ constexpr size_t kMdnsMaxPacketSize = 1024;
constexpr uint16_t kMdnsPort = 5353;

using namespace mdns::Minimal;
using MdnsCacheType = Mdns::MdnsCache<CHIP_CONFIG_MDNS_CACHE_SIZE>;

class PacketDataReporter : public ParserDelegate
{
public:
PacketDataReporter(ResolverDelegate * delegate, chip::Inet::InterfaceId interfaceId, DiscoveryType discoveryType,
const BytesRange & packet) :
const BytesRange & packet, MdnsCacheType & mdnsCache) :
mDelegate(delegate),
mDiscoveryType(discoveryType), mPacketRange(packet)
{
Expand Down Expand Up @@ -357,6 +361,9 @@ class MinMdnsResolver : public Resolver, public MdnsPacketDelegate
}
static constexpr int kMaxQnameSize = 100;
char qnameStorage[kMaxQnameSize];
// should this be static?
// original version had: static Mdns::IPCache<CHIP_CONFIG_IPCACHE_SIZE, CHIP_CONFIG_TTL_MS> sIPCache;
MdnsCacheType sMdnsCache;
};

void MinMdnsResolver::OnMdnsPacketData(const BytesRange & data, const chip::Inet::IPPacketInfo * info)
Expand All @@ -366,7 +373,7 @@ void MinMdnsResolver::OnMdnsPacketData(const BytesRange & data, const chip::Inet
return;
}

PacketDataReporter reporter(mDelegate, info->Interface, mDiscoveryType, data);
PacketDataReporter reporter(mDelegate, info->Interface, mDiscoveryType, data, sMdnsCache);

if (!ParsePacket(data, &reporter))
{
Expand Down
1 change: 1 addition & 0 deletions src/lib/mdns/tests/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ chip_test_suite("tests") {
output_name = "libMdnsTests"

test_sources = [
"TestMdnsCache.cpp",
"TestServiceNaming.cpp",
"TestTxtFields.cpp",
]
Expand Down
Loading

0 comments on commit 4043411

Please sign in to comment.