Matter SDK Coverage Report
Current view: top level - lib/address_resolve - AddressResolve.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 7.7 % 13 1
Test Date: 2025-01-17 19:00:11 Functions: 6.7 % 15 1

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2022 Project CHIP Authors
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : #pragma once
      18              : 
      19              : #include <lib/core/PeerId.h>
      20              : #include <lib/support/IntrusiveList.h>
      21              : #include <messaging/ReliableMessageProtocolConfig.h>
      22              : #include <system/SystemClock.h>
      23              : #include <system/SystemLayer.h>
      24              : #include <transport/raw/PeerAddress.h>
      25              : 
      26              : namespace chip {
      27              : namespace AddressResolve {
      28              : 
      29              : /// Contains resolve information received from nodes. Contains all information
      30              : /// bits that are considered useful but does not contain a full DNSSD data
      31              : /// structure since not all DNSSD data is useful during operational processing.
      32              : struct ResolveResult
      33              : {
      34              :     Transport::PeerAddress address;
      35              :     ReliableMessageProtocolConfig mrpRemoteConfig;
      36              :     bool supportsTcpServer   = false;
      37              :     bool supportsTcpClient   = false;
      38              :     bool isICDOperatingAsLIT = false;
      39              : 
      40            0 :     ResolveResult() : address(Transport::Type::kUdp), mrpRemoteConfig(GetDefaultMRPConfig()) {}
      41              : };
      42              : 
      43              : /// Represents an object interested in callbacks for a resolve operation.
      44              : class NodeListener
      45              : {
      46              : public:
      47            0 :     NodeListener()          = default;
      48            0 :     virtual ~NodeListener() = default;
      49              : 
      50              :     /// Callback executed once only for a lookup, when the final address of a
      51              :     /// node is considered to be the best choice for reachability.
      52              :     ///
      53              :     /// The callback is expected to be executed within the CHIP event loop
      54              :     /// thread.
      55              :     virtual void OnNodeAddressResolved(const PeerId & peerId, const ResolveResult & result) = 0;
      56              : 
      57              :     /// Node resolution failure - occurs only once for a lookup, when an address
      58              :     /// could not be resolved - generally due to a timeout or due to DNSSD
      59              :     /// infrastructure returning an error.
      60              :     ///
      61              :     /// The callback is expected to be executed within the CHIP event loop
      62              :     /// thread.
      63              :     virtual void OnNodeAddressResolutionFailed(const PeerId & peerId, CHIP_ERROR reason) = 0;
      64              : };
      65              : 
      66              : /// Represents an active Address resolution lookup.
      67              : ///
      68              : /// Implementations extend this class with implementation-specific data like
      69              : /// storing the 'last known good address' and 'scores' or any additional data
      70              : /// required to figure out when a resolve is ok.
      71              : class NodeLookupHandleBase : public IntrusiveListNodeBase<>
      72              : {
      73              : public:
      74            0 :     NodeLookupHandleBase() {}
      75            0 :     virtual ~NodeLookupHandleBase() {}
      76              : 
      77              :     // While active, resolve handles are maintained in an internal list
      78              :     // to be processed, so copying their values (i.e. pointers) is not
      79              :     // allowed.
      80              :     NodeLookupHandleBase(const NodeLookupHandleBase &)             = delete;
      81              :     NodeLookupHandleBase & operator=(const NodeLookupHandleBase &) = delete;
      82              : 
      83            0 :     void SetListener(NodeListener * listener) { mListener = listener; }
      84            0 :     NodeListener * GetListener() { return mListener; }
      85              : 
      86              :     /// Convenience method that is more readable than 'IsInList'
      87            0 :     inline bool IsActive() const { return IntrusiveListNodeBase::IsInList(); }
      88              : 
      89              : protected:
      90              :     NodeListener * mListener = nullptr;
      91              : };
      92              : 
      93              : /// Represents a request to perform a single node lookup
      94              : /// Contains all the information that should be looked for as well as
      95              : /// extra timeout configurations.
      96              : class NodeLookupRequest
      97              : {
      98              : public:
      99            0 :     NodeLookupRequest() {}
     100            0 :     NodeLookupRequest(const PeerId & peerId) : mPeerId(peerId) {}
     101              : 
     102              :     NodeLookupRequest(const NodeLookupRequest &)             = default;
     103              :     NodeLookupRequest & operator=(const NodeLookupRequest &) = default;
     104              : 
     105           29 :     const PeerId & GetPeerId() const { return mPeerId; }
     106            0 :     System::Clock::Milliseconds32 GetMinLookupTime() const { return mMinLookupTimeMs; }
     107            0 :     System::Clock::Milliseconds32 GetMaxLookupTime() const { return mMaxLookupTimeMs; }
     108              : 
     109              :     /// The minimum lookup time is how much to wait for additional DNSSD
     110              :     /// queries even if a reply has already been received or to allow for
     111              :     /// additional heuristics regarding node choice to succeed.
     112              :     /// Example heuristics and considerations:
     113              :     ///   - ping/ping6 could be used as an indicator of reachability. NOTE that
     114              :     ///     not all devices may respond to ping, so this would only be an
     115              :     ///     additional signal to accept/increase suitability score of an address
     116              :     ///     and should NOT be used as a reject if no ping response
     117              :     ///   - At lookup time, if the source ip of a dns reply is contained in the
     118              :     ///     list of server ips, that is a great indication of routability and
     119              :     ///     this minlookuptime could be bypassed altogether.
     120              :     ///
     121              :     /// Implementations for DNSSD may choose to return responses one by one
     122              :     /// for addresses (e.g. Platform mdns does this at the time this was written)
     123              :     /// or different interfaces will return separate 'done resolving' calls.
     124              :     ///
     125              :     /// If the min lookup time is set to 0, implementations are expected to call
     126              :     /// 'OnNodeAddressResolved' as soon as the first DNSSD response is received.
     127              :     NodeLookupRequest & SetMinLookupTime(System::Clock::Milliseconds32 value)
     128              :     {
     129              :         mMinLookupTimeMs = value;
     130              :         return *this;
     131              :     }
     132              : 
     133              :     /// The maximum lookup time is how much to wait until a TIMEOUT error is
     134              :     /// declared.
     135              :     ///
     136              :     /// If a DNSSD response is received before this max timeout, then
     137              :     /// OnNodeAddressResolved will be called on listener objects (immediately)
     138              :     /// if the first DNSSD reply arrives after MinLookupTimeMs has expired.
     139              :     NodeLookupRequest & SetMaxLookupTime(System::Clock::Milliseconds32 value)
     140              :     {
     141              :         mMaxLookupTimeMs = value;
     142              :         return *this;
     143              :     }
     144              : 
     145              : private:
     146              :     static_assert((CHIP_CONFIG_ADDRESS_RESOLVE_MIN_LOOKUP_TIME_MS) <= (CHIP_CONFIG_ADDRESS_RESOLVE_MAX_LOOKUP_TIME_MS),
     147              :                   "AddressResolveMinLookupTime must be equal or less than AddressResolveMaxLookupTime");
     148              :     static_assert((CHIP_CONFIG_ADDRESS_RESOLVE_MIN_LOOKUP_TIME_MS) >= 0,
     149              :                   "AddressResolveMinLookupTime must be equal or greater than 0");
     150              :     static_assert((CHIP_CONFIG_ADDRESS_RESOLVE_MAX_LOOKUP_TIME_MS) < UINT32_MAX,
     151              :                   "AddressResolveMaxLookupTime must be less than UINT32_MAX");
     152              :     static constexpr uint32_t kMinLookupTimeMsDefault = CHIP_CONFIG_ADDRESS_RESOLVE_MIN_LOOKUP_TIME_MS;
     153              :     static constexpr uint32_t kMaxLookupTimeMsDefault = CHIP_CONFIG_ADDRESS_RESOLVE_MAX_LOOKUP_TIME_MS;
     154              : 
     155              :     PeerId mPeerId;
     156              :     System::Clock::Milliseconds32 mMinLookupTimeMs{ kMinLookupTimeMsDefault };
     157              :     System::Clock::Milliseconds32 mMaxLookupTimeMs{ kMaxLookupTimeMsDefault };
     158              : };
     159              : 
     160              : /// These things are expected to be defined by the implementation header.
     161              : namespace Impl {
     162              : 
     163              : // The NodeLookup handle is a CONCRETE implementation that
     164              : // MUST derive from NodeLookupHandleBase
     165              : //
     166              : // The underlying reason is that this handle is used to hold memory for
     167              : // lookup metadata, so that resolvers do not need to maintain a likely unused
     168              : // pool of 'active lookup' metadata.
     169              : //
     170              : // The side-effect of this is that the Impl::NodeLookupHandle is exposed to
     171              : // clients for sizeof() memory purposes.
     172              : //
     173              : // Clients MUST only use the interface in NodeLookupHandleBase and assume all
     174              : // other methods/content is implementation defined.
     175              : class NodeLookupHandle;
     176              : 
     177              : } // namespace Impl
     178              : 
     179              : class Resolver
     180              : {
     181              : public:
     182              :     /// Enumeration defining how to handle cancel callbacks during operation
     183              :     /// cancellation.
     184              :     enum class FailureCallback
     185              :     {
     186              :         Call, // Call the failure callback
     187              :         Skip  // do not call the failure callback (generally silent operation)
     188              :     };
     189              : 
     190              :     virtual ~Resolver();
     191              : 
     192              :     /// Expected to be called at least once before the resolver is ever
     193              :     /// used.
     194              :     ///
     195              :     /// Expected to override global setting of DNSSD callback for addres resolution
     196              :     /// and may use the underlying system layer for timers and other functionality.
     197              :     ///
     198              :     /// If called multiple times, it is expected that the input systemLayer does
     199              :     /// not change.
     200              :     virtual CHIP_ERROR Init(System::Layer * systemLayer) = 0;
     201              : 
     202              :     /// Initiate a node lookup for a particular node and use the specified
     203              :     /// Lookup handle to keep track of node resolution
     204              :     ///
     205              :     /// If this returns CHIP_NO_ERROR, the following is expected:
     206              :     ///   - exactly one of the listener OnNodeAddressResolved
     207              :     ///     or OnNodeAddressResolutionFailed will be called at a later time
     208              :     ///   - handle must NOT be destroyed while the lookup is in progress (it
     209              :     ///     is part of an internal 'lookup list')
     210              :     ///   - handle must NOT be reused (the lookup is done on a per-node basis
     211              :     ///     and maintains lookup data internally while the operation is still
     212              :     ///     in progress)
     213              :     virtual CHIP_ERROR LookupNode(const NodeLookupRequest & request, Impl::NodeLookupHandle & handle) = 0;
     214              : 
     215              :     /// Inform the Lookup handle that the previous node lookup was not
     216              :     /// sufficient for the purpose of the caller (e.g establishing a session
     217              :     /// fails with the result of the previous lookup), and that more data is
     218              :     /// needed.
     219              :     ///
     220              :     /// This method must be called on a handle that is no longer active to
     221              :     /// succeed.
     222              :     ///
     223              :     /// If the handle is no longer active and has results that have not been
     224              :     /// delivered to the listener yet, the listener's OnNodeAddressResolved will
     225              :     /// be called synchronously before the method returns.  Note that depending
     226              :     /// on the listener implementation this can end up destroying the handle
     227              :     /// and/or the listener.
     228              :     ///
     229              :     /// This method will return CHIP_NO_ERROR if and only if it has called
     230              :     /// OnNodeAddressResolved.
     231              :     ///
     232              :     /// This method will return CHIP_ERROR_INCORRECT_STATE if the handle is
     233              :     /// still active.
     234              :     ///
     235              :     /// This method will return CHIP_ERROR_NOT_FOUND if there are no more
     236              :     /// results.
     237              :     ///
     238              :     /// This method may return other errors in some cases.
     239              :     virtual CHIP_ERROR TryNextResult(Impl::NodeLookupHandle & handle) = 0;
     240              : 
     241              :     /// Stops an active lookup request.
     242              :     ///
     243              :     /// Caller controlls weather the `fail` callback of the handle is invoked or not by using
     244              :     /// the `cancel_method` argument.
     245              :     ///
     246              :     /// Note that there is no default cancel_method on purpose, so that the caller has to make
     247              :     /// a clear decision if the callback should or should not be invoked.
     248              :     virtual CHIP_ERROR CancelLookup(Impl::NodeLookupHandle & handle, FailureCallback cancel_method) = 0;
     249              : 
     250              :     /// Shut down any active resolves
     251              :     ///
     252              :     /// Will immediately fail any scheduled resolve calls and will refuse to register
     253              :     /// any new lookups until re-initialized.
     254              :     virtual void Shutdown() = 0;
     255              : 
     256              :     /// Expected to be provided by the implementation.
     257              :     static Resolver & Instance();
     258              : };
     259              : 
     260              : } // namespace AddressResolve
     261              : } // namespace chip
     262              : 
     263              : // Include the required platform header for the actual implementation, if defined.
     264              : // Otherwise assume the default implementation is being used.
     265              : // Expectations of this include:
     266              : //   - define the `Impl::NodeLookupHandle` deriving from NodeLookupHandleBase
     267              : //   - corresponding CPP file should provide a valid Resolver::Instance()
     268              : //     implementation
     269              : #ifdef CHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER
     270              : #include CHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER
     271              : #else
     272              : #include <lib/address_resolve/AddressResolve_DefaultImpl.h>
     273              : #endif
     274              : 
     275              : namespace chip {
     276              : namespace AddressResolve {
     277              : 
     278              : // Make the code easy to read: do not reach into Impl.
     279              : using NodeLookupHandle = Impl::NodeLookupHandle;
     280              : 
     281              : } // namespace AddressResolve
     282              : } // namespace chip
        

Generated by: LCOV version 2.0-1