summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/webtransport/WebTransportSessionProxy.h
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/webtransport/WebTransportSessionProxy.h')
-rw-r--r--netwerk/protocol/webtransport/WebTransportSessionProxy.h192
1 files changed, 192 insertions, 0 deletions
diff --git a/netwerk/protocol/webtransport/WebTransportSessionProxy.h b/netwerk/protocol/webtransport/WebTransportSessionProxy.h
new file mode 100644
index 0000000000..1e8eacc60b
--- /dev/null
+++ b/netwerk/protocol/webtransport/WebTransportSessionProxy.h
@@ -0,0 +1,192 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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 mozilla_net_WebTransportProxy_h
+#define mozilla_net_WebTransportProxy_h
+
+#include <functional>
+#include "nsIChannelEventSink.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIRedirectResultListener.h"
+#include "nsIStreamListener.h"
+#include "nsIWebTransport.h"
+
+/*
+ * WebTransportSessionProxy is introduced to enable the creation of a
+ * Http3WebTransportSession and coordination of actions that are performed on
+ * the main thread and on the socket thread.
+ *
+ * mChannel, mRedirectChannel, and mListener are used only on the main thread.
+ *
+ * mWebTransportSession is used only on the socket thread.
+ *
+ * mState and mSessionId are used on both threads, socket and main thread and it
+ * is only used with a lock.
+ *
+ *
+ * WebTransportSessionProxyState:
+ * - INIT: before AsyncConnect is called.
+ *
+ * - NEGOTIATING: It is set during AsyncConnect. During this state HttpChannel
+ * is open but OnStartRequest has not been called yet. This state can
+ * transfer into:
+ * - NEGOTIATING_SUCCEEDED: when a Http3WebTransportSession has been
+ * negotiated.
+ * - DONE: when a WebTransport session has been canceled.
+ *
+ * - NEGOTIATING_SUCCEEDED: It is set during parsing of
+ * Http3WebTransportSession response when the response has been successful.
+ * mWebTransport is set to the Http3WebTransportSession at the same time the
+ * session changes to this state. This state can transfer into:
+ * - ACTIVE: during the OnStopRequest call if the WebTransport has not been
+ * canceled or failed for other reason, e.g. a browser shutdown or content
+ * blocking policies.
+ * - SESSION_CLOSE_PENDING: if the WebTransport has been canceled via an API
+ * call or content blocking policies. (the main thread initiated close).
+ * - CLOSE_CALLBACK_PENDING: if Http3WebTransportSession has been canceled
+ * due to a shutdown or a server closing a session. (the socket thread
+ * initiated close).
+ *
+ * - ACTIVE: In this state the session is negotiated and ready to use. This
+ * state can transfer into:
+ * - SESSION_CLOSE_PENDING: if the WebTransport has been canceled via an API
+ * call(nsIWebTransport::closeSession) or content blocking policies. (the
+ * main thread initiated close).
+ * - CLOSE_CALLBACK_PENDING: if Http3WebTransportSession has been canceled
+ * due to a shutdown or a server closing a session. (the socket thread
+ * initiated close).
+ *
+ * - CLOSE_CALLBACK_PENDING: This is the socket thread initiated close. In this
+ * state, the Http3WebTransportSession has been closed and a
+ * CallOnSessionClosed call is dispatched to the main thread to call the
+ * appropriate listener.
+ *
+ * - SESSION_CLOSE_PENDING: This is the main thread initiated close. In this
+ * state, the WebTransport has been closed via an API call
+ * (nsIWebTransport::closeSession) and a CloseSessionInternal call is
+ * dispatched to the socket thread to close the appropriate
+ * Http3WebTransportSession.
+ *
+ * - DONE: everything has been cleaned up on both threads.
+ *
+ *
+ * AsyncConnect creates mChannel on the main thread. Redirect callbacks are also
+ * performed on the main thread (mRedirectChannel set and access only on the
+ * main thread). Before this point, there are no activities on the socket thread
+ * and Http3WebTransportSession is nullptr. mChannel is going to create a
+ * nsHttpTransaction. The transaction will be dispatched on a nsAHttpConnection,
+ * i.e. currently only the HTTP/3 version is implemented, therefore this will be
+ * a HttpConnectionUDP and a Http3Session. The Http3Session creates a
+ * Http3WebTransportSession. Until a response is received
+ * Http3WebTransportSession is only accessed by Http3Session. During parsing of
+ * a successful received from a server on the socket thread,
+ * WebTransportSessionProxy::mWebTransportSession will take a reference to
+ * Http3WebTransportSession and mState will be set to NEGOTIATING_SUCCEEDED.
+ * From now on WebTransportSessionProxy is responsible for closing
+ * Http3WebTransportSession if the closing of the session is initiated on the
+ * main thread. OnStartRequest and OnStopRequest will be called on the main
+ * thread. The session negotiation can have 2 outcomes:
+ * - If both calls, i.e. OnStartRequest an OnStopRequest, indicate that the
+ * request has succeeded and mState is NEGOTIATING_SUCCEEDED, the
+ * mListener->OnSessionReady will be called during OnStopRequest.
+ * - Otherwise, mListener->OnSessionClosed will be called, the state transferred
+ * into SESSION_CLOSE_PENDING, and CloseSessionInternal will be dispatched to
+ * the socket thread.
+ *
+ * CloseSession is called on the main thread. If the session is already closed
+ * it returns an error. If the session is in state NEGOTIATING or
+ * NEGOTIATING_SUCCEEDED mChannel will be canceled. If the session is in state
+ * NEGOTIATING_SUCCEEDED or ACTIVE the state transferred into
+ * SESSION_CLOSE_PENDING, and CloseSessionInternal will be dispatched to the
+ * socket thread
+ *
+ * OnSessionReadyInternal is called on the socket thread. If mState is
+ * NEGOTIATING the state will be set to NEGOTIATING_SUCCEEDED and mWebTransport
+ * will be set to the newly negotiated Http3WebTransportSession. If mState is
+ * DONE, the Http3WebTransportSession will be close.
+ *
+ * OnSessionClosed is called on the socket thread. mState will be set to
+ * CLOSE_CALLBACK_PENDING and CallOnSessionClosed will be dispatched to the main
+ * thread.
+ *
+ * mWebTransport is set during states NEGOTIATING_SUCCEEDED, ACTIVE and
+ * SESSION_CLOSE_PENDING.
+ */
+
+namespace mozilla::net {
+
+class WebTransportStreamCallbackWrapper;
+
+class WebTransportSessionProxy final : public nsIWebTransport,
+ public WebTransportSessionEventListener,
+ public nsIStreamListener,
+ public nsIChannelEventSink,
+ public nsIRedirectResultListener,
+ public nsIInterfaceRequestor {
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIWEBTRANSPORT
+ NS_DECL_WEBTRANSPORTSESSIONEVENTLISTENER
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSICHANNELEVENTSINK
+ NS_DECL_NSIREDIRECTRESULTLISTENER
+ NS_DECL_NSIINTERFACEREQUESTOR
+
+ WebTransportSessionProxy();
+
+ private:
+ ~WebTransportSessionProxy();
+
+ void CloseSessionInternal();
+ void CloseSessionInternalLocked();
+ void CallOnSessionClosed();
+ void CallOnSessionClosedLocked();
+
+ enum WebTransportSessionProxyState {
+ INIT,
+ NEGOTIATING,
+ NEGOTIATING_SUCCEEDED,
+ ACTIVE,
+ CLOSE_CALLBACK_PENDING,
+ SESSION_CLOSE_PENDING,
+ DONE,
+ };
+ mozilla::Mutex mMutex;
+ WebTransportSessionProxyState mState MOZ_GUARDED_BY(mMutex) =
+ WebTransportSessionProxyState::INIT;
+ void ChangeState(WebTransportSessionProxyState newState);
+ void CreateStreamInternal(nsIWebTransportStreamCallback* callback,
+ bool aBidi);
+ void DoCreateStream(WebTransportStreamCallbackWrapper* aCallback,
+ Http3WebTransportSession* aSession, bool aBidi);
+ void SendDatagramInternal(const RefPtr<Http3WebTransportSession>& aSession,
+ nsTArray<uint8_t>&& aData, uint64_t aTrackingId);
+ void NotifyDatagramReceived(nsTArray<uint8_t>&& aData);
+ void GetMaxDatagramSizeInternal(
+ const RefPtr<Http3WebTransportSession>& aSession);
+ void OnMaxDatagramSizeInternal(uint64_t aSize);
+ void OnOutgoingDatagramOutComeInternal(
+ uint64_t aId, WebTransportSessionEventListener::DatagramOutcome aOutCome);
+
+ nsCOMPtr<nsIChannel> mChannel;
+ nsCOMPtr<nsIChannel> mRedirectChannel;
+ nsCOMPtr<WebTransportSessionEventListener> mListener MOZ_GUARDED_BY(mMutex);
+ RefPtr<Http3WebTransportSession> mWebTransportSession MOZ_GUARDED_BY(mMutex);
+ uint64_t mSessionId MOZ_GUARDED_BY(mMutex) = UINT64_MAX;
+ uint32_t mCloseStatus MOZ_GUARDED_BY(mMutex) = 0;
+ nsCString mReason MOZ_GUARDED_BY(mMutex);
+ bool mStopRequestCalled MOZ_GUARDED_BY(mMutex) = false;
+ // This is used to store events happened before OnSessionReady.
+ // Note that these events will be dispatched to the socket thread.
+ nsTArray<std::function<void()>> mPendingEvents MOZ_GUARDED_BY(mMutex);
+ nsTArray<std::function<void(nsresult)>> mPendingCreateStreamEvents
+ MOZ_GUARDED_BY(mMutex);
+ nsCOMPtr<nsIEventTarget> mTarget MOZ_GUARDED_BY(mMutex);
+};
+
+} // namespace mozilla::net
+
+#endif // mozilla_net_WebTransportProxy_h