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