1 // Copyright 2018 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 OSP_IMPL_DISCOVERY_MDNS_DOMAIN_NAME_H_
6 #define OSP_IMPL_DISCOVERY_MDNS_DOMAIN_NAME_H_
7 
8 #include <cstdint>
9 #include <ostream>
10 #include <string>
11 #include <vector>
12 
13 #include "absl/strings/string_view.h"
14 #include "platform/base/error.h"
15 #include "util/osp_logging.h"
16 
17 namespace openscreen {
18 namespace osp {
19 
20 struct DomainName {
21   static ErrorOr<DomainName> Append(const DomainName& first,
22                                     const DomainName& second);
23 
24   template <typename It>
FromLabelsDomainName25   static ErrorOr<DomainName> FromLabels(It first, It last) {
26     size_t total_length = 1;
27     for (auto label = first; label != last; ++label) {
28       if (label->size() > kDomainNameMaxLabelLength)
29         return Error::Code::kDomainNameLabelTooLong;
30 
31       total_length += label->size() + 1;
32     }
33     if (total_length > kDomainNameMaxLength)
34       return Error::Code::kDomainNameTooLong;
35 
36     DomainName result;
37     result.domain_name_.resize(total_length);
38     auto result_it = result.domain_name_.begin();
39     for (auto label = first; label != last; ++label) {
40       *result_it++ = static_cast<uint8_t>(label->size());
41       result_it = std::copy(label->begin(), label->end(), result_it);
42     }
43     *result_it = 0;
44     return std::move(result);
45   }
46 
47   static DomainName GetLocalDomain();
48 
49   static constexpr uint8_t kDomainNameMaxLabelLength = 63u;
50   static constexpr uint16_t kDomainNameMaxLength = 256u;
51 
52   DomainName();
53   explicit DomainName(std::vector<uint8_t>&& domain_name);
54   DomainName(const DomainName&);
55   DomainName(DomainName&&) noexcept;
56   ~DomainName();
57   DomainName& operator=(const DomainName&);
58   DomainName& operator=(DomainName&&) noexcept;
59 
60   bool operator==(const DomainName& other) const;
61   bool operator!=(const DomainName& other) const;
62 
63   bool EndsWithLocalDomain() const;
IsEmptyDomainName64   bool IsEmpty() const { return domain_name_.size() == 1 && !domain_name_[0]; }
65 
66   Error Append(const DomainName& after);
67   std::vector<absl::string_view> GetLabels() const;
68 
domain_nameDomainName69   const std::vector<uint8_t>& domain_name() const { return domain_name_; }
70 
71  private:
72   // RFC 1035 domain name format: sequence of 1 octet label length followed by
73   // label data, ending with a 0 octet.  May not exceed 256 bytes (including
74   // terminating 0).
75   // For example, openscreen.org would be encoded as:
76   // {10, 'o', 'p', 'e', 'n', 's', 'c', 'r', 'e', 'e', 'n',
77   //   3, 'o', 'r', 'g', 0}
78   std::vector<uint8_t> domain_name_;
79 };
80 
81 class DomainNameComparator {
82  public:
83   bool operator()(const DomainName& a, const DomainName& b) const;
84 };
85 
86 std::ostream& operator<<(std::ostream& os, const DomainName& domain_name);
87 
88 }  // namespace osp
89 }  // namespace openscreen
90 
91 #endif  // OSP_IMPL_DISCOVERY_MDNS_DOMAIN_NAME_H_
92