LCOV - code coverage report
Current view: top level - lib/dnssd - Advertiser_ImplMinimalMdnsAllocator.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 49 59 83.1 %
Date: 2024-02-15 08:20:41 Functions: 33 33 100.0 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020 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             : 
      18             : #pragma once
      19             : 
      20             : #include <inttypes.h>
      21             : 
      22             : #include <lib/core/CHIPError.h>
      23             : #include <lib/dnssd/minimal_mdns/core/FlatAllocatedQName.h>
      24             : #include <lib/dnssd/minimal_mdns/core/QName.h>
      25             : #include <lib/dnssd/minimal_mdns/responders/IP.h>
      26             : #include <lib/dnssd/minimal_mdns/responders/Ptr.h>
      27             : #include <lib/dnssd/minimal_mdns/responders/QueryResponder.h>
      28             : #include <lib/dnssd/minimal_mdns/responders/RecordResponder.h>
      29             : #include <lib/dnssd/minimal_mdns/responders/Srv.h>
      30             : #include <lib/dnssd/minimal_mdns/responders/Txt.h>
      31             : #include <lib/support/CHIPMem.h>
      32             : #include <lib/support/logging/CHIPLogging.h>
      33             : 
      34             : namespace chip {
      35             : namespace Dnssd {
      36             : 
      37             : template <size_t kMaxRecords>
      38             : class QueryResponderAllocator
      39             : {
      40             : public:
      41          11 :     QueryResponderAllocator()
      42          11 :     {
      43          97 :         for (auto & responder : mAllocatedResponders)
      44             :         {
      45          86 :             responder = nullptr;
      46             :         }
      47         363 :         for (auto & name : mAllocatedQNameParts)
      48             :         {
      49         352 :             name = nullptr;
      50             :         }
      51          11 :     }
      52          11 :     ~QueryResponderAllocator() { Clear(); }
      53             : 
      54             :     /// Appends another responder to the internal replies.
      55             :     template <typename ResponderType, typename... Args>
      56         157 :     mdns::Minimal::QueryResponderSettings AddResponder(Args &&... args)
      57             :     {
      58         157 :         return AddAllocatedResponder(chip::Platform::New<ResponderType>(std::forward<Args>(args)...));
      59             :     }
      60             : 
      61             :     template <typename... Args>
      62         117 :     mdns::Minimal::FullQName AllocateQName(Args &&... names)
      63             :     {
      64         117 :         void * storage = AllocateQNameSpace(mdns::Minimal::FlatAllocatedQName::RequiredStorageSize(std::forward<Args>(names)...));
      65         117 :         if (storage == nullptr)
      66             :         {
      67           0 :             return mdns::Minimal::FullQName();
      68             :         }
      69         117 :         return mdns::Minimal::FlatAllocatedQName::Build(storage, std::forward<Args>(names)...);
      70             :     }
      71             : 
      72          20 :     mdns::Minimal::FullQName AllocateQNameFromArray(char const * const * names, size_t num)
      73             :     {
      74          20 :         void * storage = AllocateQNameSpace(mdns::Minimal::FlatAllocatedQName::RequiredStorageSizeFromArray(names, num));
      75          20 :         if (storage == nullptr)
      76             :         {
      77           0 :             return mdns::Minimal::FullQName();
      78             :         }
      79          20 :         return mdns::Minimal::FlatAllocatedQName::BuildFromArray(storage, names, num);
      80             :     }
      81             : 
      82             :     /// Sets the query responder to a blank state and frees up any
      83             :     /// allocated memory.
      84          73 :     void Clear()
      85             :     {
      86             :         // Init clears all responders, so that data can be freed
      87          73 :         mQueryResponder.Init();
      88             : 
      89             :         // Free all allocated data
      90         801 :         for (auto & responder : mAllocatedResponders)
      91             :         {
      92         728 :             if (responder != nullptr)
      93             :             {
      94         157 :                 chip::Platform::Delete(responder);
      95         157 :                 responder = nullptr;
      96             :             }
      97             :         }
      98             : 
      99        2409 :         for (auto & name : mAllocatedQNameParts)
     100             :         {
     101        2336 :             if (name != nullptr)
     102             :             {
     103         137 :                 chip::Platform::MemoryFree(name);
     104         137 :                 name = nullptr;
     105             :             }
     106             :         }
     107          73 :     }
     108         444 :     mdns::Minimal::QueryResponder<kMaxRecords + 1> * GetQueryResponder() { return &mQueryResponder; }
     109          12 :     const mdns::Minimal::RecordResponder * GetResponder(const mdns::Minimal::QType & qtype,
     110             :                                                         const mdns::Minimal::FullQName & qname) const
     111             :     {
     112          79 :         for (auto & responder : mAllocatedResponders)
     113             :         {
     114          68 :             if (responder != nullptr && responder->GetQType() == qtype && responder->GetQName() == qname)
     115             :             {
     116           1 :                 return responder;
     117             :             }
     118             :         }
     119          11 :         return nullptr;
     120             :     }
     121             :     bool IsEmpty() const
     122             :     {
     123             :         for (auto & responder : mAllocatedResponders)
     124             :         {
     125             :             if (responder != nullptr)
     126             :             {
     127             :                 return false;
     128             :             }
     129             :         }
     130             :         for (auto & name : mAllocatedQNameParts)
     131             :         {
     132             :             if (name != nullptr)
     133             :             {
     134             :                 return false;
     135             :             }
     136             :         }
     137             :         return true;
     138             :     }
     139             : 
     140             : protected:
     141             :     // For testing.
     142             :     size_t GetMaxAllocatedQNames() { return kMaxAllocatedQNameData; }
     143             :     void * GetQNamePart(size_t idx) { return mAllocatedQNameParts[idx]; }
     144             :     mdns::Minimal::RecordResponder * GetRecordResponder(size_t idx) { return mAllocatedResponders[idx]; }
     145             : 
     146             : private:
     147             :     static constexpr size_t kMaxAllocatedQNameData = 32;
     148             :     // dynamically allocated items
     149             :     mdns::Minimal::RecordResponder * mAllocatedResponders[kMaxRecords];
     150             :     void * mAllocatedQNameParts[kMaxAllocatedQNameData];
     151             :     // The QueryResponder needs 1 extra space to hold the record for itself.
     152             :     mdns::Minimal::QueryResponder<kMaxRecords + 1> mQueryResponder;
     153             : 
     154         157 :     mdns::Minimal::QueryResponderSettings AddAllocatedResponder(mdns::Minimal::RecordResponder * newResponder)
     155             :     {
     156         157 :         if (newResponder == nullptr)
     157             :         {
     158           0 :             ChipLogError(Discovery, "Responder memory allocation failed");
     159           0 :             return mdns::Minimal::QueryResponderSettings(); // failed
     160             :         }
     161             : 
     162         721 :         for (auto & responder : mAllocatedResponders)
     163             :         {
     164         721 :             if (responder != nullptr)
     165             :             {
     166         564 :                 continue;
     167             :             }
     168             : 
     169         157 :             responder = newResponder;
     170         157 :             return mQueryResponder.AddResponder(responder);
     171             :         }
     172             : 
     173           0 :         Platform::Delete(newResponder);
     174           0 :         ChipLogError(Discovery, "Failed to find free slot for adding a responder");
     175           0 :         return mdns::Minimal::QueryResponderSettings();
     176             :     }
     177             : 
     178         137 :     void * AllocateQNameSpace(size_t size)
     179             :     {
     180         564 :         for (auto & name : mAllocatedQNameParts)
     181             :         {
     182         564 :             if (name != nullptr)
     183             :             {
     184         427 :                 continue;
     185             :             }
     186             : 
     187         137 :             name = chip::Platform::MemoryAlloc(size);
     188         137 :             if (name == nullptr)
     189             :             {
     190           0 :                 ChipLogError(Discovery, "QName memory allocation failed");
     191             :             }
     192         137 :             return name;
     193             :         }
     194           0 :         ChipLogError(Discovery, "Failed to find free slot for adding a qname");
     195           0 :         return nullptr;
     196             :     }
     197             : };
     198             : 
     199             : } // namespace Dnssd
     200             : } // namespace chip

Generated by: LCOV version 1.14