1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard
5*3f982cf4SFabien Sanglard #ifndef DISCOVERY_DNSSD_IMPL_SERVICE_KEY_H_
6*3f982cf4SFabien Sanglard #define DISCOVERY_DNSSD_IMPL_SERVICE_KEY_H_
7*3f982cf4SFabien Sanglard
8*3f982cf4SFabien Sanglard #include <string>
9*3f982cf4SFabien Sanglard #include <utility>
10*3f982cf4SFabien Sanglard
11*3f982cf4SFabien Sanglard #include "absl/strings/string_view.h"
12*3f982cf4SFabien Sanglard #include "platform/base/error.h"
13*3f982cf4SFabien Sanglard
14*3f982cf4SFabien Sanglard namespace openscreen {
15*3f982cf4SFabien Sanglard namespace discovery {
16*3f982cf4SFabien Sanglard
17*3f982cf4SFabien Sanglard class DomainName;
18*3f982cf4SFabien Sanglard class MdnsRecord;
19*3f982cf4SFabien Sanglard
20*3f982cf4SFabien Sanglard // This class is intended to be used as the key of a std::unordered_map or a
21*3f982cf4SFabien Sanglard // std::map when referencing data related to a service type
22*3f982cf4SFabien Sanglard class ServiceKey {
23*3f982cf4SFabien Sanglard public:
24*3f982cf4SFabien Sanglard // NOTE: The record provided must have valid service domain labels.
25*3f982cf4SFabien Sanglard explicit ServiceKey(const MdnsRecord& record);
26*3f982cf4SFabien Sanglard explicit ServiceKey(const DomainName& domain);
27*3f982cf4SFabien Sanglard virtual ~ServiceKey() = default;
28*3f982cf4SFabien Sanglard
29*3f982cf4SFabien Sanglard // NOTE: The provided service and domain labels must be valid.
30*3f982cf4SFabien Sanglard ServiceKey(absl::string_view service, absl::string_view domain);
31*3f982cf4SFabien Sanglard ServiceKey(const ServiceKey& other);
32*3f982cf4SFabien Sanglard ServiceKey(ServiceKey&& other);
33*3f982cf4SFabien Sanglard
34*3f982cf4SFabien Sanglard ServiceKey& operator=(const ServiceKey& rhs);
35*3f982cf4SFabien Sanglard ServiceKey& operator=(ServiceKey&& rhs);
36*3f982cf4SFabien Sanglard
37*3f982cf4SFabien Sanglard virtual DomainName GetName() const;
38*3f982cf4SFabien Sanglard
service_id()39*3f982cf4SFabien Sanglard const std::string& service_id() const { return service_id_; }
domain_id()40*3f982cf4SFabien Sanglard const std::string& domain_id() const { return domain_id_; }
41*3f982cf4SFabien Sanglard
42*3f982cf4SFabien Sanglard private:
43*3f982cf4SFabien Sanglard static ErrorOr<ServiceKey> TryCreate(const MdnsRecord& record);
44*3f982cf4SFabien Sanglard static ErrorOr<ServiceKey> TryCreate(const DomainName& domain);
45*3f982cf4SFabien Sanglard
46*3f982cf4SFabien Sanglard std::string service_id_;
47*3f982cf4SFabien Sanglard std::string domain_id_;
48*3f982cf4SFabien Sanglard
49*3f982cf4SFabien Sanglard template <typename H>
50*3f982cf4SFabien Sanglard friend H AbslHashValue(H h, const ServiceKey& key);
51*3f982cf4SFabien Sanglard
52*3f982cf4SFabien Sanglard friend bool operator<(const ServiceKey& lhs, const ServiceKey& rhs);
53*3f982cf4SFabien Sanglard
54*3f982cf4SFabien Sanglard // Validation method which needs the same code as CreateFromRecord(). Use a
55*3f982cf4SFabien Sanglard // friend declaration to avoid duplicating this code while still keeping the
56*3f982cf4SFabien Sanglard // factory private.
57*3f982cf4SFabien Sanglard friend bool HasValidDnsRecordAddress(const MdnsRecord& record);
58*3f982cf4SFabien Sanglard friend bool HasValidDnsRecordAddress(const DomainName& domain);
59*3f982cf4SFabien Sanglard };
60*3f982cf4SFabien Sanglard
61*3f982cf4SFabien Sanglard // Hashing functions to allow for using with absl::Hash<...>.
62*3f982cf4SFabien Sanglard template <typename H>
AbslHashValue(H h,const ServiceKey & key)63*3f982cf4SFabien Sanglard H AbslHashValue(H h, const ServiceKey& key) {
64*3f982cf4SFabien Sanglard return H::combine(std::move(h), key.service_id_, key.domain_id_);
65*3f982cf4SFabien Sanglard }
66*3f982cf4SFabien Sanglard
67*3f982cf4SFabien Sanglard // Comparison operators for using above keys with an std::map
68*3f982cf4SFabien Sanglard inline bool operator<(const ServiceKey& lhs, const ServiceKey& rhs) {
69*3f982cf4SFabien Sanglard int comp = lhs.domain_id_.compare(rhs.domain_id_);
70*3f982cf4SFabien Sanglard if (comp != 0) {
71*3f982cf4SFabien Sanglard return comp < 0;
72*3f982cf4SFabien Sanglard }
73*3f982cf4SFabien Sanglard return lhs.service_id_ < rhs.service_id_;
74*3f982cf4SFabien Sanglard }
75*3f982cf4SFabien Sanglard
76*3f982cf4SFabien Sanglard inline bool operator>(const ServiceKey& lhs, const ServiceKey& rhs) {
77*3f982cf4SFabien Sanglard return rhs < lhs;
78*3f982cf4SFabien Sanglard }
79*3f982cf4SFabien Sanglard
80*3f982cf4SFabien Sanglard inline bool operator<=(const ServiceKey& lhs, const ServiceKey& rhs) {
81*3f982cf4SFabien Sanglard return !(rhs > lhs);
82*3f982cf4SFabien Sanglard }
83*3f982cf4SFabien Sanglard
84*3f982cf4SFabien Sanglard inline bool operator>=(const ServiceKey& lhs, const ServiceKey& rhs) {
85*3f982cf4SFabien Sanglard return !(rhs < lhs);
86*3f982cf4SFabien Sanglard }
87*3f982cf4SFabien Sanglard
88*3f982cf4SFabien Sanglard inline bool operator==(const ServiceKey& lhs, const ServiceKey& rhs) {
89*3f982cf4SFabien Sanglard return lhs <= rhs && lhs >= rhs;
90*3f982cf4SFabien Sanglard }
91*3f982cf4SFabien Sanglard
92*3f982cf4SFabien Sanglard inline bool operator!=(const ServiceKey& lhs, const ServiceKey& rhs) {
93*3f982cf4SFabien Sanglard return !(lhs == rhs);
94*3f982cf4SFabien Sanglard }
95*3f982cf4SFabien Sanglard
96*3f982cf4SFabien Sanglard } // namespace discovery
97*3f982cf4SFabien Sanglard } // namespace openscreen
98*3f982cf4SFabien Sanglard
99*3f982cf4SFabien Sanglard #endif // DISCOVERY_DNSSD_IMPL_SERVICE_KEY_H_
100