summaryrefslogtreecommitdiffstats
path: root/netwerk/dns/TRR.h
blob: 489cca08b8218c52c8baaa118d9705e1289bd795 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_net_TRR_h
#define mozilla_net_TRR_h

#include "mozilla/net/DNSByTypeRecord.h"
#include "mozilla/Assertions.h"
#include "nsClassHashtable.h"
#include "nsIChannel.h"
#include "nsIHttpPushListener.h"
#include "nsIInterfaceRequestor.h"
#include "nsIStreamListener.h"
#include "nsHostResolver.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
#include "DNSPacket.h"

namespace mozilla {
namespace net {

class TRRService;
class TRRServiceChannel;
extern TRRService* gTRRService;

class TRR : public Runnable,
            public nsITimerCallback,
            public nsIHttpPushListener,
            public nsIInterfaceRequestor,
            public nsIStreamListener {
 public:
  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_NSIHTTPPUSHLISTENER
  NS_DECL_NSIINTERFACEREQUESTOR
  NS_DECL_NSIREQUESTOBSERVER
  NS_DECL_NSISTREAMLISTENER
  NS_DECL_NSITIMERCALLBACK

  // Number of "steps" we follow CNAME chains
  static const unsigned int kCnameChaseMax = 64;

  // when firing off a normal A or AAAA query
  explicit TRR(AHostResolver* aResolver, nsHostRecord* aRec, enum TrrType aType)
      : mozilla::Runnable("TRR"),
        mRec(aRec),
        mHostResolver(aResolver),
        mType(aType),
        mOriginSuffix(aRec->originSuffix) {
    mHost = aRec->host;
    mPB = aRec->pb;
    MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),
                          "TRR must be in parent or socket process");
  }

  // when following CNAMEs
  explicit TRR(AHostResolver* aResolver, nsHostRecord* aRec, nsCString& aHost,
               enum TrrType& aType, unsigned int aLoopCount, bool aPB)
      : mozilla::Runnable("TRR"),
        mHost(aHost),
        mRec(aRec),
        mHostResolver(aResolver),
        mType(aType),
        mPB(aPB),
        mCnameLoop(aLoopCount),
        mOriginSuffix(aRec ? aRec->originSuffix : ""_ns) {
    MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),
                          "TRR must be in parent or socket process");
  }

  // used on push
  explicit TRR(AHostResolver* aResolver, bool aPB)
      : mozilla::Runnable("TRR"),
        mHostResolver(aResolver),
        mType(TRRTYPE_A),
        mPB(aPB) {
    MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),
                          "TRR must be in parent or socket process");
  }

  // to verify a domain
  explicit TRR(AHostResolver* aResolver, nsACString& aHost, enum TrrType aType,
               const nsACString& aOriginSuffix, bool aPB)
      : mozilla::Runnable("TRR"),
        mHost(aHost),
        mRec(nullptr),
        mHostResolver(aResolver),
        mType(aType),
        mPB(aPB),
        mOriginSuffix(aOriginSuffix) {
    MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess(),
                          "TRR must be in parent or socket process");
  }

  NS_IMETHOD Run() override;
  void Cancel();
  enum TrrType Type() { return mType; }
  nsCString mHost;
  RefPtr<nsHostRecord> mRec;
  RefPtr<AHostResolver> mHostResolver;

 private:
  ~TRR() = default;
  nsresult SendHTTPRequest();
  nsresult ReturnData(nsIChannel* aChannel);

  // FailData() must be called to signal that the asynch TRR resolve is
  // completed. For failed name resolves ("no such host"), the 'error' it
  // passses on in its argument must be NS_ERROR_UNKNOWN_HOST. Other errors
  // (if host was blacklisted, there as a bad content-type received, etc)
  // other error codes must be used. This distinction is important for the
  // subsequent logic to separate the error reasons.
  nsresult FailData(nsresult error);
  static nsresult DohDecodeQuery(const nsCString& query, nsCString& host,
                                 enum TrrType& type);
  nsresult ReceivePush(nsIHttpChannel* pushed, nsHostRecord* pushedRec);
  nsresult On200Response(nsIChannel* aChannel);
  nsresult FollowCname(nsIChannel* aChannel);

  bool UseDefaultServer();
  void SaveAdditionalRecords(
      const nsClassHashtable<nsCStringHashKey, DOHresp>& aRecords);

  nsresult CreateChannelHelper(nsIURI* aUri, nsIChannel** aResult);

  friend class TRRServiceChannel;
  static nsresult SetupTRRServiceChannelInternal(nsIHttpChannel* aChannel,
                                                 bool aUseGet);

  void StoreIPHintAsDNSRecord(const struct SVCB& aSVCBRecord);

  nsCOMPtr<nsIChannel> mChannel;
  enum TrrType mType;
  DNSPacket mPacket;
  bool mFailed = false;
  bool mPB;
  DOHresp mDNS;
  nsCOMPtr<nsITimer> mTimeout;
  nsCString mCname;
  uint32_t mCnameLoop = kCnameChaseMax;  // loop detection counter

  uint32_t mTTL = UINT32_MAX;
  TypeRecordResultType mResult = mozilla::AsVariant(Nothing());

  nsHostRecord::TRRSkippedReason mTRRSkippedReason = nsHostRecord::TRR_UNSET;
  void RecordReason(nsHostRecord::TRRSkippedReason reason) {
    if (mTRRSkippedReason == nsHostRecord::TRR_UNSET) {
      mTRRSkippedReason = reason;
    }
  }

  // keep a copy of the originSuffix for the cases where mRec == nullptr */
  const nsCString mOriginSuffix;
};

}  // namespace net
}  // namespace mozilla

#endif  // include guard