tor-browser

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

nsHttpTransaction.h (24380B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      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 nsHttpTransaction_h__
      7 #define nsHttpTransaction_h__
      8 
      9 #include "ARefBase.h"
     10 #include "EventTokenBucket.h"
     11 #include "HttpTransactionShell.h"
     12 #include "TimingStruct.h"
     13 #include "mozilla/StaticPrefs_security.h"
     14 #include "mozilla/net/DNS.h"
     15 #include "mozilla/net/NeckoChannelParams.h"
     16 #include "nsAHttpConnection.h"
     17 #include "nsAHttpTransaction.h"
     18 #include "nsCOMPtr.h"
     19 #include "nsContentPermissionHelper.h"
     20 #include "nsHttp.h"
     21 #include "nsIAsyncOutputStream.h"
     22 #include "nsIClassOfService.h"
     23 #include "nsIEarlyHintObserver.h"
     24 #include "nsIInterfaceRequestor.h"
     25 #include "nsITLSSocketControl.h"
     26 #include "nsITimer.h"
     27 #include "nsIWebTransport.h"
     28 #include "nsTHashMap.h"
     29 #include "nsThreadUtils.h"
     30 
     31 //-----------------------------------------------------------------------------
     32 
     33 class nsIDNSHTTPSSVCRecord;
     34 class nsIEventTarget;
     35 class nsIInputStream;
     36 class nsIOutputStream;
     37 class nsIRequestContext;
     38 class nsISVCBRecord;
     39 
     40 namespace mozilla::net {
     41 
     42 class HTTPSRecordResolver;
     43 class nsHttpChunkedDecoder;
     44 class nsHttpHeaderArray;
     45 class nsHttpRequestHead;
     46 class nsHttpResponseHead;
     47 class NullHttpTransaction;
     48 class Http2ConnectTransaction;
     49 
     50 //-----------------------------------------------------------------------------
     51 // nsHttpTransaction represents a single HTTP transaction.  It is thread-safe,
     52 // intended to run on the socket thread.
     53 //-----------------------------------------------------------------------------
     54 
     55 class nsHttpTransaction final : public nsAHttpTransaction,
     56                                public HttpTransactionShell,
     57                                public ATokenBucketEvent,
     58                                public nsIInputStreamCallback,
     59                                public nsIOutputStreamCallback,
     60                                public ARefBase,
     61                                public nsITimerCallback,
     62                                public nsINamed {
     63 public:
     64  NS_DECL_THREADSAFE_ISUPPORTS
     65  NS_DECL_NSAHTTPTRANSACTION
     66  NS_DECL_HTTPTRANSACTIONSHELL
     67  NS_DECL_NSIINPUTSTREAMCALLBACK
     68  NS_DECL_NSIOUTPUTSTREAMCALLBACK
     69  NS_DECL_NSITIMERCALLBACK
     70  NS_DECL_NSINAMED
     71 
     72  nsHttpTransaction();
     73 
     74  void OnActivated() override;
     75 
     76  // attributes
     77  nsHttpResponseHead* ResponseHead() {
     78    return mHaveAllHeaders ? mResponseHead : nullptr;
     79  }
     80 
     81  nsIEventTarget* ConsumerTarget() { return mConsumerTarget; }
     82 
     83  // Called to set/find out if the transaction generated a complete response.
     84  void SetResponseIsComplete() { mResponseIsComplete = true; }
     85 
     86  void EnableKeepAlive() { mCaps |= NS_HTTP_ALLOW_KEEPALIVE; }
     87  void MakeSticky() { mCaps |= NS_HTTP_STICKY_CONNECTION; }
     88  void MakeNonSticky() override { mCaps &= ~NS_HTTP_STICKY_CONNECTION; }
     89  void MakeRestartable() override { mCaps |= NS_HTTP_CONNECTION_RESTARTABLE; }
     90  void MakeNonRestartable() { mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE; }
     91  void RemoveConnection();
     92  void SetIsHttp2Websocket(bool h2ws) override { mIsHttp2Websocket = h2ws; }
     93  bool IsHttp2Websocket() override { return mIsHttp2Websocket; }
     94  bool Closed() { return mClosed; }
     95 
     96  void SetTRRInfo(nsIRequest::TRRMode aMode,
     97                  TRRSkippedReason aSkipReason) override {
     98    mEffectiveTRRMode = aMode;
     99    mTRRSkipReason = aSkipReason;
    100  }
    101 
    102  bool WaitingForHTTPSRR() const { return mCaps & NS_HTTP_FORCE_WAIT_HTTP_RR; }
    103  void MakeDontWaitHTTPSRR() { mCaps &= ~NS_HTTP_FORCE_WAIT_HTTP_RR; }
    104 
    105  // SetPriority() may only be used by the connection manager.
    106  void SetPriority(int32_t priority) { mPriority = priority; }
    107  int32_t Priority() { return mPriority; }
    108 
    109  void PrintDiagnostics(nsCString& log);
    110 
    111  // Sets mTimings.transactionPending to the current time stamp or to a null
    112  // time stamp (if now is false)
    113  void SetPendingTime(bool now = true) {
    114    mozilla::MutexAutoLock lock(mLock);
    115    if (!now && !mTimings.transactionPending.IsNull()) {
    116      // Remember how long it took. We will use this value to record
    117      // TRANSACTION_WAIT_TIME_HTTP2_SUP_HTTP3 telemetry, but we need to wait
    118      // for the response headers.
    119      mPendingDurationTime = TimeStamp::Now() - mTimings.transactionPending;
    120    }
    121    // Note that the transaction could be added in to a pending queue multiple
    122    // times (when the transaction is restarted or moved to a new conn entry due
    123    // to HTTPS RR), so we should only set the pending time once.
    124    if (mTimings.transactionPending.IsNull()) {
    125      mTimings.transactionPending = now ? TimeStamp::Now() : TimeStamp();
    126    }
    127  }
    128  TimeStamp GetPendingTime() override {
    129    mozilla::MutexAutoLock lock(mLock);
    130    return mTimings.transactionPending;
    131  }
    132 
    133  // overload of nsAHttpTransaction::RequestContext()
    134  nsIRequestContext* RequestContext() override { return mRequestContext.get(); }
    135  void DispatchedAsBlocking();
    136  void RemoveDispatchedAsBlocking();
    137 
    138  void DisableSpdy() override;
    139  void DisableHttp2ForProxy() override;
    140  void DoNotRemoveAltSvc() override { mDoNotRemoveAltSvc = true; }
    141  void DoNotResetIPFamilyPreference() override {
    142    mDoNotResetIPFamilyPreference = true;
    143  }
    144  void DisableHttp3(bool aAllowRetryHTTPSRR) override;
    145 
    146  nsHttpTransaction* QueryHttpTransaction() override { return this; }
    147 
    148  uint32_t InitialRwin() const { return mInitialRwin; };
    149  bool ChannelPipeFull() { return mWaitingOnPipeOut; }
    150 
    151  // Locked methods to get and set timing info
    152  void BootstrapTimings(TimingStruct times);
    153  void SetConnectStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
    154  void SetConnectEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
    155  void SetRequestStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
    156  void SetResponseStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
    157  void SetResponseEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false);
    158 
    159  [[nodiscard]] bool Do0RTT() override;
    160  [[nodiscard]] nsresult Finish0RTT(bool aRestart,
    161                                    bool aAlpnChanged /* ignored */) override;
    162 
    163  // After Finish0RTT early data may have failed but the caller did not request
    164  // restart - this indicates that state for dev tools
    165  void Refused0RTT();
    166 
    167  uint64_t BrowserId() override { return mBrowserId; }
    168 
    169  void SetHttpTrailers(nsCString& aTrailers);
    170 
    171  bool IsWebsocketUpgrade();
    172 
    173  void OnProxyConnectComplete(int32_t aResponseCode) override;
    174  void SetFlat407Headers(const nsACString& aHeaders);
    175 
    176  void UpdateConnectionInfo(nsHttpConnectionInfo* aConnInfo);
    177 
    178  void SetClassOfService(ClassOfService cos);
    179 
    180  virtual nsresult OnHTTPSRRAvailable(nsIDNSHTTPSSVCRecord* aHTTPSSVCRecord,
    181                                      nsISVCBRecord* aHighestPriorityRecord,
    182                                      const nsACString& aCname) override;
    183 
    184  void GetHashKeyOfConnectionEntry(nsACString& aResult);
    185 
    186  bool IsForWebTransport() override { return mIsForWebTransport; }
    187  bool IsResettingForTunnelConn() override { return mIsResettingForTunnelConn; }
    188  void SetResettingForTunnelConn(bool aValue) override {
    189    mIsResettingForTunnelConn = aValue;
    190  }
    191 
    192  nsAutoCString GetUrl() { return mUrl; }
    193 
    194  uint64_t ChannelId() { return mChannelId; }
    195 
    196 private:
    197  friend class DeleteHttpTransaction;
    198  virtual ~nsHttpTransaction();
    199 
    200  [[nodiscard]] nsresult Restart();
    201  char* LocateHttpStart(char* buf, uint32_t len, bool aAllowPartialMatch);
    202  [[nodiscard]] nsresult ParseLine(nsACString& line);
    203  [[nodiscard]] nsresult ParseLineSegment(char* seg, uint32_t len);
    204  [[nodiscard]] nsresult ParseHead(char*, uint32_t count, uint32_t* countRead);
    205  [[nodiscard]] nsresult HandleContentStart();
    206  [[nodiscard]] nsresult HandleContent(char*, uint32_t count,
    207                                       uint32_t* contentRead,
    208                                       uint32_t* contentRemaining);
    209  [[nodiscard]] nsresult ProcessData(char*, uint32_t, uint32_t*);
    210  void ReportResponseHeader(uint32_t aSubType);
    211  void DeleteSelfOnConsumerThread();
    212  void ReleaseBlockingTransaction();
    213  [[nodiscard]] static nsresult ReadRequestSegment(nsIInputStream*, void*,
    214                                                   const char*, uint32_t,
    215                                                   uint32_t, uint32_t*);
    216  [[nodiscard]] static nsresult WritePipeSegment(nsIOutputStream*, void*, char*,
    217                                                 uint32_t, uint32_t, uint32_t*);
    218 
    219  bool ResponseTimeoutEnabled() const final;
    220 
    221  void ReuseConnectionOnRestartOK(bool reuseOk) override {
    222    mReuseOnRestart = reuseOk;
    223  }
    224 
    225  // Called right after we parsed the response head.  Checks for connection
    226  // based authentication schemes in reponse headers for WWW and Proxy
    227  // authentication. If such is found in any of them, NS_HTTP_STICKY_CONNECTION
    228  // is set in mCaps. We need the sticky flag be set early to keep the
    229  // connection from very start of the authentication process.
    230  void CheckForStickyAuthScheme();
    231  void CheckForStickyAuthSchemeAt(nsHttpAtom const& header);
    232  bool IsStickyAuthSchemeAt(nsACString const& auth);
    233 
    234  // Called from WriteSegments.  Checks for conditions whether to throttle
    235  // reading the content.  When this returns true, WriteSegments returns
    236  // WOULD_BLOCK.
    237  bool ShouldThrottle();
    238 
    239  void NotifyTransactionObserver(nsresult reason);
    240 
    241  // When echConfig is enabled, this function put other available records
    242  // in mRecordsForRetry. Returns true when mRecordsForRetry is not empty,
    243  // otherwise returns false.
    244  bool PrepareSVCBRecordsForRetry(const nsACString& aFailedDomainName,
    245                                  const nsACString& aFailedAlpn,
    246                                  bool& aAllRecordsHaveEchConfig);
    247  // This function setups a new connection info for restarting this transaction.
    248  void PrepareConnInfoForRetry(nsresult aReason);
    249  // This function is used to select the next non http3 record and is only
    250  // executed when the fast fallback timer is triggered.
    251  already_AddRefed<nsHttpConnectionInfo> PrepareFastFallbackConnInfo(
    252      bool aEchConfigUsed);
    253 
    254  void MaybeReportFailedSVCDomain(nsresult aReason,
    255                                  nsHttpConnectionInfo* aFailedConnInfo);
    256 
    257  void FinalizeConnInfo();
    258 
    259  // IMPORTANT: when adding new values, always add them to the end, otherwise
    260  // it will mess up telemetry.
    261  enum HTTPSSVC_CONNECTION_FAILED_REASON : uint32_t {
    262    HTTPSSVC_CONNECTION_OK = 0,
    263    HTTPSSVC_CONNECTION_UNKNOWN_HOST = 1,
    264    HTTPSSVC_CONNECTION_UNREACHABLE = 2,
    265    HTTPSSVC_CONNECTION_421_RECEIVED = 3,
    266    HTTPSSVC_CONNECTION_SECURITY_ERROR = 4,
    267    HTTPSSVC_CONNECTION_NO_USABLE_RECORD = 5,
    268    HTTPSSVC_CONNECTION_ALL_RECORDS_EXCLUDED = 6,
    269    HTTPSSVC_CONNECTION_OTHERS = 7,
    270  };
    271  HTTPSSVC_CONNECTION_FAILED_REASON ErrorCodeToFailedReason(
    272      nsresult aErrorCode);
    273 
    274  void OnHttp3BackupTimer();
    275  void OnBackupConnectionReady(bool aTriggeredByHTTPSRR);
    276  void OnFastFallbackTimer();
    277  void OnHttp3TunnelFallbackTimer();
    278  void HandleFallback(nsHttpConnectionInfo* aFallbackConnInfo);
    279  void MaybeCancelFallbackTimer();
    280 
    281  // IMPORTANT: when adding new values, always add them to the end, otherwise
    282  // it will mess up telemetry.
    283  enum TRANSACTION_RESTART_REASON : uint32_t {
    284    TRANSACTION_RESTART_NONE = 0,  // The transacion was not restarted.
    285    TRANSACTION_RESTART_FORCED,    // The transaction was forced to restart.
    286    TRANSACTION_RESTART_NO_DATA_SENT,
    287    TRANSACTION_RESTART_DOWNGRADE_WITH_EARLY_DATA,
    288    TRANSACTION_RESTART_HTTPS_RR_NET_RESET,
    289    TRANSACTION_RESTART_HTTPS_RR_CONNECTION_REFUSED,
    290    TRANSACTION_RESTART_HTTPS_RR_UNKNOWN_HOST,
    291    TRANSACTION_RESTART_HTTPS_RR_NET_TIMEOUT,
    292    TRANSACTION_RESTART_HTTPS_RR_SEC_ERROR,
    293    TRANSACTION_RESTART_HTTPS_RR_FAST_FALLBACK,
    294    TRANSACTION_RESTART_HTTP3_FAST_FALLBACK,
    295    TRANSACTION_RESTART_OTHERS,
    296    TRANSACTION_RESTART_PROTOCOL_VERSION_ALERT,
    297    TRANSACTION_RESTART_POSSIBLE_0RTT_ERROR
    298  };
    299  void SetRestartReason(TRANSACTION_RESTART_REASON aReason);
    300 
    301  bool HandleWebTransportResponse(uint16_t aStatus);
    302 
    303  void MaybeRefreshSecurityInfo() {
    304    MutexAutoLock lock(mLock);
    305    if (mConnection) {
    306      nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
    307      mConnection->GetTLSSocketControl(getter_AddRefs(tlsSocketControl));
    308      if (tlsSocketControl) {
    309        tlsSocketControl->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
    310      }
    311    }
    312  }
    313 
    314 private:
    315  class UpdateSecurityCallbacks : public Runnable {
    316   public:
    317    UpdateSecurityCallbacks(nsHttpTransaction* aTrans,
    318                            nsIInterfaceRequestor* aCallbacks)
    319        : Runnable("net::nsHttpTransaction::UpdateSecurityCallbacks"),
    320          mTrans(aTrans),
    321          mCallbacks(aCallbacks) {}
    322 
    323    NS_IMETHOD Run() override {
    324      if (mTrans->mConnection) {
    325        mTrans->mConnection->SetSecurityCallbacks(mCallbacks);
    326      }
    327      return NS_OK;
    328    }
    329 
    330   private:
    331    RefPtr<nsHttpTransaction> mTrans;
    332    nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
    333  };
    334 
    335  Mutex mLock MOZ_UNANNOTATED{"transaction lock"};
    336 
    337  nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
    338  nsCOMPtr<nsITransportEventSink> mTransportSink;
    339  nsCOMPtr<nsIEventTarget> mConsumerTarget;
    340  nsCOMPtr<nsITransportSecurityInfo> mSecurityInfo;
    341  nsCOMPtr<nsIAsyncInputStream> mPipeIn;
    342  nsCOMPtr<nsIAsyncOutputStream> mPipeOut;
    343  nsCOMPtr<nsIRequestContext> mRequestContext;
    344 
    345  uint64_t mChannelId{0};
    346 
    347  nsCString mReqHeaderBuf;  // flattened request headers
    348  nsCOMPtr<nsIInputStream> mRequestStream;
    349  int64_t mRequestSize{0};
    350 
    351  RefPtr<nsAHttpConnection> mConnection;
    352  RefPtr<nsHttpConnectionInfo> mConnInfo;
    353  // This is only set in UpdateConnectionInfo() when we have received a SVCB RR.
    354  // When echConfig is not used and the connection is failed, this transaction
    355  // will be restarted with this origin connection info directly.
    356  // When echConfig is enabled, there are two cases below.
    357  // 1. If all records have echConfig, we will retry other records except the
    358  // failed one. In the case all other records with echConfig are failed and the
    359  // pref network.dns.echconfig.fallback_to_origin_when_all_failed is true, this
    360  // origin connection info will be used.
    361  // 2. If only some records have echConfig and some not, we always fallback to
    362  // this origin conn info.
    363  RefPtr<nsHttpConnectionInfo> mOrigConnInfo;
    364  nsHttpRequestHead* mRequestHead{nullptr};    // weak ref
    365  nsHttpResponseHead* mResponseHead{nullptr};  // owning pointer
    366 
    367  nsAHttpSegmentReader* mReader{nullptr};
    368  nsAHttpSegmentWriter* mWriter{nullptr};
    369 
    370  nsCString mLineBuf;  // may contain a partial line
    371 
    372  int64_t mContentLength{-1};  // equals -1 if unknown
    373  int64_t mContentRead{0};     // count of consumed content bytes
    374  Atomic<int64_t, ReleaseAcquire> mTransferSize{0};  // count of received bytes
    375 
    376  // After a 304/204 or other "no-content" style response we will skip over
    377  // up to MAX_INVALID_RESPONSE_BODY_SZ bytes when looking for the next
    378  // response header to deal with servers that actually sent a response
    379  // body where they should not have. This member tracks how many bytes have
    380  // so far been skipped.
    381  uint32_t mInvalidResponseBytesRead{0};
    382 
    383  uint32_t mInitialRwin{0};
    384 
    385  nsHttpChunkedDecoder* mChunkedDecoder{nullptr};
    386 
    387  TimingStruct mTimings;
    388 
    389  nsresult mStatus{NS_OK};
    390 
    391  int16_t mPriority{0};
    392 
    393  // the number of times this transaction has been restarted
    394  uint16_t mRestartCount{0};
    395  Atomic<uint32_t, ReleaseAcquire> mCaps{0};
    396 
    397  HttpVersion mHttpVersion{HttpVersion::UNKNOWN};
    398  uint16_t mHttpResponseCode{0};
    399  nsCString mFlat407Headers;
    400 
    401  uint32_t mCurrentHttpResponseHeaderSize{0};
    402 
    403  int32_t const THROTTLE_NO_LIMIT = -1;
    404  // This can have 3 possible values:
    405  // * THROTTLE_NO_LIMIT - this means the transaction is not in any way limited
    406  //                       to read the response, this is the default
    407  // * a positive number - a limit is set because the transaction is obligated
    408  //                       to throttle the response read, this is decresed with
    409  //                       every piece of data the transaction receives
    410  // * zero - when the transaction depletes the limit for reading, this makes it
    411  //          stop reading and return WOULD_BLOCK from WriteSegments;
    412  //          transaction then waits for a call of ResumeReading that resets
    413  //          this member back to THROTTLE_NO_LIMIT
    414  int32_t mThrottlingReadAllowance{THROTTLE_NO_LIMIT};
    415 
    416  // mCapsToClear holds flags that should be cleared in mCaps, e.g. unset
    417  // NS_HTTP_REFRESH_DNS when DNS refresh request has completed to avoid
    418  // redundant requests on the network. The member itself is atomic, but
    419  // access to it from the networking thread may happen either before or
    420  // after the main thread modifies it. To deal with raciness, only unsetting
    421  // bitfields should be allowed: 'lost races' will thus err on the
    422  // conservative side, e.g. by going ahead with a 2nd DNS refresh.
    423  Atomic<uint32_t> mCapsToClear{0};
    424  Atomic<bool, ReleaseAcquire> mResponseIsComplete{false};
    425  Atomic<bool, ReleaseAcquire> mClosed{false};
    426  Atomic<bool, Relaxed> mIsHttp3Used{false};
    427 
    428  // True iff WriteSegments was called while this transaction should be
    429  // throttled (stop reading) Used to resume read on unblock of reading.  Conn
    430  // manager is responsible for calling back to resume reading.
    431  bool mReadingStopped{false};
    432 
    433  // state flags, all logically boolean, but not packed together into a
    434  // bitfield so as to avoid bitfield-induced races.  See bug 560579.
    435  bool mConnected{false};
    436  bool mActivated{false};
    437  bool mHaveStatusLine{false};
    438  bool mHaveAllHeaders{false};
    439  bool mTransactionDone{false};
    440  bool mDidContentStart{false};
    441  bool mNoContent{false};  // expecting an empty entity body
    442  bool mSentData{false};
    443  bool mReceivedData{false};
    444  bool mStatusEventPending{false};
    445  bool mHasRequestBody{false};
    446  bool mProxyConnectFailed{false};
    447  bool mHttpResponseMatched{false};
    448  bool mPreserveStream{false};
    449  bool mDispatchedAsBlocking{false};
    450  bool mResponseTimeoutEnabled{true};
    451  bool mForceRestart{false};
    452  bool mReuseOnRestart{false};
    453  bool mContentDecoding{false};
    454  bool mContentDecodingCheck{false};
    455  bool mDeferredSendProgress{false};
    456  bool mWaitingOnPipeOut{false};
    457  bool mDoNotRemoveAltSvc{false};
    458  bool mDoNotResetIPFamilyPreference{false};
    459  bool mIsHttp2Websocket{false};
    460 
    461  // mClosed           := transaction has been explicitly closed
    462  // mTransactionDone  := transaction ran to completion or was interrupted
    463  // mResponseComplete := transaction ran to completion
    464 
    465  // For Restart-In-Progress Functionality
    466  bool mReportedStart{false};
    467  bool mReportedResponseHeader{false};
    468 
    469  // protected by nsHttp::GetLock()
    470  bool mResponseHeadTaken{false};
    471  UniquePtr<nsHttpHeaderArray> mForTakeResponseTrailers;
    472  bool mResponseTrailersTaken{false};
    473 
    474  // Set when this transaction was restarted by call to Restart().  Used to tell
    475  // the http channel to reset proxy authentication.
    476  Atomic<bool> mRestarted{false};
    477 
    478  // The time when the transaction was submitted to the Connection Manager
    479  TimeDuration mPendingDurationTime;
    480 
    481  uint64_t mBrowserId{0};
    482 
    483  // IP address space of the browsing context that triggered this request
    484  nsILoadInfo::IPAddressSpace mParentIPAddressSpace{
    485      nsILoadInfo::IPAddressSpace::Unknown};
    486  struct LNAPerms mLnaPermissionStatus{};
    487 
    488  // For Rate Pacing via an EventTokenBucket
    489 public:
    490  // called by the connection manager to run this transaction through the
    491  // token bucket. If the token bucket admits the transaction immediately it
    492  // returns true. The function is called repeatedly until it returns true.
    493  bool TryToRunPacedRequest();
    494 
    495  // ATokenBucketEvent pure virtual implementation. Called by the token bucket
    496  // when the transaction is ready to run. If this happens asynchrounously to
    497  // token bucket submission the transaction just posts an event that causes
    498  // the pending transaction queue to be rerun (and TryToRunPacedRequest() to
    499  // be run again.
    500  void OnTokenBucketAdmitted() override;  // ATokenBucketEvent
    501 
    502  // CancelPacing() can be used to tell the token bucket to remove this
    503  // transaction from the list of pending transactions. This is used when a
    504  // transaction is believed to be HTTP/1 (and thus subject to rate pacing)
    505  // but later can be dispatched via spdy (not subject to rate pacing).
    506  void CancelPacing(nsresult reason);
    507 
    508  // Called by the connetion manager on the socket thread when reading for this
    509  // previously throttled transaction has to be resumed.
    510  void ResumeReading();
    511 
    512  // This examins classification of this transaction whether the Throttleable
    513  // class has been set while Leader, Unblocked, DontThrottle has not.
    514  bool EligibleForThrottling() const;
    515 
    516  bool AllowedToConnectToIpAddressSpace(
    517      nsILoadInfo::IPAddressSpace aTargetIpAddressSpace) override;
    518 
    519 private:
    520  bool mSubmittedRatePacing{false};
    521  bool mPassedRatePacing{false};
    522  bool mSynchronousRatePaceRequest{false};
    523  nsCOMPtr<nsICancelable> mTokenBucketCancel;
    524 
    525  void CollectTelemetryForUploads();
    526 
    527 public:
    528  ClassOfService GetClassOfService() {
    529    return {mClassOfServiceFlags, mClassOfServiceIncremental};
    530  }
    531 
    532 private:
    533  Atomic<uint32_t, Relaxed> mClassOfServiceFlags{0};
    534  Atomic<bool, Relaxed> mClassOfServiceIncremental{false};
    535 
    536 public:
    537  nsIInterfaceRequestor* SecurityCallbacks() { return mCallbacks; }
    538  // Called when this transaction is inserted in the pending queue.
    539  void OnPendingQueueInserted(const nsACString& aConnectionHashKey);
    540 
    541 private:
    542  TransactionObserverFunc mTransactionObserver;
    543  NetAddr mSelfAddr;
    544  NetAddr mPeerAddr;
    545  nsILoadInfo::IPAddressSpace mTargetIpAddressSpace{
    546      nsILoadInfo::IPAddressSpace::Unknown};
    547  bool mResolvedByTRR{false};
    548  Atomic<nsIRequest::TRRMode, Relaxed> mEffectiveTRRMode{
    549      nsIRequest::TRR_DEFAULT_MODE};
    550  Atomic<TRRSkippedReason, Relaxed> mTRRSkipReason{nsITRRSkipReason::TRR_UNSET};
    551  bool mEchConfigUsed = false;
    552 
    553  bool m0RTTInProgress{false};
    554  bool mDoNotTryEarlyData{false};
    555  enum {
    556    EARLY_NONE,
    557    EARLY_SENT,
    558    EARLY_ACCEPTED,
    559    EARLY_425
    560  } mEarlyDataDisposition{EARLY_NONE};
    561 
    562  HttpTrafficCategory mTrafficCategory{HttpTrafficCategory::eInvalid};
    563  Atomic<int32_t> mProxyConnectResponseCode{0};
    564 
    565  nsCOMPtr<nsICancelable> mDNSRequest;
    566  Atomic<uint32_t, Relaxed> mHTTPSSVCReceivedStage{HTTPSSVC_NOT_USED};
    567  bool m421Received = false;
    568  nsCOMPtr<nsIDNSHTTPSSVCRecord> mHTTPSSVCRecord;
    569  nsTArray<RefPtr<nsISVCBRecord>> mRecordsForRetry;
    570  bool mDontRetryWithDirectRoute = false;
    571  bool mFastFallbackTriggered = false;
    572  bool mHttp3BackupTimerCreated = false;
    573  bool mHttp3TunnelFallbackTimerCreated = false;
    574  nsCOMPtr<nsITimer> mFastFallbackTimer;
    575  nsCOMPtr<nsITimer> mHttp3BackupTimer;
    576  nsCOMPtr<nsITimer> mHttp3TunnelFallbackTimer;
    577  RefPtr<nsHttpConnectionInfo> mBackupConnInfo;
    578  // A clone of mConnInfo taken when this transaction is activated.
    579  // Describes the server that the associated connection is connected to.
    580  RefPtr<nsHttpConnectionInfo> mFinalizedConnInfo;
    581  RefPtr<HTTPSRecordResolver> mResolver;
    582  TRANSACTION_RESTART_REASON mRestartReason = TRANSACTION_RESTART_NONE;
    583 
    584  enum TRANSACTION_ECH_RETRY_COUNT : uint32_t {
    585    TRANSACTION_ECH_RETRY_OTHERS_COUNT = 0,
    586    TRANSACTION_ECH_RETRY_WITH_ECH_COUNT = 1,
    587    TRANSACTION_ECH_RETRY_WITHOUT_ECH_COUNT = 2,
    588    TRANSACTION_ECH_RETRY_ECH_FAILED_COUNT = 3,
    589  };
    590  nsTHashMap<nsUint32HashKey, uint32_t> mEchRetryCounterMap;
    591 
    592  bool mSupportsHTTP3 = false;
    593  Atomic<bool, Relaxed> mIsForWebTransport{false};
    594  bool mIsResettingForTunnelConn = false;
    595 
    596  bool mEarlyDataWasAvailable = false;
    597  bool ShouldRestartOn0RttError(nsresult reason);
    598 
    599  nsCOMPtr<nsIEarlyHintObserver> mEarlyHintObserver;
    600  // This hash key is set when a transaction is inserted into the connection
    601  // entry's pending queue.
    602  // See nsHttpConnectionMgr::GetOrCreateConnectionEntry(). A transaction could
    603  // be associated with the connection entry whose hash key is not the same as
    604  // this transaction's.
    605  nsCString mHashKeyOfConnectionEntry;
    606  // The CNAME of the host, or empty if none.
    607  nsCString mCname;
    608  nsCString mServerHeader;
    609 
    610  nsCOMPtr<WebTransportSessionEventListener> mWebTransportSessionEventListener;
    611 
    612  nsAutoCString mUrl;
    613 };
    614 
    615 }  // namespace mozilla::net
    616 
    617 #endif  // nsHttpTransaction_h__