1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef DISCOVERY_MDNS_MDNS_READER_H_
6 #define DISCOVERY_MDNS_MDNS_READER_H_
7 
8 #include <utility>
9 #include <vector>
10 
11 #include "discovery/mdns/mdns_records.h"
12 #include "platform/base/error.h"
13 #include "util/big_endian.h"
14 
15 namespace openscreen {
16 namespace discovery {
17 
18 struct Config;
19 
20 class MdnsReader : public BigEndianReader {
21  public:
22   MdnsReader(const Config& config, const uint8_t* buffer, size_t length);
23 
24   using BigEndianReader::Read;
25 
26   // The following methods return true if the method was able to successfully
27   // read the value to |out| and advances current() to point right past the read
28   // data. Returns false if the method failed to read the value to |out|,
29   // current() remains unchanged.
30   bool Read(TxtRecordRdata::Entry* out);
31   bool Read(DomainName* out);
32   bool Read(RawRecordRdata* out);
33   bool Read(SrvRecordRdata* out);
34   bool Read(ARecordRdata* out);
35   bool Read(AAAARecordRdata* out);
36   bool Read(PtrRecordRdata* out);
37   bool Read(TxtRecordRdata* out);
38   bool Read(NsecRecordRdata* out);
39 
40   // Reads a DNS resource record with its RDATA.
41   // The correct type of RDATA to be read is determined by the type
42   // specified in the record.
43   bool Read(MdnsRecord* out);
44   bool Read(MdnsQuestion* out);
45 
46   // Reads multiple mDNS questions and records that are a part of
47   // a mDNS message being read.
48   ErrorOr<MdnsMessage> Read();
49 
50  private:
51   struct NsecBitMapField {
52     uint8_t window_block;
53     uint8_t bitmap_length;
54     const uint8_t* bitmap;
55   };
56 
57   bool Read(IPAddress::Version version, IPAddress* out);
58   bool Read(DnsType type, Rdata* out);
59   bool Read(Header* out);
60   bool Read(std::vector<DnsType>* types, int remaining_length);
61   bool Read(NsecBitMapField* out);
62 
63   template <class ItemType>
Read(uint16_t count,std::vector<ItemType> * out)64   bool Read(uint16_t count, std::vector<ItemType>* out) {
65     Cursor cursor(this);
66     out->reserve(count);
67     for (uint16_t i = 0; i < count; ++i) {
68       ItemType entry;
69       if (!Read(&entry)) {
70         return false;
71       }
72       out->emplace_back(std::move(entry));
73     }
74     cursor.Commit();
75     return true;
76   }
77 
78   template <class RdataType>
Read(Rdata * out)79   bool Read(Rdata* out) {
80     RdataType rdata;
81     if (Read(&rdata)) {
82       *out = std::move(rdata);
83       return true;
84     }
85     return false;
86   }
87 
88   // Maximum allowed size for the rdata in any received record.
89   const size_t kMaximumAllowedRdataSize;
90 };
91 
92 }  // namespace discovery
93 }  // namespace openscreen
94 
95 #endif  // DISCOVERY_MDNS_MDNS_READER_H_
96