LCOV - code coverage report
Current view: top level - lib/dnssd/minimal_mdns - AddressPolicy_DefaultImpl.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 62 69 89.9 %
Date: 2024-02-15 08:20:41 Functions: 11 11 100.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             : #include <lib/dnssd/minimal_mdns/AddressPolicy.h>
      18             : 
      19             : #include <lib/support/logging/CHIPLogging.h>
      20             : 
      21             : namespace mdns {
      22             : namespace Minimal {
      23             : namespace {
      24             : 
      25             : /// Checks if the current interface is powered on
      26             : /// and not local loopback.
      27             : template <typename T>
      28         148 : bool IsCurrentInterfaceUsable(T & iterator)
      29             : {
      30         148 :     if (!iterator.IsUp())
      31             :     {
      32           0 :         return false; // not a usable interface
      33             :     }
      34             :     char name[chip::Inet::InterfaceId::kMaxIfNameLength];
      35         148 :     if (iterator.GetInterfaceName(name, sizeof(name)) != CHIP_NO_ERROR)
      36             :     {
      37           0 :         ChipLogError(Discovery, "Failed to get interface name.");
      38           0 :         return false;
      39             :     }
      40             : 
      41             :     // TODO: need a better way to ignore local loopback interfaces/addresses
      42             :     // We do not want to listen on local loopback even though they are up and
      43             :     // support multicast
      44             :     //
      45             :     // Some way to detect 'is local looback' that is smarter (e.g. at least
      46             :     // strict string compare on linux instead of substring) would be better.
      47             :     //
      48             :     // This would reject likely valid interfaces like 'lollipop' or 'lostinspace'
      49         148 :     if (strncmp(name, "lo", 2) == 0)
      50             :     {
      51             :         /// local loopback interface is not usable by MDNS
      52          74 :         return false;
      53             :     }
      54          74 :     return true;
      55             : }
      56             : 
      57             : class AllInterfaces : public mdns::Minimal::ListenIterator
      58             : {
      59             : public:
      60          74 :     AllInterfaces() { SkipToFirstValidInterface(); }
      61             : 
      62         222 :     bool Next(chip::Inet::InterfaceId * id, chip::Inet::IPAddressType * type) override
      63             :     {
      64         222 :         if (!mIterator.HasCurrent())
      65             :         {
      66          74 :             return false;
      67             :         }
      68             : 
      69             : #if INET_CONFIG_ENABLE_IPV4
      70         148 :         if (mState == State::kIpV4)
      71             :         {
      72          74 :             mState = State::kIpV6;
      73             : 
      74          74 :             if (CurrentInterfaceHasAddressOfType(chip::Inet::IPAddressType::kIPv4))
      75             :             {
      76          74 :                 *id   = mIterator.GetInterfaceId();
      77          74 :                 *type = chip::Inet::IPAddressType::kIPv4;
      78          74 :                 return true;
      79             :             }
      80             :         }
      81             : #endif
      82             : 
      83             : #if INET_CONFIG_ENABLE_IPV4
      84          74 :         mState = State::kIpV4;
      85             : #endif
      86             : 
      87          74 :         bool haveResult = CurrentInterfaceHasAddressOfType(chip::Inet::IPAddressType::kIPv6);
      88          74 :         if (haveResult)
      89             :         {
      90          74 :             *id   = mIterator.GetInterfaceId();
      91          74 :             *type = chip::Inet::IPAddressType::kIPv6;
      92             :         }
      93             : 
      94          74 :         for (mIterator.Next(); SkipCurrentInterface(); mIterator.Next())
      95             :         {
      96             :         }
      97             : 
      98          74 :         if (haveResult)
      99             :         {
     100          74 :             return true;
     101             :         }
     102             : 
     103           0 :         return Next(id, type);
     104             :     }
     105             : 
     106             : private:
     107             : #if INET_CONFIG_ENABLE_IPV4
     108             :     enum class State
     109             :     {
     110             :         kIpV4,
     111             :         kIpV6,
     112             :     };
     113             :     State mState = State::kIpV4;
     114             : #endif
     115             :     chip::Inet::InterfaceIterator mIterator;
     116             : 
     117         148 :     void SkipToFirstValidInterface()
     118             :     {
     119             :         do
     120             :         {
     121         148 :             if (!SkipCurrentInterface())
     122             :             {
     123          74 :                 break;
     124             :             }
     125          74 :         } while (mIterator.Next());
     126          74 :     }
     127             : 
     128         222 :     bool SkipCurrentInterface()
     129             :     {
     130         222 :         if (!mIterator.HasCurrent())
     131             :         {
     132          74 :             return false; // nothing to try.
     133             :         }
     134             : 
     135         148 :         return !IsCurrentInterfaceUsable(mIterator);
     136             :     }
     137             : 
     138             :     bool CurrentInterfaceHasAddressOfType(chip::Inet::IPAddressType type);
     139             : };
     140             : 
     141             : class AllAddressesIterator : public mdns::Minimal::IpAddressIterator
     142             : {
     143             : public:
     144         446 :     AllAddressesIterator(chip::Inet::InterfaceId interfaceId, chip::Inet::IPAddressType addrType) :
     145         446 :         mInterfaceIdFilter(interfaceId), mAddrType(addrType)
     146         446 :     {}
     147             : 
     148        1364 :     bool Next(chip::Inet::IPAddress & dest)
     149             :     {
     150             :         while (true)
     151             :         {
     152        1364 :             if (!mIterator.HasCurrent())
     153             :             {
     154         482 :                 return false;
     155             :             }
     156             : 
     157        1180 :             if (mIterator.GetInterfaceId() != mInterfaceIdFilter)
     158             :             {
     159         658 :                 mIterator.Next();
     160         658 :                 continue;
     161             :             }
     162             : 
     163         522 :             CHIP_ERROR err = mIterator.GetAddress(dest);
     164         522 :             mIterator.Next();
     165             : 
     166         522 :             if (mAddrType != chip::Inet::IPAddressType::kAny)
     167             :             {
     168         522 :                 if (dest.Type() != mAddrType)
     169             :                 {
     170         224 :                     continue;
     171             :                 }
     172             :             }
     173             : 
     174         298 :             if (err != CHIP_NO_ERROR)
     175             :             {
     176           0 :                 ChipLogError(Discovery, "Failed to fetch interface IP address: %" CHIP_ERROR_FORMAT, err.Format());
     177           0 :                 continue;
     178             :             }
     179             : 
     180         298 :             return true;
     181         882 :         }
     182             :     }
     183             : 
     184             : private:
     185             :     const chip::Inet::InterfaceId mInterfaceIdFilter;
     186             :     const chip::Inet::IPAddressType mAddrType;
     187             :     chip::Inet::InterfaceAddressIterator mIterator;
     188             : };
     189             : 
     190         148 : bool AllInterfaces::CurrentInterfaceHasAddressOfType(chip::Inet::IPAddressType type)
     191             : {
     192             :     // mIterator.HasCurrent() must be true here.
     193         148 :     AllAddressesIterator addressIter(mIterator.GetInterfaceId(), type);
     194             :     chip::Inet::IPAddress addr;
     195         148 :     if (addressIter.Next(addr))
     196             :     {
     197         148 :         return true;
     198             :     }
     199             : 
     200           0 :     return false;
     201         148 : }
     202             : 
     203             : class DefaultAddressPolicy : public AddressPolicy
     204             : {
     205             : public:
     206          74 :     chip::Platform::UniquePtr<ListenIterator> GetListenEndpoints() override
     207             :     {
     208          74 :         return chip::Platform::UniquePtr<ListenIterator>(chip::Platform::New<AllInterfaces>());
     209             :     }
     210             : 
     211         298 :     chip::Platform::UniquePtr<IpAddressIterator> GetIpAddressesForEndpoint(chip::Inet::InterfaceId interfaceId,
     212             :                                                                            chip::Inet::IPAddressType type) override
     213             :     {
     214         298 :         return chip::Platform::UniquePtr<IpAddressIterator>(chip::Platform::New<AllAddressesIterator>(interfaceId, type));
     215             :     }
     216             : };
     217             : 
     218             : DefaultAddressPolicy gDefaultAddressPolicy;
     219             : 
     220             : } // namespace
     221             : 
     222          31 : void SetDefaultAddressPolicy()
     223             : {
     224          31 :     SetAddressPolicy(&gDefaultAddressPolicy);
     225          31 : }
     226             : 
     227             : } // namespace Minimal
     228             : } // namespace mdns

Generated by: LCOV version 1.14