1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #ifndef HTTPSSVC_h__
6 #define HTTPSSVC_h__
7 
8 #include "nsIDNSByTypeRecord.h"
9 #include "mozilla/net/DNS.h"
10 #include "mozilla/Variant.h"
11 #include "mozilla/Maybe.h"
12 #include "nsHttp.h"
13 
14 namespace mozilla {
15 namespace net {
16 
17 class DNSHTTPSSVCRecordBase;
18 
19 enum SvcParamKey : uint16_t {
20   SvcParamKeyMandatory = 0,
21   SvcParamKeyAlpn = 1,
22   SvcParamKeyNoDefaultAlpn = 2,
23   SvcParamKeyPort = 3,
24   SvcParamKeyIpv4Hint = 4,
25   SvcParamKeyEchConfig = 5,
26   SvcParamKeyIpv6Hint = 6,
27   SvcParamKeyODoHConfig = 32769,
28 };
29 
IsValidSvcParamKey(uint16_t aKey)30 inline bool IsValidSvcParamKey(uint16_t aKey) {
31   return aKey <= SvcParamKeyIpv6Hint || aKey == SvcParamKeyODoHConfig;
32 }
33 
34 struct SvcParamAlpn {
35   bool operator==(const SvcParamAlpn& aOther) const {
36     return mValue == aOther.mValue;
37   }
38   CopyableTArray<nsCString> mValue;
39 };
40 
41 struct SvcParamNoDefaultAlpn {
42   bool operator==(const SvcParamNoDefaultAlpn& aOther) const { return true; }
43 };
44 
45 struct SvcParamPort {
46   bool operator==(const SvcParamPort& aOther) const {
47     return mValue == aOther.mValue;
48   }
49   uint16_t mValue;
50 };
51 
52 struct SvcParamIpv4Hint {
53   bool operator==(const SvcParamIpv4Hint& aOther) const {
54     return mValue == aOther.mValue;
55   }
56   CopyableTArray<mozilla::net::NetAddr> mValue;
57 };
58 
59 struct SvcParamEchConfig {
60   bool operator==(const SvcParamEchConfig& aOther) const {
61     return mValue == aOther.mValue;
62   }
63   nsCString mValue;
64 };
65 
66 struct SvcParamIpv6Hint {
67   bool operator==(const SvcParamIpv6Hint& aOther) const {
68     return mValue == aOther.mValue;
69   }
70   CopyableTArray<mozilla::net::NetAddr> mValue;
71 };
72 
73 struct SvcParamODoHConfig {
74   bool operator==(const SvcParamODoHConfig& aOther) const {
75     return mValue == aOther.mValue;
76   }
77   nsCString mValue;
78 };
79 
80 using SvcParamType =
81     mozilla::Variant<Nothing, SvcParamAlpn, SvcParamNoDefaultAlpn, SvcParamPort,
82                      SvcParamIpv4Hint, SvcParamEchConfig, SvcParamIpv6Hint,
83                      SvcParamODoHConfig>;
84 
85 struct SvcFieldValue {
86   bool operator==(const SvcFieldValue& aOther) const {
87     return mValue == aOther.mValue;
88   }
SvcFieldValueSvcFieldValue89   SvcFieldValue() : mValue(AsVariant(Nothing{})) {}
90   SvcParamType mValue;
91 };
92 
93 struct SVCB {
94   bool operator==(const SVCB& aOther) const {
95     return mSvcFieldPriority == aOther.mSvcFieldPriority &&
96            mSvcDomainName == aOther.mSvcDomainName &&
97            mSvcFieldValue == aOther.mSvcFieldValue;
98   }
99   bool operator<(const SVCB& aOther) const;
100   Maybe<uint16_t> GetPort() const;
101   bool NoDefaultAlpn() const;
102   void GetIPHints(CopyableTArray<mozilla::net::NetAddr>& aAddresses) const;
103   nsTArray<Tuple<nsCString, SupportedAlpnRank>> GetAllAlpn() const;
104   uint16_t mSvcFieldPriority = 0;
105   nsCString mSvcDomainName;
106   nsCString mEchConfig;
107   nsCString mODoHConfig;
108   bool mHasIPHints = false;
109   bool mHasEchConfig = false;
110   CopyableTArray<SvcFieldValue> mSvcFieldValue;
111 };
112 
113 struct SVCBWrapper {
SVCBWrapperSVCBWrapper114   explicit SVCBWrapper(const SVCB& aRecord) : mRecord(aRecord) {}
115   Maybe<Tuple<nsCString, SupportedAlpnRank>> mAlpn;
116   const SVCB& mRecord;
117 };
118 
119 class SVCBRecord : public nsISVCBRecord {
120   NS_DECL_THREADSAFE_ISUPPORTS
121   NS_DECL_NSISVCBRECORD
122  public:
SVCBRecord(const SVCB & data)123   explicit SVCBRecord(const SVCB& data)
124       : mData(data), mPort(Nothing()), mAlpn(Nothing()) {}
125   explicit SVCBRecord(const SVCB& data,
126                       Maybe<Tuple<nsCString, SupportedAlpnRank>> aAlpn);
127 
128  private:
129   friend class DNSHTTPSSVCRecordBase;
130 
131   virtual ~SVCBRecord() = default;
132 
133   SVCB mData;
134   Maybe<uint16_t> mPort;
135   Maybe<Tuple<nsCString, SupportedAlpnRank>> mAlpn;
136 };
137 
138 class DNSHTTPSSVCRecordBase {
139  public:
DNSHTTPSSVCRecordBase(const nsACString & aHost)140   explicit DNSHTTPSSVCRecordBase(const nsACString& aHost) : mHost(aHost) {}
141 
142  protected:
143   virtual ~DNSHTTPSSVCRecordBase() = default;
144 
145   already_AddRefed<nsISVCBRecord> GetServiceModeRecordInternal(
146       bool aNoHttp2, bool aNoHttp3, const nsTArray<SVCB>& aRecords,
147       bool& aRecordsAllExcluded, bool aCheckHttp3ExcludedList = true);
148 
149   bool HasIPAddressesInternal(const nsTArray<SVCB>& aRecords);
150 
151   void GetAllRecordsWithEchConfigInternal(
152       bool aNoHttp2, bool aNoHttp3, const nsTArray<SVCB>& aRecords,
153       bool* aAllRecordsHaveEchConfig, bool* aAllRecordsInH3ExcludedList,
154       nsTArray<RefPtr<nsISVCBRecord>>& aResult,
155       bool aCheckHttp3ExcludedList = true);
156 
157   // The owner name of this HTTPS RR.
158   nsCString mHost;
159 };
160 
161 }  // namespace net
162 }  // namespace mozilla
163 
164 #endif  // HTTPSSVC_h__
165