LCOV - code coverage report
Current view: top level - lib/address_resolve - AddressResolve.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 0 13 0.0 %
Date: 2024-02-15 08:20:41 Functions: 0 15 0.0 %

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

Generated by: LCOV version 1.14