1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_net_TRR_h
8 #define mozilla_net_TRR_h
10 #include "mozilla/net/DNSByTypeRecord.h"
11 #include "mozilla/Assertions.h"
12 #include "nsClassHashtable.h"
13 #include "nsIChannel.h"
14 #include "nsIHttpPushListener.h"
15 #include "nsIInterfaceRequestor.h"
16 #include "nsIStreamListener.h"
17 #include "nsThreadUtils.h"
18 #include "nsXULAppAPI.h"
19 #include "DNSPacket.h"
20 #include "nsITRRSkipReason.h"
29 class TRRServiceChannel
;
31 class TRR
: public Runnable
,
32 public nsITimerCallback
,
33 public nsIHttpPushListener
,
34 public nsIInterfaceRequestor
,
35 public nsIStreamListener
{
37 NS_DECL_ISUPPORTS_INHERITED
38 NS_DECL_NSIHTTPPUSHLISTENER
39 NS_DECL_NSIINTERFACEREQUESTOR
40 NS_DECL_NSIREQUESTOBSERVER
41 NS_DECL_NSISTREAMLISTENER
42 NS_DECL_NSITIMERCALLBACK
44 // Number of "steps" we follow CNAME chains
45 static const unsigned int kCnameChaseMax
= 64;
47 // when firing off a normal A or AAAA query
48 explicit TRR(AHostResolver
* aResolver
, nsHostRecord
* aRec
,
50 // when following CNAMEs
51 explicit TRR(AHostResolver
* aResolver
, nsHostRecord
* aRec
, nsCString
& aHost
,
52 enum TrrType
& aType
, unsigned int aLoopCount
, bool aPB
);
54 explicit TRR(AHostResolver
* aResolver
, bool aPB
);
56 explicit TRR(AHostResolver
* aResolver
, nsACString
& aHost
, enum TrrType aType
,
57 const nsACString
& aOriginSuffix
, bool aPB
,
58 bool aUseFreshConnection
);
60 NS_IMETHOD
Run() override
;
61 void Cancel(nsresult aStatus
);
62 enum TrrType
Type() { return mType
; }
64 RefPtr
<nsHostRecord
> mRec
;
65 RefPtr
<AHostResolver
> mHostResolver
;
67 void SetTimeout(uint32_t aTimeoutMs
) { mTimeoutMs
= aTimeoutMs
; }
69 nsresult
ChannelStatus() { return mChannelStatus
; }
77 RequestPurpose
Purpose() { return mPurpose
; }
78 void SetPurpose(RequestPurpose aPurpose
) { mPurpose
= aPurpose
; }
79 TRRSkippedReason
SkipReason() const { return mTRRSkippedReason
; }
82 virtual ~TRR() = default;
83 virtual DNSPacket
* GetOrCreateDNSPacket();
84 virtual nsresult
CreateQueryURI(nsIURI
** aOutURI
);
85 virtual const char* ContentType() const { return "application/dns-message"; }
86 virtual DNSResolverType
ResolverType() const { return DNSResolverType::TRR
; }
87 virtual bool MaybeBlockRequest();
88 virtual void RecordProcessingTime(nsIChannel
* aChannel
);
89 virtual void ReportStatus(nsresult aStatusCode
);
90 virtual void HandleTimeout();
91 virtual void HandleEncodeError(nsresult aStatusCode
) {}
92 virtual void HandleDecodeError(nsresult aStatusCode
);
93 nsresult
SendHTTPRequest();
94 nsresult
ReturnData(nsIChannel
* aChannel
);
96 // FailData() must be called to signal that the asynch TRR resolve is
97 // completed. For failed name resolves ("no such host"), the 'error' it
98 // passses on in its argument must be NS_ERROR_UNKNOWN_HOST. Other errors
99 // (if host was blocklisted, there as a bad content-type received, etc)
100 // other error codes must be used. This distinction is important for the
101 // subsequent logic to separate the error reasons.
102 nsresult
FailData(nsresult error
);
103 static nsresult
DohDecodeQuery(const nsCString
& query
, nsCString
& host
,
105 nsresult
ReceivePush(nsIHttpChannel
* pushed
, nsHostRecord
* pushedRec
);
106 nsresult
On200Response(nsIChannel
* aChannel
);
107 nsresult
FollowCname(nsIChannel
* aChannel
);
109 bool HasUsableResponse();
111 bool UseDefaultServer();
112 void SaveAdditionalRecords(
113 const nsClassHashtable
<nsCStringHashKey
, DOHresp
>& aRecords
);
115 friend class TRRServiceChannel
;
116 static nsresult
SetupTRRServiceChannelInternal(
117 nsIHttpChannel
* aChannel
, bool aUseGet
, const nsACString
& aContentType
);
119 void StoreIPHintAsDNSRecord(const struct SVCB
& aSVCBRecord
);
121 nsCOMPtr
<nsIChannel
> mChannel
;
122 enum TrrType mType
{ TRRTYPE_A
};
123 UniquePtr
<DNSPacket
> mPacket
;
124 bool mFailed
= false;
127 nsresult mChannelStatus
= NS_OK
;
129 RequestPurpose mPurpose
= Resolve
;
130 Atomic
<bool, Relaxed
> mCancelled
{false};
132 // The request timeout in milliseconds. If 0 we will use the default timeout
133 // we get from the prefs.
134 uint32_t mTimeoutMs
= 0;
135 nsCOMPtr
<nsITimer
> mTimeout
;
137 uint32_t mCnameLoop
= kCnameChaseMax
; // loop detection counter
139 uint32_t mTTL
= UINT32_MAX
;
140 TypeRecordResultType mResult
= mozilla::AsVariant(Nothing());
142 TRRSkippedReason mTRRSkippedReason
= TRRSkippedReason::TRR_UNSET
;
143 void RecordReason(TRRSkippedReason reason
) {
144 if (mTRRSkippedReason
== TRRSkippedReason::TRR_UNSET
) {
145 mTRRSkippedReason
= reason
;
149 // keep a copy of the originSuffix for the cases where mRec == nullptr */
150 const nsCString mOriginSuffix
;
152 // If true, we set LOAD_FRESH_CONNECTION on our channel's load flags.
153 bool mUseFreshConnection
= false;
157 } // namespace mozilla
159 #endif // include guard