Matter SDK Coverage Report
Current view: top level - lib/dnssd/minimal_mdns/core - DnsHeader.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 86.5 % 37 32
Test Date: 2025-01-17 19:00:11 Functions: 89.7 % 29 26

            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              : #pragma once
      18              : 
      19              : #include <lib/core/CHIPEncoding.h>
      20              : 
      21              : namespace mdns {
      22              : namespace Minimal {
      23              : 
      24              : /**
      25              :  * Wrapper around a MDNS bit-packed flags in a DNS header as defined in
      26              :  * RFC 1035 and RFC 6762
      27              :  *
      28              :  * | 0| 1 2 3 4| 5| 6| 7| 8| 9| 0| 1| 2 3 4 5 |
      29              :  * |QR| OPCODE |AA|TC|RD|RA| Z|AD|CD| RCODE   |
      30              :  *
      31              :  * RFC 6762 states:
      32              :  *   - OPCODE must be 0 on transmission and queries received that are not 0 MUST be ignored
      33              :  *   - RCODE must be 0 on transmission and messages received with non-zero must be silently ignored
      34              :  *
      35              :  *   - AA (Authoritative Answer) MUST be 0 on transmission, ignored on reception
      36              :  *   - RD (Recursion desired) MUST be 0 on transmission, ignored on reception
      37              :  *   - RA (Recursion available) MUST be 0 on transmission, ignored on reception
      38              :  *   - AD (Authentic data) MUST be 0 on transmission, ignored on reception
      39              :  *   - CD (Checking Disabled) MUST be 0 on transmission, ignored on reception
      40              :  *
      41              :  * Accessors are only provided on useful values
      42              :  */
      43              : class BitPackedFlags
      44              : {
      45              : public:
      46          102 :     explicit BitPackedFlags(uint16_t value) : mValue(value) {}
      47              : 
      48           50 :     uint16_t RawValue() const { return mValue & kMdnsNonIgnoredMask; }
      49              : 
      50           12 :     bool IsQuery() const { return (mValue & kIsResponseMask) == 0; }
      51            0 :     BitPackedFlags & SetQuery() { return ClearMask(kIsResponseMask); }
      52              : 
      53           24 :     bool IsResponse() const { return (mValue & kIsResponseMask) == kIsResponseMask; }
      54          104 :     BitPackedFlags & SetResponse() { return SetMask(kIsResponseMask); }
      55              : 
      56              :     bool IsAuthoritative() const { return (mValue & kAuthoritativeMask) == kAuthoritativeMask; }
      57          104 :     BitPackedFlags & SetAuthoritative() { return SetMask(kAuthoritativeMask); }
      58              : 
      59              :     bool IsTruncated() const { return (mValue & kTruncationMask) != 0; }
      60           10 :     BitPackedFlags & SetTruncated(bool value) { return value ? SetMask(kTruncationMask) : ClearMask(kTruncationMask); }
      61              : 
      62              :     /// Validates that the message does not need to be ignored according to
      63              :     /// RFC 6762
      64           24 :     bool IsValidMdns() const { return (mValue & (kOpcodeMask | kReturnCodeMask)) == 0; }
      65              : 
      66              : private:
      67              :     uint16_t mValue = 0;
      68              : 
      69            0 :     inline BitPackedFlags & ClearMask(uint16_t mask)
      70              :     {
      71            0 :         mValue &= static_cast<uint16_t>(~mask);
      72            0 :         return *this;
      73              :     }
      74              : 
      75          218 :     inline BitPackedFlags & SetMask(uint16_t mask)
      76              :     {
      77          218 :         mValue |= mask;
      78          218 :         return *this;
      79              :     }
      80              : 
      81              :     // Mask to limit values to what RFC 6762 consideres useful
      82              :     // 1111 1110 0000 0000 = FE0F
      83              :     // TODO(cecille): need to better document this value. Why is the comment different than the value?
      84              :     static constexpr uint16_t kMdnsNonIgnoredMask = 0x8E08;
      85              :     static constexpr uint16_t kAuthoritativeMask  = 0x0400;
      86              :     static constexpr uint16_t kIsResponseMask     = 0x8000;
      87              :     static constexpr uint16_t kOpcodeMask         = 0x7000;
      88              :     static constexpr uint16_t kTruncationMask     = 0x0200;
      89              :     static constexpr uint16_t kReturnCodeMask     = 0x000F;
      90              : };
      91              : 
      92              : /**
      93              :  * Allows operations on a DNS header. A DNS Header is defined in RFC 1035
      94              :  * and looks like this:
      95              :  *
      96              :  * | 0| 1 2 3 4| 5| 6| 7| 8| 9| 0| 1| 2 3 4 5 |
      97              :  * |               Message ID                 |
      98              :  * |QR| OPCODE |AA|TC|RD|RA| Z|AD|CD| RCODE   |
      99              :  * |       Items in QUESTION Section          |
     100              :  * |       Items in ANSWER Section            |
     101              :  * |       Items in AUTHORITY Section         |
     102              :  * |       Items in ADDITIONAL Section        |
     103              :  */
     104              : class ConstHeaderRef
     105              : {
     106              : public:
     107              :     static constexpr size_t kSizeBytes = 12; /// size of a DNS header structure
     108          122 :     ConstHeaderRef(const uint8_t * buffer) : mBuffer(buffer) {}
     109              : 
     110           24 :     uint16_t GetMessageId() const { return Get16At(kMessageIdOffset); }
     111              : 
     112          102 :     BitPackedFlags GetFlags() const { return BitPackedFlags(Get16At(kFlagsOffset)); }
     113              : 
     114           48 :     uint16_t GetQueryCount() const { return Get16At(kQueryCountOffset); }
     115          677 :     uint16_t GetAnswerCount() const { return Get16At(kAnswerCountOffset); }
     116          447 :     uint16_t GetAuthorityCount() const { return Get16At(kAuthorityCountOffset); }
     117          419 :     uint16_t GetAdditionalCount() const { return Get16At(kAdditionalCountOffset); }
     118              : 
     119              : protected:
     120              :     const uint8_t * mBuffer;
     121              : 
     122         1641 :     inline uint16_t Get16At(size_t offset) const { return chip::Encoding::BigEndian::Get16(mBuffer + offset); }
     123              :     uint16_t GetRawFlags() const { return Get16At(kFlagsOffset); }
     124              : 
     125              :     static constexpr size_t kMessageIdOffset       = 0;
     126              :     static constexpr size_t kFlagsOffset           = 2;
     127              :     static constexpr size_t kQueryCountOffset      = 4;
     128              :     static constexpr size_t kAnswerCountOffset     = 6;
     129              :     static constexpr size_t kAuthorityCountOffset  = 8;
     130              :     static constexpr size_t kAdditionalCountOffset = 10;
     131              : };
     132              : 
     133              : class HeaderRef : public ConstHeaderRef
     134              : {
     135              : public:
     136           98 :     HeaderRef(uint8_t * buffer) : ConstHeaderRef(buffer) {}
     137              :     HeaderRef(const HeaderRef & other)             = default;
     138              :     HeaderRef & operator=(const HeaderRef & other) = default;
     139              : 
     140           50 :     HeaderRef & Clear()
     141              :     {
     142           50 :         memset(GetWritable(), 0, kSizeBytes);
     143           50 :         return *this;
     144              :     }
     145              : 
     146           50 :     HeaderRef & SetMessageId(uint16_t value) { return Set16At(kMessageIdOffset, value); }
     147           50 :     HeaderRef & SetFlags(BitPackedFlags flags) { return Set16At(kFlagsOffset, flags.RawValue()); }
     148            0 :     HeaderRef & SetQueryCount(uint16_t value) { return Set16At(kQueryCountOffset, value); }
     149          776 :     HeaderRef & SetAnswerCount(uint16_t value) { return Set16At(kAnswerCountOffset, value); }
     150            1 :     HeaderRef & SetAuthorityCount(uint16_t value) { return Set16At(kAuthorityCountOffset, value); }
     151           25 :     HeaderRef & SetAdditionalCount(uint16_t value) { return Set16At(kAdditionalCountOffset, value); }
     152              : 
     153              : private:
     154              :     /// Returns the internal buffer as writable. Const-cast is correct because
     155              :     /// the construct took a non-const buffer as well.
     156          519 :     uint8_t * GetWritable() { return const_cast<uint8_t *>(mBuffer); }
     157              : 
     158          486 :     inline HeaderRef & Set16At(size_t offset, uint16_t value)
     159              :     {
     160          486 :         chip::Encoding::BigEndian::Put16(GetWritable() + offset, value);
     161          486 :         return *this;
     162              :     }
     163              : 
     164              :     HeaderRef & SetRawFlags(uint16_t value) { return Set16At(kFlagsOffset, value); }
     165              : };
     166              : 
     167              : } // namespace Minimal
     168              : } // namespace mdns
        

Generated by: LCOV version 2.0-1