tor-browser

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

WebTransportSessionProxy.h (9141B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
      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 mozilla_net_WebTransportProxy_h
      7 #define mozilla_net_WebTransportProxy_h
      8 
      9 #include <functional>
     10 #include "nsIChannelEventSink.h"
     11 #include "nsIInterfaceRequestor.h"
     12 #include "nsIRedirectResultListener.h"
     13 #include "nsIStreamListener.h"
     14 #include "nsIWebTransport.h"
     15 
     16 /*
     17 * WebTransportSessionProxy is introduced to enable the creation of a
     18 * Http3WebTransportSession and coordination of actions that are performed on
     19 * the main thread and on the socket thread.
     20 *
     21 * mChannel, mRedirectChannel, and mListener are used only on the main thread.
     22 *
     23 * mWebTransportSession is used only on the socket thread.
     24 *
     25 * mState and mSessionId are used on both threads, socket and main thread and it
     26 * is only used with a lock.
     27 *
     28 *
     29 * WebTransportSessionProxyState:
     30 * - INIT: before AsyncConnect is called.
     31 *
     32 * - NEGOTIATING: It is set during AsyncConnect. During this state HttpChannel
     33 *   is open but OnStartRequest has not been called yet. This state can
     34 *   transfer into:
     35 *    - NEGOTIATING_SUCCEEDED: when a Http3WebTransportSession has been
     36 *      negotiated.
     37 *    - DONE: when a WebTransport session has been canceled.
     38 *
     39 * - NEGOTIATING_SUCCEEDED: It is set during parsing of
     40 *   Http3WebTransportSession response when the response has been successful.
     41 *   mWebTransport is set to the Http3WebTransportSession at the same time the
     42 *   session changes to this state. This state can transfer into:
     43 *    - ACTIVE: during the OnStopRequest call if the WebTransport has not been
     44 *      canceled or failed for other reason, e.g. a browser shutdown or content
     45 *      blocking policies.
     46 *    - SESSION_CLOSE_PENDING: if the WebTransport has been canceled via an API
     47 *      call or content blocking policies. (the main thread initiated close).
     48 *    - CLOSE_CALLBACK_PENDING: if Http3WebTransportSession has been canceled
     49 *     due to a shutdown or a server closing a session. (the socket thread
     50 *     initiated close).
     51 *
     52 * - ACTIVE: In this state the session is negotiated and ready to use. This
     53 *   state can transfer into:
     54 *    - SESSION_CLOSE_PENDING: if the WebTransport has been canceled via an API
     55 *      call(nsIWebTransport::closeSession) or content blocking policies. (the
     56 *      main thread initiated close).
     57 *    - CLOSE_CALLBACK_PENDING: if Http3WebTransportSession has been canceled
     58 *      due to a shutdown or a server closing a session. (the socket thread
     59 *      initiated close).
     60 *
     61 * - CLOSE_CALLBACK_PENDING: This is the socket thread initiated close. In this
     62 *   state, the Http3WebTransportSession has been closed and a
     63 * CallOnSessionClosed call is dispatched to the main thread to call the
     64 * appropriate listener.
     65 *
     66 * - SESSION_CLOSE_PENDING: This is the main thread initiated close. In this
     67 * state, the WebTransport has been closed via an API call
     68 *   (nsIWebTransport::closeSession) and a CloseSessionInternal call is
     69 * dispatched to the socket thread to close the appropriate
     70 * Http3WebTransportSession.
     71 *
     72 * - DONE: everything has been cleaned up on both threads.
     73 *
     74 *
     75 * AsyncConnect creates mChannel on the main thread. Redirect callbacks are also
     76 * performed on the main thread (mRedirectChannel set and access only on the
     77 * main thread). Before this point, there are no activities on the socket thread
     78 * and Http3WebTransportSession is nullptr. mChannel is going to create a
     79 * nsHttpTransaction. The transaction will be dispatched on a nsAHttpConnection,
     80 * i.e. currently only the HTTP/3 version is implemented, therefore this will be
     81 * a HttpConnectionUDP and a Http3Session. The Http3Session creates a
     82 * Http3WebTransportSession. Until a response is received
     83 * Http3WebTransportSession is only accessed by Http3Session. During parsing of
     84 * a successful received from a server on the socket thread,
     85 * WebTransportSessionProxy::mWebTransportSession will take a reference to
     86 * Http3WebTransportSession and mState will be set to NEGOTIATING_SUCCEEDED.
     87 * From now on WebTransportSessionProxy is responsible for closing
     88 * Http3WebTransportSession if the closing of the session is initiated on the
     89 * main thread. OnStartRequest and OnStopRequest will be called on the main
     90 * thread. The session negotiation can have 2 outcomes:
     91 * - If both calls, i.e. OnStartRequest an OnStopRequest, indicate that the
     92 * request has succeeded and mState is NEGOTIATING_SUCCEEDED, the
     93 * mListener->OnSessionReady will be called during OnStopRequest.
     94 * - Otherwise, mListener->OnSessionClosed will be called, the state transferred
     95 * into SESSION_CLOSE_PENDING, and CloseSessionInternal will be dispatched to
     96 * the socket thread.
     97 *
     98 * CloseSession is called on the main thread. If the session is already closed
     99 * it returns an error. If the session is in state NEGOTIATING or
    100 * NEGOTIATING_SUCCEEDED mChannel will be canceled. If the session is in state
    101 * NEGOTIATING_SUCCEEDED or ACTIVE the state transferred into
    102 * SESSION_CLOSE_PENDING, and CloseSessionInternal will be dispatched to the
    103 * socket thread
    104 *
    105 * OnSessionReadyInternal is called on the socket thread. If mState is
    106 * NEGOTIATING the state will be set to NEGOTIATING_SUCCEEDED and mWebTransport
    107 * will be set to the newly negotiated Http3WebTransportSession. If mState is
    108 * DONE, the Http3WebTransportSession will be close.
    109 *
    110 * OnSessionClosed is called on the socket thread. mState will be set to
    111 * CLOSE_CALLBACK_PENDING and CallOnSessionClosed will be dispatched to the main
    112 * thread.
    113 *
    114 * mWebTransport is set during states NEGOTIATING_SUCCEEDED, ACTIVE and
    115 * SESSION_CLOSE_PENDING.
    116 */
    117 
    118 namespace mozilla::net {
    119 
    120 class WebTransportEventService;
    121 
    122 class WebTransportStreamCallbackWrapper;
    123 
    124 class WebTransportSessionProxy final
    125    : public nsIWebTransport,
    126      public WebTransportSessionEventListener,
    127      public WebTransportSessionEventListenerInternal,
    128      public WebTransportConnectionSettings,
    129      public nsIStreamListener,
    130      public nsIChannelEventSink,
    131      public nsIRedirectResultListener,
    132      public nsIInterfaceRequestor {
    133 public:
    134  NS_DECL_THREADSAFE_ISUPPORTS
    135  NS_DECL_NSIWEBTRANSPORT
    136  NS_DECL_WEBTRANSPORTSESSIONEVENTLISTENER
    137  NS_DECL_WEBTRANSPORTSESSIONEVENTLISTENERINTERNAL
    138  NS_DECL_WEBTRANSPORTCONNECTIONSETTINGS
    139  NS_DECL_NSIREQUESTOBSERVER
    140  NS_DECL_NSISTREAMLISTENER
    141  NS_DECL_NSICHANNELEVENTSINK
    142  NS_DECL_NSIREDIRECTRESULTLISTENER
    143  NS_DECL_NSIINTERFACEREQUESTOR
    144 
    145  WebTransportSessionProxy();
    146 
    147 private:
    148  ~WebTransportSessionProxy();
    149 
    150  void CloseSessionInternal();
    151  void CloseSessionInternalLocked();
    152  void CallOnSessionClosed();
    153  void CallOnSessionClosedLocked();
    154 
    155  enum WebTransportSessionProxyState {
    156    INIT,
    157    NEGOTIATING,
    158    NEGOTIATING_SUCCEEDED,
    159    ACTIVE,
    160    CLOSE_CALLBACK_PENDING,
    161    SESSION_CLOSE_PENDING,
    162    DONE,
    163  };
    164  mozilla::Mutex mMutex;
    165  WebTransportSessionProxyState mState MOZ_GUARDED_BY(mMutex) =
    166      WebTransportSessionProxyState::INIT;
    167  void ChangeState(WebTransportSessionProxyState newState);
    168  void CreateStreamInternal(nsIWebTransportStreamCallback* callback,
    169                            bool aBidi);
    170  void DoCreateStream(WebTransportStreamCallbackWrapper* aCallback,
    171                      WebTransportSessionBase* aSession, bool aBidi);
    172  void SendDatagramInternal(const RefPtr<WebTransportSessionBase>& aSession,
    173                            nsTArray<uint8_t>&& aData, uint64_t aTrackingId);
    174  void NotifyDatagramReceived(nsTArray<uint8_t>&& aData);
    175  void GetMaxDatagramSizeInternal(
    176      const RefPtr<WebTransportSessionBase>& aSession);
    177  void OnMaxDatagramSizeInternal(uint64_t aSize);
    178  void OnOutgoingDatagramOutComeInternal(
    179      uint64_t aId, WebTransportSessionEventListener::DatagramOutcome aOutCome);
    180 
    181  nsCOMPtr<nsIChannel> mChannel;
    182  uint64_t mHttpChannelID = 0;
    183  nsCOMPtr<nsIChannel> mRedirectChannel;
    184  RefPtr<WebTransportEventService> mService;
    185  nsCOMPtr<WebTransportSessionEventListener> mListener MOZ_GUARDED_BY(mMutex);
    186  RefPtr<WebTransportSessionBase> mWebTransportSession MOZ_GUARDED_BY(mMutex);
    187  uint64_t mSessionId MOZ_GUARDED_BY(mMutex) = UINT64_MAX;
    188  uint32_t mCloseStatus MOZ_GUARDED_BY(mMutex) = 0;
    189  nsCString mReason MOZ_GUARDED_BY(mMutex);
    190  bool mCleanly MOZ_GUARDED_BY(mMutex) = false;
    191  bool mStopRequestCalled MOZ_GUARDED_BY(mMutex) = false;
    192  // This is used to store events happened before OnSessionReady.
    193  // Note that these events will be dispatched to the socket thread.
    194  nsTArray<std::function<void()>> mPendingEvents MOZ_GUARDED_BY(mMutex);
    195  nsTArray<std::function<void(nsresult)>> mPendingCreateStreamEvents
    196      MOZ_GUARDED_BY(mMutex);
    197  nsCOMPtr<nsIEventTarget> mTarget MOZ_GUARDED_BY(mMutex);
    198  nsTArray<RefPtr<nsIWebTransportHash>> mServerCertHashes;
    199  bool mDedicatedConnection;  // for WebTranport
    200  nsIWebTransport::HTTPVersion mHTTPVersion = nsIWebTransport::HTTPVersion::h3;
    201 };
    202 
    203 }  // namespace mozilla::net
    204 
    205 #endif  // mozilla_net_WebTransportProxy_h