603 lines
23 KiB
C++
603 lines
23 KiB
C++
/* -*- 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 "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; }
|
|
bool Closed() { return mClosed; }
|
|
|
|
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 mTimings.transactionPending 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 && !mTimings.transactionPending.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() - mTimings.transactionPending;
|
|
}
|
|
// 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 (mTimings.transactionPending.IsNull()) {
|
|
mTimings.transactionPending = now ? TimeStamp::Now() : TimeStamp();
|
|
}
|
|
}
|
|
TimeStamp GetPendingTime() override {
|
|
mozilla::MutexAutoLock lock(mLock);
|
|
return mTimings.transactionPending;
|
|
}
|
|
|
|
// 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 DoNotResetIPFamilyPreference() override {
|
|
mDoNotResetIPFamilyPreference = true;
|
|
}
|
|
void DisableHttp3(bool aAllowRetryHTTPSRR) override;
|
|
|
|
nsHttpTransaction* QueryHttpTransaction() override { return this; }
|
|
|
|
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);
|
|
|
|
void UpdateConnectionInfo(nsHttpConnectionInfo* aConnInfo);
|
|
|
|
void SetClassOfService(ClassOfService cos);
|
|
|
|
virtual nsresult OnHTTPSRRAvailable(nsIDNSHTTPSSVCRecord* aHTTPSSVCRecord,
|
|
nsISVCBRecord* aHighestPriorityRecord,
|
|
const nsACString& aCname) override;
|
|
|
|
void GetHashKeyOfConnectionEntry(nsACString& aResult);
|
|
|
|
bool IsForWebTransport() override { return mIsForWebTransport; }
|
|
bool IsResettingForTunnelConn() override { return mIsResettingForTunnelConn; }
|
|
void SetResettingForTunnelConn(bool aValue) override {
|
|
mIsResettingForTunnelConn = aValue;
|
|
}
|
|
|
|
nsAutoCString GetUrl() { return mUrl; }
|
|
|
|
uint64_t ChannelId() { return mChannelId; }
|
|
|
|
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 ReportResponseHeader(uint32_t aSubType);
|
|
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 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);
|
|
|
|
void FinalizeConnInfo();
|
|
|
|
// 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,
|
|
TRANSACTION_RESTART_POSSIBLE_0RTT_ERROR
|
|
};
|
|
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};
|
|
|
|
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 mDoNotResetIPFamilyPreference{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
|
|
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};
|
|
Atomic<int32_t> mProxyConnectResponseCode{0};
|
|
|
|
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;
|
|
// A clone of mConnInfo taken when this transaction is activated.
|
|
// Describes the server that the associated connection is connected to.
|
|
RefPtr<nsHttpConnectionInfo> mFinalizedConnInfo;
|
|
RefPtr<HTTPSRecordResolver> mResolver;
|
|
TRANSACTION_RESTART_REASON mRestartReason = TRANSACTION_RESTART_NONE;
|
|
|
|
enum TRANSACTION_ECH_RETRY_COUNT : uint32_t {
|
|
TRANSACTION_ECH_RETRY_OTHERS_COUNT = 0,
|
|
TRANSACTION_ECH_RETRY_WITH_ECH_COUNT = 1,
|
|
TRANSACTION_ECH_RETRY_WITHOUT_ECH_COUNT = 2,
|
|
TRANSACTION_ECH_RETRY_ECH_FAILED_COUNT = 3,
|
|
};
|
|
nsTHashMap<nsUint32HashKey, uint32_t> mEchRetryCounterMap;
|
|
|
|
bool mSupportsHTTP3 = false;
|
|
Atomic<bool, Relaxed> mIsForWebTransport{false};
|
|
bool mIsResettingForTunnelConn = 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;
|
|
// The CNAME of the host, or empty if none.
|
|
nsCString mCname;
|
|
nsCString mServerHeader;
|
|
|
|
nsCOMPtr<WebTransportSessionEventListener> mWebTransportSessionEventListener;
|
|
|
|
nsAutoCString mUrl;
|
|
};
|
|
|
|
} // namespace mozilla::net
|
|
|
|
#endif // nsHttpTransaction_h__
|