Bug 1805196 - implement initial webtransport connection and close. r=necko-reviewers,jesup

Differential Revision: https://phabricator.services.mozilla.com/D165312
This commit is contained in:
sunil mayya 2023-01-10 10:11:21 +00:00
Родитель 092c5a5d1f
Коммит c01f5b855f
8 изменённых файлов: 189 добавлений и 32 удалений

Просмотреть файл

@ -104,6 +104,7 @@ bool WebTransport::Init(const GlobalObject& aGlobal, const nsAString& aURL,
return false;
}
nsCOMPtr<nsIPrincipal> principal = nsContentUtils::GetSystemPrincipal();
// Create a new IPC connection
Endpoint<PWebTransportParent> parentEndpoint;
Endpoint<PWebTransportChild> childEndpoint;
@ -138,7 +139,8 @@ bool WebTransport::Init(const GlobalObject& aGlobal, const nsAString& aURL,
// https://w3c.github.io/webtransport/#webtransport-constructor Spec 5.2
backgroundChild
->SendCreateWebTransportParent(aURL, dedicated, requireUnreliable,
->SendCreateWebTransportParent(aURL, principal, dedicated,
requireUnreliable,
(uint32_t)congestionControl,
// XXX serverCertHashes,
std::move(parentEndpoint))
@ -172,6 +174,7 @@ void WebTransport::ResolveWaitingConnection(
WebTransportReliabilityMode aReliability, WebTransportChild* aChild) {
LOG(("Resolved Connection %p, reliability = %u", this,
(unsigned)aReliability));
MOZ_ASSERT(mState == WebTransportState::CONNECTING);
mChild = aChild;
mState = WebTransportState::CONNECTED;

Просмотреть файл

@ -5,25 +5,30 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebTransportParent.h"
#include "Http3WebTransportSession.h"
#include "mozilla/StaticPrefs_network.h"
#include "mozilla/dom/WebTransportBinding.h"
#include "mozilla/dom/WebTransportLog.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "nsIEventTarget.h"
#include "nsIOService.h"
#include "nsIPrincipal.h"
#include "nsIWebTransport.h"
namespace mozilla::dom {
NS_IMPL_ISUPPORTS(WebTransportParent, WebTransportSessionEventListener);
using IPCResult = mozilla::ipc::IPCResult;
using CreateWebTransportPromise =
MozPromise<WebTransportReliabilityMode, nsresult, true>;
using ResolveType = Tuple<const nsresult&, const uint8_t&>;
WebTransportParent::~WebTransportParent() {
LOG(("Destroying WebTransportParent %p", this));
}
// static
void WebTransportParent::Create(
const nsAString& aURL, const bool& aDedicated,
const nsAString& aURL, nsIPrincipal* aPrincipal, const bool& aDedicated,
const bool& aRequireUnreliable, const uint32_t& aCongestionControl,
// Sequence<WebTransportHash>* aServerCertHashes,
Endpoint<PWebTransportParent>&& aParentEndpoint,
@ -54,39 +59,68 @@ void WebTransportParent::Create(
return;
}
MOZ_DIAGNOSTIC_ASSERT(mozilla::net::gIOService);
nsresult rv =
mozilla::net::gIOService->NewWebTransport(getter_AddRefs(mWebTransport));
if (NS_FAILED(rv)) {
aResolver(ResolveType(
rv, static_cast<uint8_t>(WebTransportReliabilityMode::Pending)));
return;
}
mOwningEventTarget = GetCurrentEventTarget();
MOZ_ASSERT(aPrincipal);
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), aURL);
if (NS_FAILED(rv)) {
aResolver(ResolveType(
NS_ERROR_INVALID_ARG,
static_cast<uint8_t>(WebTransportReliabilityMode::Pending)));
return;
}
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
"WebTransport AsyncConnect",
[self = RefPtr{this}, uri = std::move(uri),
principal = RefPtr{aPrincipal},
flags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL] {
self->mWebTransport->AsyncConnect(uri, principal, flags, self);
});
// Bind to SocketThread for IPC - connection creation/destruction must
// hit MainThread, but keep all other traffic on SocketThread. Note that
// we must call aResolver() on this (PBackground) thread.
nsresult rv;
nsCOMPtr<nsISerialEventTarget> sts =
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
MOZ_ASSERT(NS_SUCCEEDED(rv));
InvokeAsync(sts, __func__,
[parentEndpoint = std::move(aParentEndpoint)]() mutable {
RefPtr<WebTransportParent> parent = new WebTransportParent();
mResolver = aResolver;
LOG(("Binding parent endpoint"));
if (!parentEndpoint.Bind(parent)) {
return CreateWebTransportPromise::CreateAndReject(
NS_ERROR_FAILURE, __func__);
}
// IPC now holds a ref to parent
// XXX Send connection to the server via MainThread
return CreateWebTransportPromise::CreateAndResolve(
WebTransportReliabilityMode::Supports_unreliable, __func__);
})
InvokeAsync(
sts, __func__,
[parentEndpoint = std::move(aParentEndpoint), runnable = r]() mutable {
RefPtr<WebTransportParent> parent = new WebTransportParent();
LOG(("Binding parent endpoint"));
if (!parentEndpoint.Bind(parent)) {
return CreateWebTransportPromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
}
// IPC now holds a ref to parent
// Send connection to the server via MainThread
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
return CreateWebTransportPromise::CreateAndResolve(
WebTransportReliabilityMode::Supports_unreliable, __func__);
})
->Then(
GetCurrentSerialEventTarget(), __func__,
[aResolver](
[self = RefPtr{this}](
const CreateWebTransportPromise::ResolveOrRejectValue& aValue) {
if (aValue.IsReject()) {
aResolver(ResolveType(
self->mResolver(ResolveType(
aValue.RejectValue(),
static_cast<uint8_t>(WebTransportReliabilityMode::Pending)));
} else {
aResolver(ResolveType(
NS_OK, static_cast<uint8_t>(aValue.ResolveValue())));
}
});
}
@ -101,9 +135,106 @@ mozilla::ipc::IPCResult WebTransportParent::RecvClose(
const uint32_t& aCode, const nsACString& aReason) {
LOG(("Close received, code = %u, reason = %s", aCode,
PromiseFlatCString(aReason).get()));
// XXX shut down streams cleanly
MOZ_ASSERT(!mClosed);
mClosed.Flip();
NS_DispatchToMainThread(NS_NewRunnableFunction(
"WebTransport Close", [self = RefPtr{this}, aCode, &aReason] {
if (self->mWebTransport) {
self->mWebTransport->CloseSession(aCode, aReason);
}
}));
Close();
return IPC_OK();
}
// We recieve this notification from the WebTransportSessionProxy if session was
// successfully created at the end of
// WebTransportSessionProxy::OnStopRequest
NS_IMETHODIMP
WebTransportParent::OnSessionReady(uint64_t aSessionId) {
MOZ_ASSERT(mOwningEventTarget);
MOZ_ASSERT(!mOwningEventTarget->IsOnCurrentThread());
LOG(("Created web transport session, sessionID = %" PRIu64 "", aSessionId));
mOwningEventTarget->Dispatch(NS_NewRunnableFunction(
"WebTransportParent::OnSessionReady", [self = RefPtr{this}] {
if (!self->IsClosed()) {
self->mResolver(ResolveType(
NS_OK, static_cast<uint8_t>(
WebTransportReliabilityMode::Supports_unreliable)));
}
}));
return NS_OK;
}
// We recieve this notification from the WebTransportSessionProxy if session
// creation was unsuccessful at the end of
// WebTransportSessionProxy::OnStopRequest
NS_IMETHODIMP
WebTransportParent::OnSessionClosed(const uint32_t aErrorCode,
const nsACString& aReason) {
LOG(("Creating web transport session failed code= %u, reason= %s", aErrorCode,
PromiseFlatCString(aReason).get()));
nsresult rv = NS_OK;
if (aErrorCode != 0) {
// currently we just know if session was closed gracefully or not.
// we need better error propagation from lower-levels of http3
// webtransport session and it's subsequent error mapping to DOM.
// XXX See Bug 1806834
rv = NS_ERROR_FAILURE;
}
MOZ_ASSERT(mOwningEventTarget);
MOZ_ASSERT(!mOwningEventTarget->IsOnCurrentThread());
mOwningEventTarget->Dispatch(NS_NewRunnableFunction(
"WebTransportParent::OnSessionClosed",
[self = RefPtr{this}, result = rv] {
if (!self->IsClosed()) {
self->mResolver(ResolveType(
result, static_cast<uint8_t>(
WebTransportReliabilityMode::Supports_unreliable)));
}
}));
return NS_OK;
}
// This method is currently not used by WebTransportSessionProxy to inform of
// any session related events. All notification is recieved via
// WebTransportSessionProxy::OnSessionReady and
// WebTransportSessionProxy::OnSessionClosed methods
NS_IMETHODIMP
WebTransportParent::OnSessionReadyInternal(
mozilla::net::Http3WebTransportSession* aSession) {
Unused << aSession;
return NS_OK;
}
NS_IMETHODIMP
WebTransportParent::OnIncomingStreamAvailableInternal(
mozilla::net::Http3WebTransportStream* aStream) {
// XXX implement once DOM WebAPI supports creation of streams
Unused << aStream;
return NS_OK;
}
NS_IMETHODIMP
WebTransportParent::OnIncomingUnidirectionalStreamAvailable(
nsIWebTransportReceiveStream* aStream) {
// XXX implement once DOM WebAPI supports creation of streams
Unused << aStream;
return NS_OK;
}
NS_IMETHODIMP
WebTransportParent::OnIncomingBidirectionalStreamAvailable(
nsIWebTransportBidirectionalStream* aStream) {
// XXX implement once DOM WebAPI supports creation of streams
Unused << aStream;
return NS_OK;
}
} // namespace mozilla::dom

Просмотреть файл

@ -12,19 +12,23 @@
#include "mozilla/dom/PWebTransportParent.h"
#include "mozilla/ipc/Endpoint.h"
#include "nsISupports.h"
#include "nsIPrincipal.h"
#include "nsIWebTransport.h"
namespace mozilla::dom {
enum class WebTransportReliabilityMode : uint8_t;
class WebTransportParent : public PWebTransportParent {
class WebTransportParent : public PWebTransportParent,
public WebTransportSessionEventListener {
public:
WebTransportParent() = default;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebTransportParent, override)
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_WEBTRANSPORTSESSIONEVENTLISTENER
static void Create(
const nsAString& aURL, const bool& aDedicated,
void Create(
const nsAString& aURL, nsIPrincipal* aPrincipal, const bool& aDedicated,
const bool& aRequireUnreliable, const uint32_t& aCongestionControl,
// Sequence<WebTransportHash>* aServerCertHashes,
Endpoint<PWebTransportParent>&& aParentEndpoint,
@ -35,8 +39,17 @@ class WebTransportParent : public PWebTransportParent {
void ActorDestroy(ActorDestroyReason aWhy) override;
bool IsClosed() const { return mClosed; }
protected:
virtual ~WebTransportParent();
private:
using ResolveType = Tuple<const nsresult&, const uint8_t&>;
std::function<void(ResolveType)> mResolver;
FlippedOnce<false> mClosed;
nsCOMPtr<nsIWebTransport> mWebTransport;
nsCOMPtr<nsIEventTarget> mOwningEventTarget;
};
} // namespace mozilla::dom

Просмотреть файл

@ -15,3 +15,8 @@ UNIFIED_SOURCES += [
FINAL_LIBRARY = "xul"
include("/ipc/chromium/chromium-config.mozbuild")
LOCAL_INCLUDES += [
"/netwerk/base",
"/netwerk/protocol/http",
]

Просмотреть файл

@ -504,7 +504,7 @@ mozilla::ipc::IPCResult BackgroundParentImpl::RecvCreateFileSystemManagerParent(
}
mozilla::ipc::IPCResult BackgroundParentImpl::RecvCreateWebTransportParent(
const nsAString& aURL, const bool& aDedicated,
const nsAString& aURL, nsIPrincipal* aPrincipal, const bool& aDedicated,
const bool& aRequireUnreliable, const uint32_t& aCongestionControl,
// Sequence<WebTransportHash>* aServerCertHashes,
Endpoint<PWebTransportParent>&& aParentEndpoint,
@ -512,8 +512,10 @@ mozilla::ipc::IPCResult BackgroundParentImpl::RecvCreateWebTransportParent(
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
mozilla::dom::WebTransportParent::Create(
aURL, aDedicated, aRequireUnreliable, aCongestionControl,
RefPtr<mozilla::dom::WebTransportParent> webt =
new mozilla::dom::WebTransportParent();
webt->Create(
aURL, aPrincipal, aDedicated, aRequireUnreliable, aCongestionControl,
/*aServerCertHashes, */ std::move(aParentEndpoint), std::move(aResolver));
return IPC_OK();
}

Просмотреть файл

@ -138,7 +138,7 @@ class BackgroundParentImpl : public PBackgroundParent {
CreateFileSystemManagerParentResolver&& aResolver) override;
mozilla::ipc::IPCResult RecvCreateWebTransportParent(
const nsAString& aURL, const bool& aDedicated,
const nsAString& aURL, nsIPrincipal* aPrincipal, const bool& aDedicated,
const bool& aRequireUnreliable, const uint32_t& aCongestionControl,
// Sequence<WebTransportHash>* aServerCertHashes,
Endpoint<PWebTransportParent>&& aParentEndpoint,

Просмотреть файл

@ -201,6 +201,7 @@ parent:
*/
async CreateWebTransportParent(
nsString aURL,
nsIPrincipal aPrincipal,
bool aDedicated,
bool aRequireUnreliable,
uint32_t aCongestionControl,

Просмотреть файл

@ -93,6 +93,8 @@ nsresult WebTransportSessionProxy::AsyncConnect(
rv = mChannel->AsyncOpen(this);
if (NS_FAILED(rv)) {
MutexAutoLock lock(mMutex);
mChannel = nullptr;
mListener = nullptr;
ChangeState(WebTransportSessionProxyState::DONE);
}
return rv;