tor-browser

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

nsHttpConnection.h (14239B)


      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 nsHttpConnection_h__
      7 #define nsHttpConnection_h__
      8 
      9 #include <functional>
     10 #include "HttpConnectionBase.h"
     11 #include "nsHttpConnectionInfo.h"
     12 #include "nsHttpResponseHead.h"
     13 #include "nsAHttpTransaction.h"
     14 #include "nsCOMPtr.h"
     15 #include "nsProxyRelease.h"
     16 #include "prinrval.h"
     17 #include "mozilla/Mutex.h"
     18 #include "ARefBase.h"
     19 #include "TimingStruct.h"
     20 #include "HttpTrafficAnalyzer.h"
     21 #include "TlsHandshaker.h"
     22 
     23 #include "nsIAsyncInputStream.h"
     24 #include "nsIAsyncOutputStream.h"
     25 #include "nsIInterfaceRequestor.h"
     26 #include "nsILoadInfo.h"
     27 #include "nsISocketTransport.h"
     28 #include "nsISupportsPriority.h"
     29 #include "nsITimer.h"
     30 #include "nsITlsHandshakeListener.h"
     31 
     32 class nsISocketTransport;
     33 class nsITLSSocketControl;
     34 
     35 namespace mozilla {
     36 namespace net {
     37 
     38 class nsHttpHandler;
     39 class ASpdySession;
     40 
     41 // 1dcc863e-db90-4652-a1fe-13fea0b54e46
     42 #define NS_HTTPCONNECTION_IID \
     43  {0x1dcc863e, 0xdb90, 0x4652, {0xa1, 0xfe, 0x13, 0xfe, 0xa0, 0xb5, 0x4e, 0x46}}
     44 
     45 //-----------------------------------------------------------------------------
     46 // nsHttpConnection - represents a connection to a HTTP server (or proxy)
     47 //
     48 // NOTE: this objects lives on the socket thread only.  it should not be
     49 // accessed from any other thread.
     50 //-----------------------------------------------------------------------------
     51 
     52 class nsHttpConnection final : public HttpConnectionBase,
     53                               public nsAHttpSegmentReader,
     54                               public nsAHttpSegmentWriter,
     55                               public nsIInputStreamCallback,
     56                               public nsIOutputStreamCallback,
     57                               public nsITransportEventSink,
     58                               public nsIInterfaceRequestor {
     59 private:
     60  virtual ~nsHttpConnection();
     61 
     62 public:
     63  NS_INLINE_DECL_STATIC_IID(NS_HTTPCONNECTION_IID)
     64  NS_DECL_HTTPCONNECTIONBASE
     65  NS_DECL_THREADSAFE_ISUPPORTS
     66  NS_DECL_NSAHTTPSEGMENTREADER
     67  NS_DECL_NSAHTTPSEGMENTWRITER
     68  NS_DECL_NSIINPUTSTREAMCALLBACK
     69  NS_DECL_NSIOUTPUTSTREAMCALLBACK
     70  NS_DECL_NSITRANSPORTEVENTSINK
     71  NS_DECL_NSIINTERFACEREQUESTOR
     72 
     73  nsHttpConnection();
     74 
     75  // Initialize the connection:
     76  //  info        - specifies the connection parameters.
     77  //  maxHangTime - limits the amount of time this connection can spend on a
     78  //                single transaction before it should no longer be kept
     79  //                alive.  a value of 0xffff indicates no limit.
     80  [[nodiscard]] virtual nsresult Init(nsHttpConnectionInfo* info,
     81                                      uint16_t maxHangTime, nsISocketTransport*,
     82                                      nsIAsyncInputStream*,
     83                                      nsIAsyncOutputStream*,
     84                                      bool connectedTransport, nsresult status,
     85                                      nsIInterfaceRequestor*, PRIntervalTime,
     86                                      bool forWebSocket);
     87 
     88  //-------------------------------------------------------------------------
     89  // XXX document when these are ok to call
     90 
     91  bool IsKeepAlive() {
     92    return (mUsingSpdyVersion != SpdyVersion::NONE) ||
     93           (mKeepAliveMask && mKeepAlive);
     94  }
     95 
     96  // Returns time in seconds for how long connection can be reused.
     97  uint32_t TimeToLive();
     98 
     99  bool NeedSpdyTunnel() {
    100    return mConnInfo->UsingHttpsProxy() && !mHasTLSTransportLayer &&
    101           mConnInfo->UsingConnect();
    102  }
    103 
    104  // A connection is forced into plaintext when it is intended to be used as a
    105  // CONNECT tunnel but the setup fails. The plaintext only carries the CONNECT
    106  // error.
    107  void ForcePlainText() { mForcePlainText = true; }
    108 
    109  bool IsUrgentStartPreferred() const {
    110    return mUrgentStartPreferredKnown && mUrgentStartPreferred;
    111  }
    112  void SetUrgentStartPreferred(bool urgent);
    113 
    114  void SetIsReusedAfter(uint32_t afterMilliseconds);
    115 
    116  int64_t MaxBytesRead() { return mMaxBytesRead; }
    117  HttpVersion GetLastHttpResponseVersion() { return mLastHttpResponseVersion; }
    118 
    119  friend class HttpConnectionForceIO;
    120  friend class TlsHandshaker;
    121 
    122  // When a persistent connection is in the connection manager idle
    123  // connection pool, the nsHttpConnection still reads errors and hangups
    124  // on the socket so that it can be proactively released if the server
    125  // initiates a termination. Only call on socket thread.
    126  void BeginIdleMonitoring();
    127  void EndIdleMonitoring();
    128 
    129  bool UsingSpdy() override { return (mUsingSpdyVersion != SpdyVersion::NONE); }
    130  SpdyVersion GetSpdyVersion() { return mUsingSpdyVersion; }
    131  bool EverUsedSpdy() { return mEverUsedSpdy; }
    132  bool UsingHttp3() override { return false; }
    133 
    134  // true when connection SSL NPN phase is complete and we know
    135  // authoritatively whether UsingSpdy() or not.
    136  bool ReportedNPN() { return mReportedSpdy; }
    137 
    138  // When the connection is active this is called up to once every 1 second
    139  // return the interval (in seconds) that the connection next wants to
    140  // have this invoked. It might happen sooner depending on the needs of
    141  // other connections.
    142  uint32_t ReadTimeoutTick(PRIntervalTime now);
    143 
    144  // For Active and Idle connections, this will be called when
    145  // mTCPKeepaliveTransitionTimer fires, to check if the TCP keepalive config
    146  // should move from short-lived (fast-detect) to long-lived.
    147  static void UpdateTCPKeepalive(nsITimer* aTimer, void* aClosure);
    148 
    149  // When the connection is active this is called every second
    150  void ReadTimeoutTick();
    151 
    152  int64_t ContentBytesWritten() { return mContentBytesWritten; }
    153 
    154  void SetupSecondaryTLS();
    155  void SetInTunnel() override;
    156 
    157  // Check active connections for traffic (or not). SPDY connections send a
    158  // ping, ordinary HTTP connections get some time to get traffic to be
    159  // considered alive.
    160  void CheckForTraffic(bool check);
    161 
    162  // NoTraffic() returns true if there's been no traffic on the (non-spdy)
    163  // connection since CheckForTraffic() was called.
    164  bool NoTraffic() {
    165    return mTrafficStamp &&
    166           (mTrafficCount == (mTotalBytesWritten + mTotalBytesRead));
    167  }
    168 
    169  // Return true when the socket this connection is using has not been
    170  // authenticated using a client certificate.  Before SSL negotiation
    171  // has finished this returns false.
    172  bool NoClientCertAuth() const override;
    173 
    174  ExtendedCONNECTSupport GetExtendedCONNECTSupport() override;
    175 
    176  int64_t BytesWritten() override { return mTotalBytesWritten; }
    177 
    178  nsISocketTransport* Transport() override { return mSocketTransport; }
    179 
    180  nsresult GetSelfAddr(NetAddr* addr) override;
    181  nsresult GetPeerAddr(NetAddr* addr) override;
    182  bool ResolvedByTRR() override;
    183  bool GetEchConfigUsed() override;
    184  nsIRequest::TRRMode EffectiveTRRMode() override;
    185  TRRSkippedReason TRRSkipReason() override;
    186  bool IsForWebSocket() { return mForWebSocket; }
    187 
    188  // The following functions are related to setting up a tunnel.
    189  [[nodiscard]] static nsresult MakeConnectString(
    190      nsAHttpTransaction* trans, nsHttpRequestHead* request, nsACString& result,
    191      bool h2ws, bool aShouldResistFingerprinting);
    192  [[nodiscard]] static nsresult ReadFromStream(nsIInputStream*, void*,
    193                                               const char*, uint32_t, uint32_t,
    194                                               uint32_t*);
    195 
    196  nsresult CreateTunnelStream(nsAHttpTransaction* httpTransaction,
    197                              HttpConnectionBase** aHttpConnection,
    198                              bool aIsExtendedCONNECT = false) override;
    199 
    200  bool RequestDone() { return mRequestDone; }
    201 
    202 private:
    203  void SetTunnelSetupDone() override;
    204  nsresult SetupProxyConnectStream() override;
    205  nsresult SendConnectRequest(void* closure, uint32_t* transactionBytes);
    206 
    207  void HandleTunnelResponse(uint16_t responseStatus, bool* reset);
    208  void HandleWebSocketResponse(nsHttpRequestHead* requestHead,
    209                               nsHttpResponseHead* responseHead,
    210                               uint16_t responseStatus);
    211  void ResetTransaction(RefPtr<nsAHttpTransaction>&& trans,
    212                        bool aForH2Proxy = false);
    213 
    214  // Value (set in mTCPKeepaliveConfig) indicates which set of prefs to use.
    215  enum TCPKeepaliveConfig {
    216    kTCPKeepaliveDisabled = 0,
    217    kTCPKeepaliveShortLivedConfig,
    218    kTCPKeepaliveLongLivedConfig
    219  };
    220 
    221  [[nodiscard]] nsresult OnTransactionDone(nsresult reason);
    222  [[nodiscard]] nsresult OnSocketWritable();
    223  [[nodiscard]] nsresult OnSocketReadable();
    224 
    225  PRIntervalTime IdleTime();
    226  bool IsAlive();
    227 
    228  // Start the Spdy transaction handler when NPN indicates spdy/*
    229  void StartSpdy(nsITLSSocketControl* ssl, SpdyVersion spdyVersion);
    230  // Like the above, but do the bare minimum to do 0RTT data, so we can back
    231  // it out, if necessary
    232  void Start0RTTSpdy(SpdyVersion spdyVersion);
    233 
    234  // Helpers for Start*Spdy
    235  nsresult TryTakeSubTransactions(nsTArray<RefPtr<nsAHttpTransaction> >& list);
    236  nsresult MoveTransactionsToSpdy(nsresult status,
    237                                  nsTArray<RefPtr<nsAHttpTransaction> >& list);
    238 
    239  // Directly Add a transaction to an active connection for SPDY
    240  [[nodiscard]] nsresult AddTransaction(nsAHttpTransaction*, int32_t);
    241 
    242  // Used to set TCP keepalives for fast detection of dead connections during
    243  // an initial period, and slower detection for long-lived connections.
    244  [[nodiscard]] nsresult StartShortLivedTCPKeepalives();
    245  [[nodiscard]] nsresult StartLongLivedTCPKeepalives();
    246  [[nodiscard]] nsresult DisableTCPKeepalives();
    247 
    248  bool CheckCanWrite0RTTData();
    249  void PostProcessNPNSetup(bool handshakeSucceeded, bool hasSecurityInfo,
    250                           bool earlyDataUsed);
    251  void Reset0RttForSpdy();
    252  void HandshakeDoneInternal();
    253  uint32_t TransactionCaps() const { return mTransactionCaps; }
    254 
    255  void MarkAsDontReuse();
    256 
    257  virtual WebTransportSessionBase* GetWebTransportSession(
    258      nsAHttpTransaction* aTransaction) override;
    259 
    260 private:
    261  // mTransaction only points to the HTTP Transaction callbacks if the
    262  // transaction is open, otherwise it is null.
    263  RefPtr<nsAHttpTransaction> mTransaction;
    264 
    265  RefPtr<TlsHandshaker> mTlsHandshaker;
    266 
    267  nsCOMPtr<nsIAsyncInputStream> mSocketIn;
    268  nsCOMPtr<nsIAsyncOutputStream> mSocketOut;
    269 
    270  nsresult mSocketInCondition{NS_ERROR_NOT_INITIALIZED};
    271  nsresult mSocketOutCondition{NS_ERROR_NOT_INITIALIZED};
    272 
    273  RefPtr<nsHttpHandler> mHttpHandler;  // keep gHttpHandler alive
    274 
    275  PRIntervalTime mLastReadTime{0};
    276  PRIntervalTime mLastWriteTime{0};
    277  // max download time before dropping keep-alive status
    278  PRIntervalTime mMaxHangTime{0};
    279  PRIntervalTime mIdleTimeout;  // value of keep-alive: timeout=
    280  PRIntervalTime mConsiderReusedAfterInterval{0};
    281  PRIntervalTime mConsiderReusedAfterEpoch{0};
    282  TimeStamp mLastTRRResponseTime;   // Time of the last successful TRR response
    283  int64_t mCurrentBytesRead{0};     // data read per activation
    284  int64_t mMaxBytesRead{0};         // max read in 1 activation
    285  int64_t mTotalBytesRead{0};       // total data read
    286  int64_t mContentBytesWritten{0};  // does not include CONNECT tunnel or TLS
    287 
    288  RefPtr<nsIAsyncInputStream> mInputOverflow;
    289 
    290  // Whether the first non-null transaction dispatched on this connection was
    291  // urgent-start or not
    292  bool mUrgentStartPreferred{false};
    293  // A flag to prevent reset of mUrgentStartPreferred by subsequent transactions
    294  bool mUrgentStartPreferredKnown{false};
    295  bool mConnectedTransport{false};
    296  // assume to keep-alive by default
    297  bool mKeepAlive{true};
    298  bool mKeepAliveMask{true};
    299  bool mDontReuse{false};
    300  bool mIsReused{false};
    301  bool mLastTransactionExpectedNoContent{false};
    302  bool mIdleMonitoring{false};
    303  bool mInSpdyTunnel{false};
    304  bool mForcePlainText{false};
    305 
    306  // A snapshot of current number of transfered bytes
    307  int64_t mTrafficCount{0};
    308  bool mTrafficStamp{false};  // true then the above is set
    309 
    310  // The number of <= HTTP/1.1 transactions performed on this connection. This
    311  // excludes spdy transactions.
    312  uint32_t mHttp1xTransactionCount{0};
    313 
    314  // Keep-Alive: max="mRemainingConnectionUses" provides the number of future
    315  // transactions (including the current one) that the server expects to allow
    316  // on this persistent connection.
    317  uint32_t mRemainingConnectionUses{0xffffffff};
    318 
    319  // version level in use, 0 if unused
    320  SpdyVersion mUsingSpdyVersion{SpdyVersion::NONE};
    321 
    322  RefPtr<ASpdySession> mSpdySession;
    323  RefPtr<ASpdySession> mExtendedCONNECTHttp2Session;
    324  int32_t mPriority{nsISupportsPriority::PRIORITY_NORMAL};
    325  bool mReportedSpdy{false};
    326 
    327  // mUsingSpdyVersion is cleared when mSpdySession is freed, this is permanent
    328  bool mEverUsedSpdy{false};
    329 
    330  // mLastHttpResponseVersion stores the last response's http version seen.
    331  HttpVersion mLastHttpResponseVersion{HttpVersion::v1_1};
    332 
    333  // If a large keepalive has been requested for any trans,
    334  // scale the default by this factor
    335  uint32_t mDefaultTimeoutFactor{1};
    336 
    337  bool mResponseTimeoutEnabled{false};
    338 
    339  // Flag to indicate connection is in inital keepalive period (fast detect).
    340  uint32_t mTCPKeepaliveConfig{kTCPKeepaliveDisabled};
    341  nsCOMPtr<nsITimer> mTCPKeepaliveTransitionTimer;
    342 
    343 private:
    344  // For ForceSend()
    345  static void ForceSendIO(nsITimer* aTimer, void* aClosure);
    346  [[nodiscard]] nsresult MaybeForceSendIO();
    347  bool mForceSendPending{false};
    348  nsCOMPtr<nsITimer> mForceSendTimer;
    349 
    350  int64_t mContentBytesWritten0RTT{0};
    351  bool mDid0RTTSpdy{false};
    352 
    353  nsresult mErrorBeforeConnect = NS_OK;
    354 
    355  nsCOMPtr<nsISocketTransport> mSocketTransport;
    356 
    357  // This flag indicates if the connection is used for WebSocket.
    358  // - When true and mInSpdyTunnel is also true: WebSocket over HTTP/2.
    359  // - When true and mInSpdyTunnel is false: WebSocket over HTTP/1.1.
    360  bool mForWebSocket{false};
    361 
    362  std::function<void()> mContinueHandshakeDone{nullptr};
    363 
    364 private:
    365  int64_t mTotalBytesWritten = 0;  // does not include CONNECT tunnel
    366 
    367  nsCOMPtr<nsIInputStream> mProxyConnectStream;
    368 
    369  bool mRequestDone{false};
    370  bool mHasTLSTransportLayer{false};
    371  bool mTransactionDisallowHttp3{false};
    372 };
    373 
    374 }  // namespace net
    375 }  // namespace mozilla
    376 
    377 #endif  // nsHttpConnection_h__