LCOV - code coverage report
Current view: top level - lib/dnssd/minimal_mdns - Parser.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 57 74 77.0 %
Date: 2024-02-15 08:20:41 Functions: 4 4 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             : #include "Parser.h"
      19             : 
      20             : #include "Query.h"
      21             : 
      22             : #include <stdio.h>
      23             : 
      24             : namespace mdns {
      25             : namespace Minimal {
      26             : 
      27          56 : bool QueryData::Parse(const BytesRange & validData, const uint8_t ** start)
      28             : {
      29             :     // Structure is:
      30             :     //    QNAME
      31             :     //    TYPE
      32             :     //    CLASS (plus a flag for unicast)
      33             : 
      34          56 :     if (!validData.Contains(*start))
      35             :     {
      36           0 :         return false;
      37             :     }
      38             : 
      39          56 :     const uint8_t * nameEnd = nullptr;
      40             :     {
      41          56 :         SerializedQNameIterator it(validData, *start);
      42          56 :         nameEnd = it.FindDataEnd();
      43             :     }
      44          56 :     if (nameEnd == nullptr)
      45             :     {
      46           0 :         return false;
      47             :     }
      48             : 
      49          56 :     if (!validData.Contains(nameEnd + 3))
      50             :     {
      51           0 :         return false;
      52             :     }
      53             : 
      54             :     // TODO: should there be checks for valid mType/class?
      55             : 
      56          56 :     mType = static_cast<QType>(chip::Encoding::BigEndian::Read16(nameEnd));
      57             : 
      58          56 :     uint16_t klass = chip::Encoding::BigEndian::Read16(nameEnd);
      59             : 
      60          56 :     mAnswerViaUnicast = (klass & kQClassUnicastAnswerFlag) != 0;
      61          56 :     mClass            = static_cast<QClass>(klass & ~kQClassUnicastAnswerFlag);
      62          56 :     mNameIterator     = SerializedQNameIterator(validData, *start);
      63             : 
      64          56 :     *start = nameEnd;
      65             : 
      66          56 :     return true;
      67             : }
      68             : 
      69          32 : bool QueryData::Append(HeaderRef & hdr, RecordWriter & out) const
      70             : {
      71          32 :     if ((hdr.GetAdditionalCount() != 0) || (hdr.GetAnswerCount() != 0) || (hdr.GetAuthorityCount() != 0))
      72             :     {
      73           0 :         return false;
      74             :     }
      75             : 
      76          32 :     out.WriteQName(GetName())
      77          32 :         .Put16(static_cast<uint16_t>(mType))
      78          32 :         .Put16(static_cast<uint16_t>(static_cast<uint16_t>(mClass) | (mAnswerViaUnicast ? kQClassUnicastAnswerFlag : 0)));
      79             : 
      80          32 :     if (!out.Fit())
      81             :     {
      82           0 :         return false;
      83             :     }
      84             : 
      85          32 :     hdr.SetQueryCount(static_cast<uint16_t>(hdr.GetQueryCount() + 1));
      86          32 :     return true;
      87             : }
      88             : 
      89         688 : bool ResourceData::Parse(const BytesRange & validData, const uint8_t ** start)
      90             : {
      91             :     // Structure is:
      92             :     //    QNAME
      93             :     //    TYPE      (16 bit)
      94             :     //    CLASS     (16 bit)
      95             :     //    TTL       (32 bit)
      96             :     //    RDLENGTH  (16 bit)
      97             :     //    <DATA>    (RDLENGTH bytes)
      98         688 :     if (!validData.Contains(*start))
      99             :     {
     100           0 :         return false;
     101             :     }
     102             : 
     103         688 :     const uint8_t * nameEnd = nullptr;
     104             : 
     105             :     {
     106         688 :         SerializedQNameIterator it(validData, *start);
     107         688 :         nameEnd = it.FindDataEnd();
     108             :     }
     109         688 :     if (nameEnd == nullptr)
     110             :     {
     111           0 :         return false;
     112             :     }
     113             : 
     114             :     // need 3*u16 + u32
     115         688 :     if (!validData.Contains(nameEnd + 9))
     116             :     {
     117           0 :         return false;
     118             :     }
     119             : 
     120         688 :     mType  = static_cast<QType>(chip::Encoding::BigEndian::Read16(nameEnd));
     121         688 :     mClass = static_cast<QClass>(chip::Encoding::BigEndian::Read16(nameEnd));
     122         688 :     mTtl   = chip::Encoding::BigEndian::Read32(nameEnd);
     123             : 
     124         688 :     uint16_t dataLen = chip::Encoding::BigEndian::Read16(nameEnd); // resource data
     125             : 
     126         688 :     if (!validData.Contains(nameEnd + dataLen - 1))
     127             :     {
     128           0 :         return false; // no space for RDATA
     129             :     }
     130         688 :     mData = BytesRange(nameEnd, nameEnd + dataLen);
     131             : 
     132         688 :     mNameIterator = SerializedQNameIterator(validData, *start);
     133             : 
     134         688 :     *start = nameEnd + dataLen;
     135             : 
     136         688 :     return true;
     137             : }
     138             : 
     139         120 : bool ParsePacket(const BytesRange & packetData, ParserDelegate * delegate)
     140             : {
     141         120 :     if (packetData.Size() < static_cast<ptrdiff_t>(HeaderRef::kSizeBytes))
     142             :     {
     143           0 :         return false;
     144             :     }
     145             : 
     146             :     // header is used as const, so cast is safe
     147         120 :     ConstHeaderRef header(packetData.Start());
     148             : 
     149         120 :     if (!header.GetFlags().IsValidMdns())
     150             :     {
     151           0 :         return false;
     152             :     }
     153             : 
     154         120 :     delegate->OnHeader(header);
     155             : 
     156         120 :     const uint8_t * data = packetData.Start() + HeaderRef::kSizeBytes;
     157             : 
     158             :     {
     159         120 :         QueryData queryData;
     160         176 :         for (uint16_t i = 0; i < header.GetQueryCount(); i++)
     161             :         {
     162          56 :             if (!queryData.Parse(packetData, &data))
     163             :             {
     164           0 :                 return false;
     165             :             }
     166             : 
     167          56 :             delegate->OnQuery(queryData);
     168             :         }
     169             :     }
     170             : 
     171             :     {
     172         120 :         ResourceData resourceData;
     173         769 :         for (uint16_t i = 0; i < header.GetAnswerCount(); i++)
     174             :         {
     175         649 :             if (!resourceData.Parse(packetData, &data))
     176             :             {
     177           0 :                 return false;
     178             :             }
     179             : 
     180         649 :             delegate->OnResource(ResourceType::kAnswer, resourceData);
     181             :         }
     182             : 
     183         120 :         for (uint16_t i = 0; i < header.GetAuthorityCount(); i++)
     184             :         {
     185           0 :             if (!resourceData.Parse(packetData, &data))
     186             :             {
     187           0 :                 return false;
     188             :             }
     189             : 
     190           0 :             delegate->OnResource(ResourceType::kAuthority, resourceData);
     191             :         }
     192             : 
     193         142 :         for (uint16_t i = 0; i < header.GetAdditionalCount(); i++)
     194             :         {
     195          22 :             if (!resourceData.Parse(packetData, &data))
     196             :             {
     197           0 :                 return false;
     198             :             }
     199             : 
     200          22 :             delegate->OnResource(ResourceType::kAdditional, resourceData);
     201             :         }
     202             :     }
     203             : 
     204         120 :     return true;
     205             : }
     206             : 
     207             : } // namespace Minimal
     208             : } // namespace mdns

Generated by: LCOV version 1.14