diff options
Diffstat (limited to '')
-rw-r--r-- | netwerk/protocol/http/nsHttpTransaction.h | 596 |
1 files changed, 596 insertions, 0 deletions
diff --git a/netwerk/protocol/http/nsHttpTransaction.h b/netwerk/protocol/http/nsHttpTransaction.h new file mode 100644 index 0000000000..364fa7b1e6 --- /dev/null +++ b/netwerk/protocol/http/nsHttpTransaction.h @@ -0,0 +1,596 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 nsHttpTransaction_h__ +#define nsHttpTransaction_h__ + +#include "ARefBase.h" +#include "EventTokenBucket.h" +#include "Http2Push.h" +#include "HttpTransactionShell.h" +#include "TimingStruct.h" +#include "mozilla/StaticPrefs_security.h" +#include "mozilla/net/DNS.h" +#include "mozilla/net/NeckoChannelParams.h" +#include "nsAHttpConnection.h" +#include "nsAHttpTransaction.h" +#include "nsCOMPtr.h" +#include "nsHttp.h" +#include "nsIAsyncOutputStream.h" +#include "nsIClassOfService.h" +#include "nsIEarlyHintObserver.h" +#include "nsIInterfaceRequestor.h" +#include "nsITLSSocketControl.h" +#include "nsITimer.h" +#include "nsIWebTransport.h" +#include "nsTHashMap.h" +#include "nsThreadUtils.h" + +//----------------------------------------------------------------------------- + +class nsIDNSHTTPSSVCRecord; +class nsIEventTarget; +class nsIInputStream; +class nsIOutputStream; +class nsIRequestContext; +class nsISVCBRecord; + +namespace mozilla::net { + +class HTTPSRecordResolver; +class nsHttpChunkedDecoder; +class nsHttpHeaderArray; +class nsHttpRequestHead; +class nsHttpResponseHead; +class NullHttpTransaction; +class Http2ConnectTransaction; + +//----------------------------------------------------------------------------- +// nsHttpTransaction represents a single HTTP transaction. It is thread-safe, +// intended to run on the socket thread. +//----------------------------------------------------------------------------- + +class nsHttpTransaction final : public nsAHttpTransaction, + public HttpTransactionShell, + public ATokenBucketEvent, + public nsIInputStreamCallback, + public nsIOutputStreamCallback, + public ARefBase, + public nsITimerCallback, + public nsINamed { + public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSAHTTPTRANSACTION + NS_DECL_HTTPTRANSACTIONSHELL + NS_DECL_NSIINPUTSTREAMCALLBACK + NS_DECL_NSIOUTPUTSTREAMCALLBACK + NS_DECL_NSITIMERCALLBACK + NS_DECL_NSINAMED + + nsHttpTransaction(); + + void OnActivated() override; + + // attributes + nsHttpResponseHead* ResponseHead() { + return mHaveAllHeaders ? mResponseHead : nullptr; + } + + nsIEventTarget* ConsumerTarget() { return mConsumerTarget; } + + // Called to set/find out if the transaction generated a complete response. + void SetResponseIsComplete() { mResponseIsComplete = true; } + + void EnableKeepAlive() { mCaps |= NS_HTTP_ALLOW_KEEPALIVE; } + void MakeSticky() { mCaps |= NS_HTTP_STICKY_CONNECTION; } + void MakeNonSticky() override { mCaps &= ~NS_HTTP_STICKY_CONNECTION; } + void MakeRestartable() override { mCaps |= NS_HTTP_CONNECTION_RESTARTABLE; } + void MakeNonRestartable() { mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE; } + void RemoveConnection(); + void SetIsHttp2Websocket(bool h2ws) override { mIsHttp2Websocket = h2ws; } + bool IsHttp2Websocket() override { return mIsHttp2Websocket; } + + void SetTRRInfo(nsIRequest::TRRMode aMode, + TRRSkippedReason aSkipReason) override { + mEffectiveTRRMode = aMode; + mTRRSkipReason = aSkipReason; + } + + bool WaitingForHTTPSRR() const { return mCaps & NS_HTTP_FORCE_WAIT_HTTP_RR; } + void MakeDontWaitHTTPSRR() { mCaps &= ~NS_HTTP_FORCE_WAIT_HTTP_RR; } + + // SetPriority() may only be used by the connection manager. + void SetPriority(int32_t priority) { mPriority = priority; } + int32_t Priority() { return mPriority; } + + void PrintDiagnostics(nsCString& log); + + // Sets mPendingTime to the current time stamp or to a null time stamp (if now + // is false) + void SetPendingTime(bool now = true) { + mozilla::MutexAutoLock lock(mLock); + if (!now && !mPendingTime.IsNull()) { + // Remember how long it took. We will use this value to record + // TRANSACTION_WAIT_TIME_HTTP2_SUP_HTTP3 telemetry, but we need to wait + // for the response headers. + mPendingDurationTime = TimeStamp::Now() - mPendingTime; + } + // Note that the transaction could be added in to a pending queue multiple + // times (when the transaction is restarted or moved to a new conn entry due + // to HTTPS RR), so we should only set the pending time once. + if (mPendingTime.IsNull()) { + mPendingTime = now ? TimeStamp::Now() : TimeStamp(); + } + } + TimeStamp GetPendingTime() override { + mozilla::MutexAutoLock lock(mLock); + return mPendingTime; + } + + // overload of nsAHttpTransaction::RequestContext() + nsIRequestContext* RequestContext() override { return mRequestContext.get(); } + void DispatchedAsBlocking(); + void RemoveDispatchedAsBlocking(); + + void DisableSpdy() override; + void DisableHttp2ForProxy() override; + void DoNotRemoveAltSvc() override { mDoNotRemoveAltSvc = true; } + void DisableHttp3(bool aAllowRetryHTTPSRR) override; + + nsHttpTransaction* QueryHttpTransaction() override { return this; } + + already_AddRefed<Http2PushedStreamWrapper> GetPushedStream() { + return do_AddRef(mPushedStream); + } + already_AddRefed<Http2PushedStreamWrapper> TakePushedStream() { + return mPushedStream.forget(); + } + + uint32_t InitialRwin() const { return mInitialRwin; }; + bool ChannelPipeFull() { return mWaitingOnPipeOut; } + + // Locked methods to get and set timing info + void BootstrapTimings(TimingStruct times); + void SetConnectStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false); + void SetConnectEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false); + void SetRequestStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false); + void SetResponseStart(mozilla::TimeStamp timeStamp, bool onlyIfNull = false); + void SetResponseEnd(mozilla::TimeStamp timeStamp, bool onlyIfNull = false); + + [[nodiscard]] bool Do0RTT() override; + [[nodiscard]] nsresult Finish0RTT(bool aRestart, + bool aAlpnChanged /* ignored */) override; + + // After Finish0RTT early data may have failed but the caller did not request + // restart - this indicates that state for dev tools + void Refused0RTT(); + + uint64_t BrowserId() override { return mBrowserId; } + + void SetHttpTrailers(nsCString& aTrailers); + + bool IsWebsocketUpgrade(); + + void OnProxyConnectComplete(int32_t aResponseCode) override; + void SetFlat407Headers(const nsACString& aHeaders); + + // This is only called by Http2PushedStream::TryOnPush when a new pushed + // stream is available. The newly added stream will be taken by another + // transaction. + void OnPush(Http2PushedStreamWrapper* aStream); + + void UpdateConnectionInfo(nsHttpConnectionInfo* aConnInfo); + + void SetClassOfService(ClassOfService cos); + + virtual nsresult OnHTTPSRRAvailable( + nsIDNSHTTPSSVCRecord* aHTTPSSVCRecord, + nsISVCBRecord* aHighestPriorityRecord) override; + + void GetHashKeyOfConnectionEntry(nsACString& aResult); + + bool IsForWebTransport() { return mIsForWebTransport; } + + private: + friend class DeleteHttpTransaction; + virtual ~nsHttpTransaction(); + + [[nodiscard]] nsresult Restart(); + char* LocateHttpStart(char* buf, uint32_t len, bool aAllowPartialMatch); + [[nodiscard]] nsresult ParseLine(nsACString& line); + [[nodiscard]] nsresult ParseLineSegment(char* seg, uint32_t len); + [[nodiscard]] nsresult ParseHead(char*, uint32_t count, uint32_t* countRead); + [[nodiscard]] nsresult HandleContentStart(); + [[nodiscard]] nsresult HandleContent(char*, uint32_t count, + uint32_t* contentRead, + uint32_t* contentRemaining); + [[nodiscard]] nsresult ProcessData(char*, uint32_t, uint32_t*); + void DeleteSelfOnConsumerThread(); + void ReleaseBlockingTransaction(); + + [[nodiscard]] static nsresult ReadRequestSegment(nsIInputStream*, void*, + const char*, uint32_t, + uint32_t, uint32_t*); + [[nodiscard]] static nsresult WritePipeSegment(nsIOutputStream*, void*, char*, + uint32_t, uint32_t, uint32_t*); + + bool TimingEnabled() const { return mCaps & NS_HTTP_TIMING_ENABLED; } + + bool ResponseTimeoutEnabled() const final; + + void ReuseConnectionOnRestartOK(bool reuseOk) override { + mReuseOnRestart = reuseOk; + } + + // Called right after we parsed the response head. Checks for connection + // based authentication schemes in reponse headers for WWW and Proxy + // authentication. If such is found in any of them, NS_HTTP_STICKY_CONNECTION + // is set in mCaps. We need the sticky flag be set early to keep the + // connection from very start of the authentication process. + void CheckForStickyAuthScheme(); + void CheckForStickyAuthSchemeAt(nsHttpAtom const& header); + bool IsStickyAuthSchemeAt(nsACString const& auth); + + // Called from WriteSegments. Checks for conditions whether to throttle + // reading the content. When this returns true, WriteSegments returns + // WOULD_BLOCK. + bool ShouldThrottle(); + + void NotifyTransactionObserver(nsresult reason); + + // When echConfig is enabled, this function put other available records + // in mRecordsForRetry. Returns true when mRecordsForRetry is not empty, + // otherwise returns false. + bool PrepareSVCBRecordsForRetry(const nsACString& aFailedDomainName, + const nsACString& aFailedAlpn, + bool& aAllRecordsHaveEchConfig); + // This function setups a new connection info for restarting this transaction. + void PrepareConnInfoForRetry(nsresult aReason); + // This function is used to select the next non http3 record and is only + // executed when the fast fallback timer is triggered. + already_AddRefed<nsHttpConnectionInfo> PrepareFastFallbackConnInfo( + bool aEchConfigUsed); + + void MaybeReportFailedSVCDomain(nsresult aReason, + nsHttpConnectionInfo* aFailedConnInfo); + + already_AddRefed<Http2PushedStreamWrapper> TakePushedStreamById( + uint32_t aStreamId); + + // IMPORTANT: when adding new values, always add them to the end, otherwise + // it will mess up telemetry. + enum HTTPSSVC_CONNECTION_FAILED_REASON : uint32_t { + HTTPSSVC_CONNECTION_OK = 0, + HTTPSSVC_CONNECTION_UNKNOWN_HOST = 1, + HTTPSSVC_CONNECTION_UNREACHABLE = 2, + HTTPSSVC_CONNECTION_421_RECEIVED = 3, + HTTPSSVC_CONNECTION_SECURITY_ERROR = 4, + HTTPSSVC_CONNECTION_NO_USABLE_RECORD = 5, + HTTPSSVC_CONNECTION_ALL_RECORDS_EXCLUDED = 6, + HTTPSSVC_CONNECTION_OTHERS = 7, + }; + HTTPSSVC_CONNECTION_FAILED_REASON ErrorCodeToFailedReason( + nsresult aErrorCode); + + void OnHttp3BackupTimer(); + void OnBackupConnectionReady(bool aTriggeredByHTTPSRR); + void OnFastFallbackTimer(); + void HandleFallback(nsHttpConnectionInfo* aFallbackConnInfo); + void MaybeCancelFallbackTimer(); + + // IMPORTANT: when adding new values, always add them to the end, otherwise + // it will mess up telemetry. + enum TRANSACTION_RESTART_REASON : uint32_t { + TRANSACTION_RESTART_NONE = 0, // The transacion was not restarted. + TRANSACTION_RESTART_FORCED, // The transaction was forced to restart. + TRANSACTION_RESTART_NO_DATA_SENT, + TRANSACTION_RESTART_DOWNGRADE_WITH_EARLY_DATA, + TRANSACTION_RESTART_HTTPS_RR_NET_RESET, + TRANSACTION_RESTART_HTTPS_RR_CONNECTION_REFUSED, + TRANSACTION_RESTART_HTTPS_RR_UNKNOWN_HOST, + TRANSACTION_RESTART_HTTPS_RR_NET_TIMEOUT, + TRANSACTION_RESTART_HTTPS_RR_SEC_ERROR, + TRANSACTION_RESTART_HTTPS_RR_FAST_FALLBACK, + TRANSACTION_RESTART_HTTP3_FAST_FALLBACK, + TRANSACTION_RESTART_OTHERS, + TRANSACTION_RESTART_PROTOCOL_VERSION_ALERT, + }; + void SetRestartReason(TRANSACTION_RESTART_REASON aReason); + + bool HandleWebTransportResponse(uint16_t aStatus); + + void MaybeRefreshSecurityInfo() { + MutexAutoLock lock(mLock); + if (mConnection) { + nsCOMPtr<nsITLSSocketControl> tlsSocketControl; + mConnection->GetTLSSocketControl(getter_AddRefs(tlsSocketControl)); + if (tlsSocketControl) { + tlsSocketControl->GetSecurityInfo(getter_AddRefs(mSecurityInfo)); + } + } + } + + private: + class UpdateSecurityCallbacks : public Runnable { + public: + UpdateSecurityCallbacks(nsHttpTransaction* aTrans, + nsIInterfaceRequestor* aCallbacks) + : Runnable("net::nsHttpTransaction::UpdateSecurityCallbacks"), + mTrans(aTrans), + mCallbacks(aCallbacks) {} + + NS_IMETHOD Run() override { + if (mTrans->mConnection) { + mTrans->mConnection->SetSecurityCallbacks(mCallbacks); + } + return NS_OK; + } + + private: + RefPtr<nsHttpTransaction> mTrans; + nsCOMPtr<nsIInterfaceRequestor> mCallbacks; + }; + + Mutex mLock MOZ_UNANNOTATED{"transaction lock"}; + + nsCOMPtr<nsIInterfaceRequestor> mCallbacks; + nsCOMPtr<nsITransportEventSink> mTransportSink; + nsCOMPtr<nsIEventTarget> mConsumerTarget; + nsCOMPtr<nsITransportSecurityInfo> mSecurityInfo; + nsCOMPtr<nsIAsyncInputStream> mPipeIn; + nsCOMPtr<nsIAsyncOutputStream> mPipeOut; + nsCOMPtr<nsIRequestContext> mRequestContext; + + uint64_t mChannelId{0}; + + nsCString mReqHeaderBuf; // flattened request headers + nsCOMPtr<nsIInputStream> mRequestStream; + int64_t mRequestSize{0}; + + RefPtr<nsAHttpConnection> mConnection; + RefPtr<nsHttpConnectionInfo> mConnInfo; + // This is only set in UpdateConnectionInfo() when we have received a SVCB RR. + // When echConfig is not used and the connection is failed, this transaction + // will be restarted with this origin connection info directly. + // When echConfig is enabled, there are two cases below. + // 1. If all records have echConfig, we will retry other records except the + // failed one. In the case all other records with echConfig are failed and the + // pref network.dns.echconfig.fallback_to_origin_when_all_failed is true, this + // origin connection info will be used. + // 2. If only some records have echConfig and some not, we always fallback to + // this origin conn info. + RefPtr<nsHttpConnectionInfo> mOrigConnInfo; + nsHttpRequestHead* mRequestHead{nullptr}; // weak ref + nsHttpResponseHead* mResponseHead{nullptr}; // owning pointer + + nsAHttpSegmentReader* mReader{nullptr}; + nsAHttpSegmentWriter* mWriter{nullptr}; + + nsCString mLineBuf; // may contain a partial line + + int64_t mContentLength{-1}; // equals -1 if unknown + int64_t mContentRead{0}; // count of consumed content bytes + Atomic<int64_t, ReleaseAcquire> mTransferSize{0}; // count of received bytes + + // After a 304/204 or other "no-content" style response we will skip over + // up to MAX_INVALID_RESPONSE_BODY_SZ bytes when looking for the next + // response header to deal with servers that actually sent a response + // body where they should not have. This member tracks how many bytes have + // so far been skipped. + uint32_t mInvalidResponseBytesRead{0}; + + RefPtr<Http2PushedStreamWrapper> mPushedStream; + uint32_t mInitialRwin{0}; + + nsHttpChunkedDecoder* mChunkedDecoder{nullptr}; + + TimingStruct mTimings; + + nsresult mStatus{NS_OK}; + + int16_t mPriority{0}; + + // the number of times this transaction has been restarted + uint16_t mRestartCount{0}; + Atomic<uint32_t, ReleaseAcquire> mCaps{0}; + + HttpVersion mHttpVersion{HttpVersion::UNKNOWN}; + uint16_t mHttpResponseCode{0}; + nsCString mFlat407Headers; + + uint32_t mCurrentHttpResponseHeaderSize{0}; + + int32_t const THROTTLE_NO_LIMIT = -1; + // This can have 3 possible values: + // * THROTTLE_NO_LIMIT - this means the transaction is not in any way limited + // to read the response, this is the default + // * a positive number - a limit is set because the transaction is obligated + // to throttle the response read, this is decresed with + // every piece of data the transaction receives + // * zero - when the transaction depletes the limit for reading, this makes it + // stop reading and return WOULD_BLOCK from WriteSegments; + // transaction then waits for a call of ResumeReading that resets + // this member back to THROTTLE_NO_LIMIT + int32_t mThrottlingReadAllowance{THROTTLE_NO_LIMIT}; + + // mCapsToClear holds flags that should be cleared in mCaps, e.g. unset + // NS_HTTP_REFRESH_DNS when DNS refresh request has completed to avoid + // redundant requests on the network. The member itself is atomic, but + // access to it from the networking thread may happen either before or + // after the main thread modifies it. To deal with raciness, only unsetting + // bitfields should be allowed: 'lost races' will thus err on the + // conservative side, e.g. by going ahead with a 2nd DNS refresh. + Atomic<uint32_t> mCapsToClear{0}; + Atomic<bool, ReleaseAcquire> mResponseIsComplete{false}; + Atomic<bool, ReleaseAcquire> mClosed{false}; + Atomic<bool, Relaxed> mIsHttp3Used{false}; + + // True iff WriteSegments was called while this transaction should be + // throttled (stop reading) Used to resume read on unblock of reading. Conn + // manager is responsible for calling back to resume reading. + bool mReadingStopped{false}; + + // state flags, all logically boolean, but not packed together into a + // bitfield so as to avoid bitfield-induced races. See bug 560579. + bool mConnected{false}; + bool mActivated{false}; + bool mHaveStatusLine{false}; + bool mHaveAllHeaders{false}; + bool mTransactionDone{false}; + bool mDidContentStart{false}; + bool mNoContent{false}; // expecting an empty entity body + bool mSentData{false}; + bool mReceivedData{false}; + bool mStatusEventPending{false}; + bool mHasRequestBody{false}; + bool mProxyConnectFailed{false}; + bool mHttpResponseMatched{false}; + bool mPreserveStream{false}; + bool mDispatchedAsBlocking{false}; + bool mResponseTimeoutEnabled{true}; + bool mForceRestart{false}; + bool mReuseOnRestart{false}; + bool mContentDecoding{false}; + bool mContentDecodingCheck{false}; + bool mDeferredSendProgress{false}; + bool mWaitingOnPipeOut{false}; + bool mDoNotRemoveAltSvc{false}; + bool mIsHttp2Websocket{false}; + + // mClosed := transaction has been explicitly closed + // mTransactionDone := transaction ran to completion or was interrupted + // mResponseComplete := transaction ran to completion + + // For Restart-In-Progress Functionality + bool mReportedStart{false}; + bool mReportedResponseHeader{false}; + + // protected by nsHttp::GetLock() + bool mResponseHeadTaken{false}; + UniquePtr<nsHttpHeaderArray> mForTakeResponseTrailers; + bool mResponseTrailersTaken{false}; + + // Set when this transaction was restarted by call to Restart(). Used to tell + // the http channel to reset proxy authentication. + Atomic<bool> mRestarted{false}; + + // The time when the transaction was submitted to the Connection Manager + TimeStamp mPendingTime; + TimeDuration mPendingDurationTime; + + uint64_t mBrowserId{0}; + + // For Rate Pacing via an EventTokenBucket + public: + // called by the connection manager to run this transaction through the + // token bucket. If the token bucket admits the transaction immediately it + // returns true. The function is called repeatedly until it returns true. + bool TryToRunPacedRequest(); + + // ATokenBucketEvent pure virtual implementation. Called by the token bucket + // when the transaction is ready to run. If this happens asynchrounously to + // token bucket submission the transaction just posts an event that causes + // the pending transaction queue to be rerun (and TryToRunPacedRequest() to + // be run again. + void OnTokenBucketAdmitted() override; // ATokenBucketEvent + + // CancelPacing() can be used to tell the token bucket to remove this + // transaction from the list of pending transactions. This is used when a + // transaction is believed to be HTTP/1 (and thus subject to rate pacing) + // but later can be dispatched via spdy (not subject to rate pacing). + void CancelPacing(nsresult reason); + + // Called by the connetion manager on the socket thread when reading for this + // previously throttled transaction has to be resumed. + void ResumeReading(); + + // This examins classification of this transaction whether the Throttleable + // class has been set while Leader, Unblocked, DontThrottle has not. + bool EligibleForThrottling() const; + + private: + bool mSubmittedRatePacing{false}; + bool mPassedRatePacing{false}; + bool mSynchronousRatePaceRequest{false}; + nsCOMPtr<nsICancelable> mTokenBucketCancel; + + void CollectTelemetryForUploads(); + + public: + ClassOfService GetClassOfService() { + return {mClassOfServiceFlags, mClassOfServiceIncremental}; + } + + private: + Atomic<uint32_t, Relaxed> mClassOfServiceFlags{0}; + Atomic<bool, Relaxed> mClassOfServiceIncremental{false}; + + public: + nsIInterfaceRequestor* SecurityCallbacks() { return mCallbacks; } + // Called when this transaction is inserted in the pending queue. + void OnPendingQueueInserted(const nsACString& aConnectionHashKey); + + private: + TransactionObserverFunc mTransactionObserver; + NetAddr mSelfAddr; + NetAddr mPeerAddr; + bool mResolvedByTRR{false}; + Atomic<nsIRequest::TRRMode, Relaxed> mEffectiveTRRMode{ + nsIRequest::TRR_DEFAULT_MODE}; + Atomic<TRRSkippedReason, Relaxed> mTRRSkipReason{nsITRRSkipReason::TRR_UNSET}; + bool mEchConfigUsed = false; + + bool m0RTTInProgress{false}; + bool mDoNotTryEarlyData{false}; + enum { + EARLY_NONE, + EARLY_SENT, + EARLY_ACCEPTED, + EARLY_425 + } mEarlyDataDisposition{EARLY_NONE}; + + HttpTrafficCategory mTrafficCategory{HttpTrafficCategory::eInvalid}; + bool mThroughCaptivePortal; + Atomic<int32_t> mProxyConnectResponseCode{0}; + + OnPushCallback mOnPushCallback; + nsTHashMap<uint32_t, RefPtr<Http2PushedStreamWrapper>> mIDToStreamMap; + + nsCOMPtr<nsICancelable> mDNSRequest; + Atomic<uint32_t, Relaxed> mHTTPSSVCReceivedStage{HTTPSSVC_NOT_USED}; + bool m421Received = false; + nsCOMPtr<nsIDNSHTTPSSVCRecord> mHTTPSSVCRecord; + nsTArray<RefPtr<nsISVCBRecord>> mRecordsForRetry; + bool mDontRetryWithDirectRoute = false; + bool mFastFallbackTriggered = false; + bool mHttp3BackupTimerCreated = false; + nsCOMPtr<nsITimer> mFastFallbackTimer; + nsCOMPtr<nsITimer> mHttp3BackupTimer; + RefPtr<nsHttpConnectionInfo> mBackupConnInfo; + RefPtr<HTTPSRecordResolver> mResolver; + TRANSACTION_RESTART_REASON mRestartReason = TRANSACTION_RESTART_NONE; + + nsTHashMap<nsUint32HashKey, uint32_t> mEchRetryCounterMap; + + bool mSupportsHTTP3 = false; + Atomic<bool, Relaxed> mIsForWebTransport{false}; + + bool mEarlyDataWasAvailable = false; + bool ShouldRestartOn0RttError(nsresult reason); + + nsCOMPtr<nsIEarlyHintObserver> mEarlyHintObserver; + // This hash key is set when a transaction is inserted into the connection + // entry's pending queue. + // See nsHttpConnectionMgr::GetOrCreateConnectionEntry(). A transaction could + // be associated with the connection entry whose hash key is not the same as + // this transaction's. + nsCString mHashKeyOfConnectionEntry; + + nsCOMPtr<WebTransportSessionEventListener> mWebTransportSessionEventListener; +}; + +} // namespace mozilla::net + +#endif // nsHttpTransaction_h__ |