tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsHostResolver.h (12787B)


      1 /* vim:set ts=4 sw=2 sts=2 et cin: */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef nsHostResolver_h__
      7 #define nsHostResolver_h__
      8 
      9 #include "nscore.h"
     10 #include "prnetdb.h"
     11 #include "PLDHashTable.h"
     12 #include "mozilla/CondVar.h"
     13 #include "mozilla/DataMutex.h"
     14 #include "nsISupportsImpl.h"
     15 #include "nsIDNSListener.h"
     16 #include "nsTArray.h"
     17 #include "GetAddrInfo.h"
     18 #include "HostRecordQueue.h"
     19 #include "mozilla/net/DNS.h"
     20 #include "mozilla/net/DashboardTypes.h"
     21 #include "mozilla/Atomics.h"
     22 #include "mozilla/TimeStamp.h"
     23 #include "nsHostRecord.h"
     24 #include "nsRefPtrHashtable.h"
     25 #include "nsIThreadPool.h"
     26 #include "mozilla/net/NetworkConnectivityService.h"
     27 #include "mozilla/net/DNSByTypeRecord.h"
     28 #include "mozilla/StaticPrefs_network.h"
     29 
     30 namespace mozilla {
     31 namespace net {
     32 class TRR;
     33 class TRRQuery;
     34 
     35 static inline uint32_t MaxResolverThreadsAnyPriority() {
     36  return StaticPrefs::network_dns_max_any_priority_threads();
     37 }
     38 
     39 static inline uint32_t MaxResolverThreadsHighPriority() {
     40  return StaticPrefs::network_dns_max_high_priority_threads();
     41 }
     42 
     43 static inline uint32_t MaxResolverThreads() {
     44  return MaxResolverThreadsAnyPriority() + MaxResolverThreadsHighPriority();
     45 }
     46 
     47 }  // namespace net
     48 }  // namespace mozilla
     49 
     50 #define TRR_DISABLED(x)                       \
     51  (((x) == nsIDNSService::MODE_NATIVEONLY) || \
     52   ((x) == nsIDNSService::MODE_TRROFF))
     53 
     54 #define MAX_NON_PRIORITY_REQUESTS 150
     55 
     56 class AHostResolver {
     57 public:
     58  AHostResolver() = default;
     59  virtual ~AHostResolver() = default;
     60  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
     61 
     62  enum LookupStatus {
     63    LOOKUP_OK,
     64    LOOKUP_RESOLVEAGAIN,
     65  };
     66 
     67  virtual LookupStatus CompleteLookup(nsHostRecord*, nsresult,
     68                                      mozilla::net::AddrInfo*, bool pb,
     69                                      const nsACString& aOriginsuffix,
     70                                      mozilla::net::TRRSkippedReason aReason,
     71                                      mozilla::net::TRR*) = 0;
     72  virtual LookupStatus CompleteLookupByType(
     73      nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult,
     74      mozilla::net::TRRSkippedReason aReason, uint32_t aTtl, bool pb) = 0;
     75  virtual nsresult GetHostRecord(const nsACString& host,
     76                                 const nsACString& aTrrServer, uint16_t type,
     77                                 nsIDNSService::DNSFlags flags, uint16_t af,
     78                                 bool pb, const nsCString& originSuffix,
     79                                 nsHostRecord** result) {
     80    return NS_ERROR_FAILURE;
     81  }
     82  virtual nsresult TrrLookup_unlocked(nsHostRecord*,
     83                                      mozilla::net::TRR* pushedTRR = nullptr) {
     84    return NS_ERROR_FAILURE;
     85  }
     86  virtual void MaybeRenewHostRecord(nsHostRecord* aRec) {}
     87 };
     88 
     89 /**
     90 * nsHostResolver - an asynchronous host name resolver.
     91 */
     92 class nsHostResolver : public nsISupports, public AHostResolver {
     93  using CondVar = mozilla::CondVar;
     94  using Mutex = mozilla::Mutex;
     95 
     96 public:
     97  NS_DECL_THREADSAFE_ISUPPORTS
     98 
     99  /**
    100   * creates an addref'd instance of a nsHostResolver object.
    101   */
    102  static nsresult Create(nsHostResolver** result);
    103  /**
    104   * puts the resolver in the shutdown state, which will cause any pending
    105   * callbacks to be detached.  any future calls to ResolveHost will fail.
    106   */
    107  void Shutdown();
    108 
    109  /**
    110   * resolve the given hostname and originAttributes asynchronously.  the caller
    111   * can synthesize a synchronous host lookup using a lock and a cvar.  as noted
    112   * above the callback will occur re-entrantly from an unspecified thread.  the
    113   * host lookup cannot be canceled (cancelation can be layered above this by
    114   * having the callback implementation return without doing anything).
    115   */
    116  nsresult ResolveHost(const nsACString& aHost, const nsACString& trrServer,
    117                       int32_t aPort, uint16_t type,
    118                       const mozilla::OriginAttributes& aOriginAttributes,
    119                       nsIDNSService::DNSFlags flags, uint16_t af,
    120                       nsResolveHostCallback* callback);
    121 
    122  nsHostRecord* InitRecord(const nsHostKey& key);
    123  mozilla::net::NetworkConnectivityService* GetNCS() {
    124    return mNCS;
    125  }  // This is actually a singleton
    126 
    127  /**
    128   * return a resolved hard coded loopback dns record for the specified key
    129   */
    130  already_AddRefed<nsHostRecord> InitLoopbackRecord(const nsHostKey& key,
    131                                                    nsresult* aRv);
    132 
    133  /**
    134   * return a mock HTTPS record
    135   */
    136  already_AddRefed<nsHostRecord> InitMockHTTPSRecord(const nsHostKey& key);
    137 
    138  /**
    139   * removes the specified callback from the nsHostRecord for the given
    140   * hostname, originAttributes, flags, and address family.  these parameters
    141   * should correspond to the parameters passed to ResolveHost.  this function
    142   * executes the callback if the callback is still pending with the given
    143   * status.
    144   */
    145  void DetachCallback(const nsACString& hostname, const nsACString& trrServer,
    146                      uint16_t type,
    147                      const mozilla::OriginAttributes& aOriginAttributes,
    148                      nsIDNSService::DNSFlags flags, uint16_t af,
    149                      nsResolveHostCallback* callback, nsresult status);
    150 
    151  /**
    152   * Cancels an async request associated with the hostname, originAttributes,
    153   * flags, address family and listener.  Cancels first callback found which
    154   * matches these criteria.  These parameters should correspond to the
    155   * parameters passed to ResolveHost.  If this is the last callback associated
    156   * with the host record, it is removed from any request queues it might be on.
    157   */
    158  void CancelAsyncRequest(const nsACString& host, const nsACString& trrServer,
    159                          uint16_t type,
    160                          const mozilla::OriginAttributes& aOriginAttributes,
    161                          nsIDNSService::DNSFlags flags, uint16_t af,
    162                          nsIDNSListener* aListener, nsresult status);
    163 
    164  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
    165 
    166  /**
    167   * Flush the DNS cache.
    168   */
    169  void FlushCache(bool aTrrToo, bool aFlushEvictionQueue = false);
    170 
    171  LookupStatus CompleteLookup(nsHostRecord*, nsresult, mozilla::net::AddrInfo*,
    172                              bool pb, const nsACString& aOriginsuffix,
    173                              mozilla::net::TRRSkippedReason aReason,
    174                              mozilla::net::TRR* aTRRRequest) override;
    175  LookupStatus CompleteLookupByType(nsHostRecord*, nsresult,
    176                                    mozilla::net::TypeRecordResultType& aResult,
    177                                    mozilla::net::TRRSkippedReason aReason,
    178                                    uint32_t aTtl, bool pb) override;
    179  nsresult GetHostRecord(const nsACString& host, const nsACString& trrServer,
    180                         uint16_t type, nsIDNSService::DNSFlags flags,
    181                         uint16_t af, bool pb, const nsCString& originSuffix,
    182                         nsHostRecord** result) override;
    183  nsresult TrrLookup_unlocked(nsHostRecord*,
    184                              mozilla::net::TRR* pushedTRR = nullptr) override;
    185  static nsIDNSService::ResolverMode Mode();
    186 
    187  virtual void MaybeRenewHostRecord(nsHostRecord* aRec) override;
    188 
    189  // Records true if the TRR service is enabled for the record's effective
    190  // TRR mode. Also records the TRRSkipReason when the TRR service is not
    191  // available/enabled.
    192  bool TRRServiceEnabledForRecord(nsHostRecord* aRec) MOZ_REQUIRES(mLock);
    193 
    194 private:
    195  explicit nsHostResolver();
    196  virtual ~nsHostResolver();
    197 
    198  bool DoRetryTRR(AddrHostRecord* aAddrRec,
    199                  const mozilla::MutexAutoLock& aLock);
    200  bool MaybeRetryTRRLookup(
    201      AddrHostRecord* aAddrRec, nsresult aFirstAttemptStatus,
    202      mozilla::net::TRRSkippedReason aFirstAttemptSkipReason,
    203      nsresult aChannelStatus, const mozilla::MutexAutoLock& aLock);
    204 
    205  LookupStatus CompleteLookupLocked(nsHostRecord*, nsresult,
    206                                    mozilla::net::AddrInfo*, bool pb,
    207                                    const nsACString& aOriginsuffix,
    208                                    mozilla::net::TRRSkippedReason aReason,
    209                                    mozilla::net::TRR* aTRRRequest,
    210                                    const mozilla::MutexAutoLock& aLock)
    211      MOZ_REQUIRES(mLock);
    212  LookupStatus CompleteLookupByTypeLocked(
    213      nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult,
    214      mozilla::net::TRRSkippedReason aReason, uint32_t aTtl, bool pb,
    215      const mozilla::MutexAutoLock& aLock) MOZ_REQUIRES(mLock);
    216  nsresult Init();
    217  static void ComputeEffectiveTRRMode(nsHostRecord* aRec);
    218  nsresult NativeLookup(nsHostRecord* aRec,
    219                        const mozilla::MutexAutoLock& aLock);
    220  nsresult TrrLookup(nsHostRecord*, const mozilla::MutexAutoLock& aLock,
    221                     mozilla::net::TRR* pushedTRR = nullptr);
    222 
    223  // Kick-off a name resolve operation, using native resolver and/or TRR
    224  nsresult NameLookup(nsHostRecord* aRec, const mozilla::MutexAutoLock& aLock);
    225  bool GetHostToLookup(nsHostRecord** result);
    226  void MaybeRenewHostRecordLocked(nsHostRecord* aRec,
    227                                  const mozilla::MutexAutoLock& aLock)
    228      MOZ_REQUIRES(mLock);
    229 
    230  // Cancels host records in the pending queue and also
    231  // calls CompleteLookup with the NS_ERROR_ABORT result code.
    232  void ClearPendingQueue(mozilla::LinkedList<RefPtr<nsHostRecord>>& aPendingQ);
    233  nsresult ConditionallyCreateThread(nsHostRecord* rec) MOZ_REQUIRES(mLock);
    234 
    235  /**
    236   * Starts a new lookup in the background for cached entries that are in the
    237   * grace period or that are are negative.
    238   *
    239   * Also records telemetry for type of cache hit (HIT/NEGATIVE_HIT/RENEWAL).
    240   */
    241  nsresult ConditionallyRefreshRecord(nsHostRecord* rec, const nsACString& host,
    242                                      const mozilla::MutexAutoLock& aLock)
    243      MOZ_REQUIRES(mLock);
    244 
    245  void OnResolveComplete(nsHostRecord* aRec,
    246                         const mozilla::MutexAutoLock& aLock)
    247      MOZ_REQUIRES(mLock);
    248 
    249  void AddToEvictionQ(nsHostRecord* rec, const mozilla::MutexAutoLock& aLock)
    250      MOZ_REQUIRES(mLock);
    251 
    252  void ThreadFunc();
    253 
    254  // Resolve the host from the DNS cache.
    255  already_AddRefed<nsHostRecord> FromCache(nsHostRecord* aRec,
    256                                           const nsACString& aHost,
    257                                           uint16_t aType, nsresult& aStatus,
    258                                           const mozilla::MutexAutoLock& aLock)
    259      MOZ_REQUIRES(mLock);
    260  // Called when the host name is an IP address and has been passed.
    261  already_AddRefed<nsHostRecord> FromCachedIPLiteral(nsHostRecord* aRec);
    262  // Like the above function, but the host name is not parsed to NetAddr yet.
    263  already_AddRefed<nsHostRecord> FromIPLiteral(
    264      AddrHostRecord* aAddrRec, const mozilla::net::NetAddr& aAddr);
    265  // Called to check if we have an AF_UNSPEC entry in the cache.
    266  already_AddRefed<nsHostRecord> FromUnspecEntry(
    267      nsHostRecord* aRec, const nsACString& aHost, const nsACString& aTrrServer,
    268      const nsACString& aOriginSuffix, uint16_t aType,
    269      nsIDNSService::DNSFlags aFlags, uint16_t af, bool aPb, nsresult& aStatus,
    270      const mozilla::MutexAutoLock& aLock) MOZ_REQUIRES(mLock);
    271 
    272  enum {
    273    METHOD_HIT = 1,
    274    METHOD_RENEWAL = 2,
    275    METHOD_NEGATIVE_HIT = 3,
    276    METHOD_LITERAL = 4,
    277    METHOD_OVERFLOW = 5,
    278    METHOD_NETWORK_FIRST = 6,
    279    METHOD_NETWORK_SHARED = 7
    280  };
    281 
    282  // mutable so SizeOfIncludingThis can be const
    283  mutable Mutex mLock{"nsHostResolver.mLock"};
    284  CondVar mIdleTaskCV;
    285  nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord> mRecordDB
    286      MOZ_GUARDED_BY(mLock);
    287  PRTime mCreationTime;
    288  mozilla::TimeDuration mLongIdleTimeout;
    289  mozilla::TimeDuration mShortIdleTimeout;
    290 
    291  RefPtr<nsIThreadPool> mResolverThreads;
    292  RefPtr<mozilla::net::NetworkConnectivityService>
    293      mNCS;  // reference to a singleton
    294  mozilla::net::HostRecordQueue mQueue MOZ_GUARDED_BY(mLock);
    295  mozilla::Atomic<bool> mShutdown MOZ_GUARDED_BY(mLock){true};
    296  mozilla::Atomic<uint32_t> mNumIdleTasks MOZ_GUARDED_BY(mLock){0};
    297  mozilla::Atomic<uint32_t> mActiveTaskCount MOZ_GUARDED_BY(mLock){0};
    298  mozilla::Atomic<uint32_t> mActiveAnyThreadCount MOZ_GUARDED_BY(mLock){0};
    299 
    300  // Set the expiration time stamps appropriately.
    301  void PrepareRecordExpirationAddrRecord(AddrHostRecord* rec) const;
    302 
    303 public:
    304  /*
    305   * Called by the networking dashboard via the DnsService2
    306   */
    307  void GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries>*);
    308 
    309  static bool IsNativeHTTPSEnabled();
    310 };
    311 
    312 #endif  // nsHostResolver_h__