tor-browser

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

DnsAndConnectSocket.h (9242B)


      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 DnsAndConnectSocket_h__
      7 #define DnsAndConnectSocket_h__
      8 
      9 #include "mozilla/TimeStamp.h"
     10 #include "nsAHttpConnection.h"
     11 #include "nsHttpConnection.h"
     12 #include "nsHttpTransaction.h"
     13 #include "nsIAsyncOutputStream.h"
     14 #include "nsICancelable.h"
     15 #include "nsIDNSListener.h"
     16 #include "nsIDNSRecord.h"
     17 #include "nsIDNSService.h"
     18 #include "nsINamed.h"
     19 #include "nsITransport.h"
     20 #include "nsWeakReference.h"
     21 
     22 namespace mozilla {
     23 namespace net {
     24 
     25 // 8d411b53-54bc-4a99-8b78-ff125eab1564
     26 #define NS_DNSANDCONNECTSOCKET_IID \
     27  {0x8d411b53, 0x54bc, 0x4a99, {0x8b, 0x78, 0xff, 0x12, 0x5e, 0xab, 0x15, 0x64}}
     28 
     29 class PendingTransactionInfo;
     30 class ConnectionEntry;
     31 
     32 class DnsAndConnectSocket final : public nsIOutputStreamCallback,
     33                                  public nsITransportEventSink,
     34                                  public nsIInterfaceRequestor,
     35                                  public nsITimerCallback,
     36                                  public nsINamed,
     37                                  public nsSupportsWeakReference,
     38                                  public nsIDNSListener {
     39  ~DnsAndConnectSocket();
     40 
     41 public:
     42  NS_INLINE_DECL_STATIC_IID(NS_DNSANDCONNECTSOCKET_IID)
     43  NS_DECL_THREADSAFE_ISUPPORTS
     44  NS_DECL_NSIOUTPUTSTREAMCALLBACK
     45  NS_DECL_NSITRANSPORTEVENTSINK
     46  NS_DECL_NSIINTERFACEREQUESTOR
     47  NS_DECL_NSITIMERCALLBACK
     48  NS_DECL_NSINAMED
     49  NS_DECL_NSIDNSLISTENER
     50 
     51  DnsAndConnectSocket(nsHttpConnectionInfo* ci, nsAHttpTransaction* trans,
     52                      uint32_t caps, bool speculative, bool urgentStart);
     53 
     54  [[nodiscard]] nsresult Init(ConnectionEntry* ent);
     55  void Abandon();
     56  double Duration(TimeStamp epoch);
     57  void CloseTransports(nsresult error);
     58 
     59  bool IsSpeculative() { return mSpeculative; }
     60 
     61  bool Allow1918() { return mAllow1918; }
     62  void SetAllow1918(bool val) { mAllow1918 = val; }
     63 
     64  bool HasConnected() { return mHasConnected; }
     65 
     66  void PrintDiagnostics(nsCString& log);
     67 
     68  // Checks whether the transaction can be dispatched using this
     69  // half-open's connection.  If this half-open is marked as urgent-start,
     70  // it only accepts urgent start transactions.  Call only before Claim().
     71  bool AcceptsTransaction(nsHttpTransaction* trans);
     72  bool Claim();
     73  void Unclaim();
     74 
     75 private:
     76  // This performs checks that the DnsAndConnectSocket has been properly cleand
     77  // up.
     78  void CheckIsDone();
     79 
     80  /**
     81   * State:
     82   *   INIT: initial state. From this state:
     83   *         1) change the state to RESOLVING and start the primary DNS lookup
     84   *            if mSkipDnsResolution is false,
     85   *         2) or the lookup is skip and the state changes to CONNECTING and
     86   *            start the backup timer.
     87   *         3) or changes to DONE in case of an error.
     88   *   RESOLVING: the primary DNS resolution is in progress. From this state
     89   *              we transition into CONNECTING or DONE.
     90   *   CONNECTING: We change to this state when the primary connection has
     91   *               started. At that point the backup timer is started.
     92   *   ONE_CONNECTED: We change into this state when one of the connections
     93   *                  is connected and the second is in progres.
     94   *   DONE
     95   *
     96   * Events:
     97   *   INIT_EVENT: Start the primary dns resolution (if mSkipDnsResolution is
     98   *               false), otherwise start the primary connection.
     99   *   RESOLVED_PRIMARY_EVENT: the primary DNS resolution is done. This event
    100   *                           may be resent due to DNS retries
    101   *   CONNECTED_EVENT: A connecion (primary or backup) is done
    102   */
    103  enum DnsAndSocketState {
    104    INIT,
    105    RESOLVING,
    106    CONNECTING,
    107    ONE_CONNECTED,
    108    DONE
    109  } mState = INIT;
    110 
    111  enum SetupEvents {
    112    INIT_EVENT,
    113    RESOLVED_PRIMARY_EVENT,
    114    PRIMARY_DONE_EVENT,
    115    BACKUP_DONE_EVENT,
    116    BACKUP_TIMER_FIRED_EVENT
    117  };
    118 
    119  // This structure is responsible for performing DNS lookup, creating socket
    120  // and connecting the socket.
    121  struct TransportSetup {
    122    enum TransportSetupState {
    123      INIT,
    124      RESOLVING,
    125      RESOLVED,
    126      RETRY_RESOLVING,
    127      CONNECTING,
    128      CONNECTING_DONE,
    129      DONE
    130    } mState;
    131 
    132    bool FirstResolving() {
    133      return mState == TransportSetup::TransportSetupState::RESOLVING;
    134    }
    135    bool ConnectingOrRetry() {
    136      return (mState == TransportSetup::TransportSetupState::CONNECTING) ||
    137             (mState == TransportSetup::TransportSetupState::RETRY_RESOLVING) ||
    138             (mState == TransportSetup::TransportSetupState::CONNECTING_DONE);
    139    }
    140    bool Resolved() {
    141      return mState == TransportSetup::TransportSetupState::RESOLVED;
    142    }
    143    bool DoneConnecting() {
    144      return (mState == TransportSetup::TransportSetupState::CONNECTING_DONE) ||
    145             (mState == TransportSetup::TransportSetupState::DONE);
    146    }
    147 
    148    nsCString mHost;
    149    nsCOMPtr<nsICancelable> mDNSRequest;
    150    nsCOMPtr<nsIDNSAddrRecord> mDNSRecord;
    151    nsIDNSService::DNSFlags mDnsFlags = nsIDNSService::RESOLVE_DEFAULT_FLAGS;
    152    bool mRetryWithDifferentIPFamily = false;
    153    bool mResetFamilyPreference = false;
    154    bool mSkipDnsResolution = false;
    155 
    156    nsCOMPtr<nsISocketTransport> mSocketTransport;
    157    nsCOMPtr<nsIAsyncOutputStream> mStreamOut;
    158    nsCOMPtr<nsIAsyncInputStream> mStreamIn;
    159    TimeStamp mSynStarted;
    160    bool mConnectedOK = false;
    161    bool mIsBackup;
    162 
    163    bool mWaitingForConnect = false;
    164    void SetConnecting();
    165    void MaybeSetConnectingDone();
    166 
    167    nsresult Init(DnsAndConnectSocket* dnsAndSock);
    168    void CancelDnsResolution();
    169    void Abandon();
    170    void CloseAll();
    171    nsresult SetupConn(DnsAndConnectSocket* dnsAndSock,
    172                       nsAHttpTransaction* transaction, ConnectionEntry* ent,
    173                       nsresult status, uint32_t cap,
    174                       HttpConnectionBase** connection);
    175    [[nodiscard]] nsresult SetupStreams(DnsAndConnectSocket* dnsAndSock);
    176    nsresult ResolveHost(DnsAndConnectSocket* dnsAndSock);
    177    bool ShouldRetryDNS();
    178    nsresult OnLookupComplete(DnsAndConnectSocket* dnsAndSock,
    179                              nsIDNSRecord* rec, nsresult status);
    180    nsresult CheckConnectedResult(DnsAndConnectSocket* dnsAndSock);
    181    // Toggles the IP family flags (RESOLVE_DISABLE_IPV6 and
    182    // RESOLVE_DISABLE_IPV4) in mDnsFlags if retrying with a different IP family
    183    // is enabled.
    184    bool ToggleIpFamilyFlagsIfRetryEnabled();
    185 
    186   protected:
    187    explicit TransportSetup(bool isBackup);
    188  };
    189 
    190  struct PrimaryTransportSetup final : TransportSetup {
    191    PrimaryTransportSetup() : TransportSetup(false) {}
    192  };
    193 
    194  struct BackupTransportSetup final : TransportSetup {
    195    BackupTransportSetup() : TransportSetup(true) {}
    196  };
    197 
    198  nsresult SetupConn(bool isPrimary, nsresult status);
    199  void SetupBackupTimer();
    200  void CancelBackupTimer();
    201 
    202  bool IsPrimary(nsITransport* trans);
    203  bool IsPrimary(nsIAsyncOutputStream* out);
    204  bool IsPrimary(nsICancelable* dnsRequest);
    205  bool IsBackup(nsITransport* trans);
    206  bool IsBackup(nsIAsyncOutputStream* out);
    207  bool IsBackup(nsICancelable* dnsRequest);
    208 
    209  // To find out whether |mTransaction| is still in the connection entry's
    210  // pending queue. If the transaction is found and |removeWhenFound| is
    211  // true, the transaction will be removed from the pending queue.
    212  already_AddRefed<PendingTransactionInfo> FindTransactionHelper(
    213      bool removeWhenFound);
    214 
    215  void CheckProxyConfig();
    216  nsresult SetupDnsFlags(ConnectionEntry* ent);
    217  nsresult SetupEvent(SetupEvents event);
    218 
    219  RefPtr<nsAHttpTransaction> mTransaction;
    220  bool mDispatchedMTransaction = false;
    221 
    222  PrimaryTransportSetup mPrimaryTransport;
    223  uint32_t mCaps;
    224 
    225  // mSpeculative is set if the socket was created from
    226  // SpeculativeConnect(). It is cleared when a transaction would normally
    227  // start a new connection from scratch but instead finds this one in
    228  // the half open list and claims it for its own use. (which due to
    229  // the vagaries of scheduling from the pending queue might not actually
    230  // match up - but it prevents a speculative connection from opening
    231  // more connections that are needed.)
    232  bool mSpeculative;
    233 
    234  // If created with a non-null urgent transaction, remember it, so we can
    235  // mark the connection as urgent rightaway it's created.
    236  bool mUrgentStart;
    237 
    238  bool mAllow1918 = true;
    239 
    240  // mHasConnected tracks whether one of the sockets has completed the
    241  // connection process. It may have completed unsuccessfully.
    242  bool mHasConnected = false;
    243 
    244  bool mBackupConnStatsSet = false;
    245 
    246  // A DnsAndConnectSocket can be made for a concrete non-null transaction,
    247  // but the transaction can be dispatch to another connection. In that
    248  // case we can free this transaction to be claimed by other
    249  // transactions.
    250  bool mFreeToUse = true;
    251 
    252  RefPtr<nsHttpConnectionInfo> mConnInfo;
    253  nsCOMPtr<nsITimer> mSynTimer;
    254  BackupTransportSetup mBackupTransport;
    255 
    256  bool mIsHttp3 = false;
    257 
    258  bool mSkipDnsResolution = false;
    259  bool mProxyNotTransparent = false;
    260  bool mProxyTransparentResolvesHost = false;
    261 };
    262 
    263 }  // namespace net
    264 }  // namespace mozilla
    265 
    266 #endif  // DnsAndConnectSocket_h__