/* -*- 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/. */
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
// 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;
}
// 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);
// 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);
// 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);
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
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};
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;
public:
nsIInterfaceRequestor* SecurityCallbacks() { return mCallbacks; } // Called when this transaction is inserted in the pending queue. void OnPendingQueueInserted(const nsACString& aConnectionHashKey);
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;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.