• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_DNSSD_PUBLIC_DNS_SD_TXT_RECORD_H_
6 #define DISCOVERY_DNSSD_PUBLIC_DNS_SD_TXT_RECORD_H_
7 
8 #include <functional>
9 #include <map>
10 #include <set>
11 #include <string>
12 #include <vector>
13 
14 #include "platform/base/error.h"
15 
16 namespace openscreen {
17 namespace discovery {
18 
19 class DnsSdTxtRecord {
20  public:
21   using ValueRef = std::reference_wrapper<const std::vector<uint8_t>>;
22 
23   // Returns whether the provided key value pair is valid for a TXT record.
24   static bool IsValidTxtValue(const std::string& key,
25                               const std::vector<uint8_t>& value);
26   static bool IsValidTxtValue(const std::string& key, const std::string& value);
27   static bool IsValidTxtValue(const std::string& key, uint8_t value);
28 
29   // Sets the value currently stored in this DNS-SD TXT record. Returns error
30   // if the provided key is already set or if either the key or value is
31   // invalid, and Error::None() otherwise. Keys are case-insensitive. Setting a
32   // value or flag which was already set will overwrite the previous one, and
33   // setting a value with a key which was previously associated with a flag
34   // erases the flag's value and vice versa.
35   Error SetValue(const std::string& key, std::vector<uint8_t> value);
36   Error SetValue(const std::string& key, const std::string& value);
37   Error SetFlag(const std::string& key, bool value);
38 
39   // Reads the value associated with the provided key, or an error if the key
40   // is mapped to the opposite type or the query is otherwise invalid. Keys are
41   // case-insensitive.
42   // NOTE: If GetValue is called on a key assigned to a flag, an ItemNotFound
43   // error will be returned. If GetFlag is called on a key assigned to a value,
44   // 'false' will be returned.
45   ErrorOr<ValueRef> GetValue(const std::string& key) const;
46   ErrorOr<bool> GetFlag(const std::string& key) const;
47 
48   // Clears an existing TxtRecord value associated with the given key. If the
49   // key is not found, these methods return successfully without removing any
50   // keys.
51   // NOTE: If ClearValue is called on a key assigned to a flag (or ClearFlag for
52   // a value), no error will be returned but no value will be cleared.
53   Error ClearValue(const std::string& key);
54   Error ClearFlag(const std::string& key);
55 
IsEmpty()56   inline bool IsEmpty() const {
57     return key_value_txt_.empty() && boolean_txt_.empty();
58   }
59 
60   // Returns the data for the TXT record represented by this object.
61   // Specifically, it returns a vector containing an entry for each string s in
62   // boolean_txt_ of the form 's' (without quotes) and an entry for each key-
63   // value pair (key, value) in key_value_txt_ of the form 'key=value' (without
64   // quotes).
65   std::vector<std::vector<uint8_t>> GetData() const;
66 
67  private:
68   struct CaseInsensitiveComparison {
69     bool operator()(const std::string& lhs, const std::string& rhs) const;
70   };
71 
72   // Validations for keys and (key, value) pairs.
73   static bool IsKeyValid(const std::string& key);
74 
75   // Set of (key, value) pairs associated with this TXT record.
76   // NOTE: The same string name can only occur in one of key_value_txt_,
77   // boolean_txt_.
78   std::map<std::string, std::vector<uint8_t>, CaseInsensitiveComparison>
79       key_value_txt_;
80 
81   // Set of named booleans associated with this TXT record. All stored boolean
82   // names are 'true', as 'false' values are not stored.
83   // NOTE: The same string name can only occur in one of key_value_txt_,
84   // boolean_txt_.
85   std::set<std::string, CaseInsensitiveComparison> boolean_txt_;
86 
87   friend bool operator<(const DnsSdTxtRecord& lhs, const DnsSdTxtRecord& rhs);
88 };
89 
90 inline bool operator<(const DnsSdTxtRecord& lhs, const DnsSdTxtRecord& rhs) {
91   if (lhs.boolean_txt_ != rhs.boolean_txt_) {
92     return lhs.boolean_txt_ < rhs.boolean_txt_;
93   }
94 
95   return lhs.key_value_txt_ < rhs.key_value_txt_;
96 }
97 
98 inline bool operator>(const DnsSdTxtRecord& lhs, const DnsSdTxtRecord& rhs) {
99   return rhs < lhs;
100 }
101 
102 inline bool operator<=(const DnsSdTxtRecord& lhs, const DnsSdTxtRecord& rhs) {
103   return !(rhs > lhs);
104 }
105 
106 inline bool operator>=(const DnsSdTxtRecord& lhs, const DnsSdTxtRecord& rhs) {
107   return !(rhs < lhs);
108 }
109 
110 inline bool operator==(const DnsSdTxtRecord& lhs, const DnsSdTxtRecord& rhs) {
111   return lhs <= rhs && lhs >= rhs;
112 }
113 
114 inline bool operator!=(const DnsSdTxtRecord& lhs, const DnsSdTxtRecord& rhs) {
115   return !(lhs == rhs);
116 }
117 
118 }  // namespace discovery
119 }  // namespace openscreen
120 
121 #endif  // DISCOVERY_DNSSD_PUBLIC_DNS_SD_TXT_RECORD_H_
122