mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1497249 - P2: ipdl for nsIWebSocketConnection r=michal
Differential Revision: https://phabricator.services.mozilla.com/D30624
This commit is contained in:
parent
1e225df236
commit
682f8a9a04
@ -555,6 +555,12 @@ WebrtcTCPSocket::OnTransportAvailable(nsISocketTransport* aTransport,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebrtcTCPSocket::OnWebSocketConnectionAvailable(
|
||||
nsIWebSocketConnection* aConnection) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void WebrtcTCPSocket::FinishOpen() {
|
||||
MOZ_ASSERT(OnSocketThread());
|
||||
// mTransport, mSocketIn, and mSocketOut are all set. We may have set them in
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "HttpTransactionChild.h"
|
||||
#include "AltSvcTransactionChild.h"
|
||||
#include "EventTokenBucket.h"
|
||||
#include "mozilla/net/WebSocketConnectionChild.h"
|
||||
#include "nsHttpConnectionInfo.h"
|
||||
#include "nsHttpConnectionMgr.h"
|
||||
#include "nsHttpHandler.h"
|
||||
@ -177,5 +178,25 @@ mozilla::ipc::IPCResult HttpConnectionMgrChild::RecvSpeculativeConnect(
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
already_AddRefed<PWebSocketConnectionChild>
|
||||
HttpConnectionMgrChild::AllocPWebSocketConnectionChild(
|
||||
PHttpTransactionChild* aTransWithStickyConn) {
|
||||
RefPtr<WebSocketConnectionChild> actor = new WebSocketConnectionChild();
|
||||
return actor.forget();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HttpConnectionMgrChild::RecvPWebSocketConnectionConstructor(
|
||||
PWebSocketConnectionChild* aActor,
|
||||
PHttpTransactionChild* aTransWithStickyConn) {
|
||||
RefPtr<WebSocketConnectionChild> child =
|
||||
static_cast<WebSocketConnectionChild*>(aActor);
|
||||
nsCOMPtr<nsIHttpUpgradeListener> listener =
|
||||
static_cast<nsIHttpUpgradeListener*>(child.get());
|
||||
Unused << mConnMgr->CompleteUpgrade(
|
||||
ToRealHttpTransaction(aTransWithStickyConn), listener);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -41,6 +41,12 @@ class HttpConnectionMgrChild final : public PHttpConnectionMgrChild {
|
||||
Maybe<SpeculativeConnectionOverriderArgs> aOverriderArgs, uint32_t aCaps,
|
||||
Maybe<PAltSvcTransactionChild*> aTrans);
|
||||
|
||||
already_AddRefed<PWebSocketConnectionChild> AllocPWebSocketConnectionChild(
|
||||
PHttpTransactionChild* aTransWithStickyConn);
|
||||
mozilla::ipc::IPCResult RecvPWebSocketConnectionConstructor(
|
||||
PWebSocketConnectionChild* aActor,
|
||||
PHttpTransactionChild* aTransWithStickyConn) override;
|
||||
|
||||
private:
|
||||
virtual ~HttpConnectionMgrChild();
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "HttpConnectionMgrParent.h"
|
||||
#include "AltSvcTransactionParent.h"
|
||||
#include "mozilla/net/HttpTransactionParent.h"
|
||||
#include "mozilla/net/WebSocketConnectionParent.h"
|
||||
#include "nsHttpConnectionInfo.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsISpeculativeConnect.h"
|
||||
@ -252,8 +253,13 @@ nsresult HttpConnectionMgrParent::ClearConnectionHistory() {
|
||||
|
||||
nsresult HttpConnectionMgrParent::CompleteUpgrade(
|
||||
HttpTransactionShell* aTrans, nsIHttpUpgradeListener* aUpgradeListener) {
|
||||
// TODO: fix this in bug 1497249
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
MOZ_ASSERT(aTrans->AsHttpTransactionParent());
|
||||
|
||||
RefPtr<WebSocketConnectionParent> wsConnParent =
|
||||
new WebSocketConnectionParent(aUpgradeListener);
|
||||
Unused << SendPWebSocketConnectionConstructor(
|
||||
wsConnParent, aTrans->AsHttpTransactionParent());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsHttpConnectionMgr* HttpConnectionMgrParent::AsHttpConnectionMgr() {
|
||||
|
@ -8,6 +8,7 @@
|
||||
include protocol PAltSvcTransaction;
|
||||
include protocol PSocketProcess;
|
||||
include protocol PHttpTransaction;
|
||||
include protocol PWebSocketConnection;
|
||||
|
||||
include NeckoChannelParams;
|
||||
|
||||
@ -17,6 +18,7 @@ namespace net {
|
||||
async refcounted protocol PHttpConnectionMgr
|
||||
{
|
||||
manager PSocketProcess;
|
||||
manages PWebSocketConnection;
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
@ -33,6 +35,7 @@ child:
|
||||
async SpeculativeConnect(HttpConnectionInfoCloneArgs aConnInfo,
|
||||
SpeculativeConnectionOverriderArgs? aOverriderArgs,
|
||||
uint32_t aCaps, PAltSvcTransaction? aTrans);
|
||||
async PWebSocketConnection(PHttpTransaction aTransWithStickyConn);
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
@ -7942,6 +7942,13 @@ nsresult nsHttpChannel::ContinueOnStopRequestAfterAuthRetry(
|
||||
mResponseHead->Status() == 200;
|
||||
|
||||
if (upgradeWebsocket || upgradeConnect) {
|
||||
// TODO: Support connection upgrade for socket process in bug 1632809.
|
||||
if (nsIOService::UseSocketProcess() && upgradeConnect) {
|
||||
Unused << mUpgradeProtocolCallback->OnUpgradeFailed(
|
||||
NS_ERROR_NOT_IMPLEMENTED);
|
||||
return ContinueOnStopRequest(aStatus, aIsFromNet, aContentComplete);
|
||||
}
|
||||
|
||||
nsresult rv = gHttpHandler->CompleteUpgrade(aTransWithStickyConn,
|
||||
mUpgradeProtocolCallback);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -27,6 +27,7 @@ interface nsIProxyInfo;
|
||||
interface nsISecurityConsoleMessage;
|
||||
interface nsISocketTransport;
|
||||
interface nsIURI;
|
||||
interface nsIWebSocketConnection;
|
||||
|
||||
/**
|
||||
* The callback interface for nsIHttpChannelInternal::HTTPUpgrade()
|
||||
@ -40,6 +41,8 @@ interface nsIHttpUpgradeListener : nsISupports
|
||||
in nsIAsyncOutputStream aSocketOut);
|
||||
|
||||
[must_use] void onUpgradeFailed(in nsresult aErrorCode);
|
||||
|
||||
[must_use] void onWebSocketConnectionAvailable(in nsIWebSocketConnection aConnection);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -48,6 +48,12 @@ TransportProviderParent::OnTransportAvailable(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TransportProviderParent::OnWebSocketConnectionAvailable(
|
||||
nsIWebSocketConnection* aConnection) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TransportProviderParent::OnUpgradeFailed(nsresult aErrorCode) { return NS_OK; }
|
||||
|
||||
|
33
netwerk/protocol/websocket/PWebSocketConnection.ipdl
Normal file
33
netwerk/protocol/websocket/PWebSocketConnection.ipdl
Normal file
@ -0,0 +1,33 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
|
||||
/* 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/. */
|
||||
|
||||
include protocol PHttpConnectionMgr;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
async refcounted protocol PWebSocketConnection
|
||||
{
|
||||
manager PHttpConnectionMgr;
|
||||
|
||||
parent:
|
||||
async OnTransportAvailable(nsCString securityInfoSerialization);
|
||||
async OnError(nsresult aStatus);
|
||||
async OnTCPClosed();
|
||||
async OnDataReceived(uint8_t[] aData);
|
||||
async OnUpgradeFailed(nsresult aReason);
|
||||
|
||||
child:
|
||||
async EnqueueOutgoingData(uint8_t[] aHeader, uint8_t[] aPayload);
|
||||
async StartReading();
|
||||
async DrainSocketData();
|
||||
|
||||
async __delete__();
|
||||
|
||||
};
|
||||
|
||||
} //namespace net
|
||||
} //namespace mozilla
|
@ -3527,7 +3527,31 @@ WebSocketChannel::OnTransportAvailable(nsISocketTransport* aTransport,
|
||||
MOZ_ASSERT(!mRecvdHttpUpgradeTransport, "OTA duplicated");
|
||||
MOZ_ASSERT(aSocketIn, "OTA with invalid socketIn");
|
||||
|
||||
mConnection = new nsWebSocketConnection(aTransport, aSocketIn, aSocketOut);
|
||||
return OnWebSocketConnectionAvailable(
|
||||
new nsWebSocketConnection(aTransport, aSocketIn, aSocketOut));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannel::OnWebSocketConnectionAvailable(
|
||||
nsIWebSocketConnection* aConnection) {
|
||||
LOG(
|
||||
("WebSocketChannel::OnWebSocketConnectionAvailable %p [%p] "
|
||||
"rcvdonstart=%d\n",
|
||||
this, aConnection, mGotUpgradeOK));
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread(), "not main thread");
|
||||
MOZ_ASSERT(!mRecvdHttpUpgradeTransport,
|
||||
"OnWebSocketConnectionAvailable duplicated");
|
||||
MOZ_ASSERT(aConnection,
|
||||
"OnWebSocketConnectionAvailable with invalid connection");
|
||||
|
||||
if (mStopped) {
|
||||
LOG(("WebSocketChannel::OnWebSocketConnectionAvailable: Already stopped"));
|
||||
aConnection->Close();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mConnection = aConnection;
|
||||
nsresult rv = mConnection->Init(this, mSocketThread);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
186
netwerk/protocol/websocket/WebSocketConnectionChild.cpp
Normal file
186
netwerk/protocol/websocket/WebSocketConnectionChild.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* 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/. */
|
||||
|
||||
#include "WebSocketLog.h"
|
||||
#include "WebSocketConnectionChild.h"
|
||||
|
||||
#include "nsISerializable.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsWebSocketConnection.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS(WebSocketConnectionChild, nsIWebSocketConnectionListener,
|
||||
nsIHttpUpgradeListener)
|
||||
|
||||
WebSocketConnectionChild::WebSocketConnectionChild() {
|
||||
LOG(("WebSocketConnectionChild ctor %p\n", this));
|
||||
}
|
||||
|
||||
WebSocketConnectionChild::~WebSocketConnectionChild() {
|
||||
LOG(("WebSocketConnectionChild dtor %p\n", this));
|
||||
}
|
||||
|
||||
// nsIHttpUpgradeListener
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionChild::OnTransportAvailable(
|
||||
nsISocketTransport* aTransport, nsIAsyncInputStream* aSocketIn,
|
||||
nsIAsyncOutputStream* aSocketOut) {
|
||||
if (!NS_IsMainThread()) {
|
||||
nsCOMPtr<nsISocketTransport> transport = aTransport;
|
||||
nsCOMPtr<nsIAsyncInputStream> inputStream = aSocketIn;
|
||||
nsCOMPtr<nsIAsyncOutputStream> outputStream = aSocketOut;
|
||||
RefPtr<WebSocketConnectionChild> self = this;
|
||||
return NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction("WebSocketConnectionChild::OnTransportAvailable",
|
||||
[self, transport, inputStream, outputStream]() {
|
||||
Unused << self->OnTransportAvailable(
|
||||
transport, inputStream, outputStream);
|
||||
}),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
LOG(("WebSocketConnectionChild::OnTransportAvailable %p\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mConnection, "already called");
|
||||
MOZ_ASSERT(aTransport);
|
||||
|
||||
nsAutoCString serializedSecurityInfo;
|
||||
nsCOMPtr<nsISupports> secInfoSupp;
|
||||
aTransport->GetSecurityInfo(getter_AddRefs(secInfoSupp));
|
||||
if (secInfoSupp) {
|
||||
nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(secInfoSupp);
|
||||
if (secInfoSer) {
|
||||
NS_SerializeToString(secInfoSer, serializedSecurityInfo);
|
||||
}
|
||||
}
|
||||
|
||||
mConnection = new nsWebSocketConnection(aTransport, aSocketIn, aSocketOut);
|
||||
nsresult rv = mConnection->Init(this, GetCurrentEventTarget());
|
||||
if (NS_FAILED(rv)) {
|
||||
Unused << SendOnError(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Unused << SendOnTransportAvailable(serializedSecurityInfo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionChild::OnWebSocketConnectionAvailable(
|
||||
nsIWebSocketConnection* aConnection) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionChild::OnUpgradeFailed(nsresult aReason) {
|
||||
if (!NS_IsMainThread()) {
|
||||
return NS_DispatchToMainThread(NewRunnableMethod<nsresult>(
|
||||
"WebSocketConnectionChild::OnUpgradeFailed", this,
|
||||
&WebSocketConnectionChild::OnUpgradeFailed, aReason));
|
||||
}
|
||||
|
||||
if (CanSend()) {
|
||||
Unused << SendOnUpgradeFailed(aReason);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebSocketConnectionChild::RecvEnqueueOutgoingData(
|
||||
nsTArray<uint8_t>&& aHeader, nsTArray<uint8_t>&& aPayload) {
|
||||
LOG(("WebSocketConnectionChild::RecvEnqueueOutgoingData %p\n", this));
|
||||
|
||||
if (!mConnection) {
|
||||
MOZ_ASSERT(false);
|
||||
return IPC_FAIL(this, "Connection is not available");
|
||||
}
|
||||
|
||||
mConnection->EnqueueOutputData(std::move(aHeader), std::move(aPayload));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebSocketConnectionChild::RecvStartReading() {
|
||||
LOG(("WebSocketConnectionChild::RecvStartReading %p\n", this));
|
||||
|
||||
if (!mConnection) {
|
||||
MOZ_ASSERT(false);
|
||||
return IPC_FAIL(this, "Connection is not available");
|
||||
}
|
||||
|
||||
mConnection->StartReading();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebSocketConnectionChild::RecvDrainSocketData() {
|
||||
LOG(("WebSocketConnectionChild::RecvDrainSocketData %p\n", this));
|
||||
|
||||
if (!mConnection) {
|
||||
MOZ_ASSERT(false);
|
||||
return IPC_FAIL(this, "Connection is not available");
|
||||
}
|
||||
|
||||
mConnection->DrainSocketData();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebSocketConnectionChild::Recv__delete__() {
|
||||
LOG(("WebSocketConnectionChild::Recv__delete__ %p\n", this));
|
||||
|
||||
if (!mConnection) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mConnection->Close();
|
||||
mConnection = nullptr;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionChild::OnError(nsresult aStatus) {
|
||||
LOG(("WebSocketConnectionChild::OnError %p\n", this));
|
||||
|
||||
if (CanSend()) {
|
||||
Unused << SendOnError(aStatus);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionChild::OnTCPClosed() {
|
||||
LOG(("WebSocketConnectionChild::OnTCPClosed %p\n", this));
|
||||
|
||||
if (CanSend()) {
|
||||
Unused << SendOnTCPClosed();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionChild::OnDataReceived(uint8_t* aData, uint32_t aCount) {
|
||||
LOG(("WebSocketConnectionChild::OnDataReceived %p\n", this));
|
||||
|
||||
if (CanSend()) {
|
||||
nsTArray<uint8_t> data;
|
||||
data.AppendElements(aData, aCount);
|
||||
Unused << SendOnDataReceived(std::move(data));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void WebSocketConnectionChild::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
LOG(("WebSocketConnectionChild::ActorDestroy %p\n", this));
|
||||
if (mConnection) {
|
||||
mConnection->Close();
|
||||
mConnection = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
52
netwerk/protocol/websocket/WebSocketConnectionChild.h
Normal file
52
netwerk/protocol/websocket/WebSocketConnectionChild.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* 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_WebSocketConnectionChild_h
|
||||
#define mozilla_net_WebSocketConnectionChild_h
|
||||
|
||||
#include "mozilla/net/PWebSocketConnectionChild.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsIWebSocketConnection.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class nsWebSocketConnection;
|
||||
|
||||
// WebSocketConnectionChild only lives in socket process and uses
|
||||
// nsWebSocketConnection to send/read data from socket. Only IPDL holds a strong
|
||||
// reference to WebSocketConnectionChild, so the life time of
|
||||
// WebSocketConnectionChild is bound to the IPC actor.
|
||||
|
||||
class WebSocketConnectionChild final : public PWebSocketConnectionChild,
|
||||
public nsIHttpUpgradeListener,
|
||||
public nsIWebSocketConnectionListener {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIHTTPUPGRADELISTENER
|
||||
NS_DECL_NSIWEBSOCKETCONNECTIONLISTENER
|
||||
|
||||
WebSocketConnectionChild();
|
||||
|
||||
mozilla::ipc::IPCResult RecvEnqueueOutgoingData(nsTArray<uint8_t>&& aHeader,
|
||||
nsTArray<uint8_t>&& aPayload);
|
||||
mozilla::ipc::IPCResult RecvStartReading();
|
||||
mozilla::ipc::IPCResult RecvDrainSocketData();
|
||||
mozilla::ipc::IPCResult Recv__delete__() override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
virtual ~WebSocketConnectionChild();
|
||||
|
||||
RefPtr<nsWebSocketConnection> mConnection;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_WebSocketConnectionChild_h
|
246
netwerk/protocol/websocket/WebSocketConnectionParent.cpp
Normal file
246
netwerk/protocol/websocket/WebSocketConnectionParent.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* 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/. */
|
||||
|
||||
#include "WebSocketLog.h"
|
||||
#include "WebSocketConnectionParent.h"
|
||||
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ADDREF(WebSocketConnectionParent)
|
||||
NS_IMPL_RELEASE(WebSocketConnectionParent)
|
||||
NS_INTERFACE_MAP_BEGIN(WebSocketConnectionParent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebSocketConnection)
|
||||
NS_INTERFACE_MAP_ENTRY_CONCRETE(WebSocketConnectionParent)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
WebSocketConnectionParent::WebSocketConnectionParent(
|
||||
nsIHttpUpgradeListener* aListener)
|
||||
: mUpgradeListener(aListener), mClosed(false) {
|
||||
LOG(("WebSocketConnectionParent ctor %p\n", this));
|
||||
MOZ_ASSERT(mUpgradeListener);
|
||||
}
|
||||
|
||||
WebSocketConnectionParent::~WebSocketConnectionParent() {
|
||||
LOG(("WebSocketConnectionParent dtor %p\n", this));
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebSocketConnectionParent::RecvOnTransportAvailable(
|
||||
const nsCString& aSecurityInfoSerialization) {
|
||||
LOG(("WebSocketConnectionParent::RecvOnTransportAvailable %p\n", this));
|
||||
if (!aSecurityInfoSerialization.IsEmpty()) {
|
||||
nsresult rv = NS_DeserializeObject(aSecurityInfoSerialization,
|
||||
getter_AddRefs(mSecurityInfo));
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
|
||||
"Deserializing security info should not fail");
|
||||
Unused << rv; // So we don't get an unused error in release builds.
|
||||
}
|
||||
|
||||
if (mUpgradeListener) {
|
||||
Unused << mUpgradeListener->OnWebSocketConnectionAvailable(this);
|
||||
mUpgradeListener = nullptr;
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
static inline void DispatchHelper(nsIEventTarget* aTarget, const char* aName,
|
||||
std::function<void()>&& aTask) {
|
||||
if (aTarget->IsOnCurrentThread()) {
|
||||
aTask();
|
||||
} else {
|
||||
aTarget->Dispatch(NS_NewRunnableFunction(aName, std::move(aTask)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebSocketConnectionParent::RecvOnError(
|
||||
const nsresult& aStatus) {
|
||||
LOG(("WebSocketConnectionParent::RecvOnError %p\n", this));
|
||||
MOZ_ASSERT(mEventTarget);
|
||||
|
||||
RefPtr<WebSocketConnectionParent> self = this;
|
||||
auto task = [self{std::move(self)}, aStatus]() {
|
||||
if (self->mListener) {
|
||||
self->mListener->OnError(aStatus);
|
||||
}
|
||||
};
|
||||
|
||||
DispatchHelper(mEventTarget, "WebSocketConnectionParent::RecvOnError",
|
||||
std::move(task));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebSocketConnectionParent::RecvOnUpgradeFailed(
|
||||
const nsresult& aReason) {
|
||||
RefPtr<WebSocketConnectionParent> self = this;
|
||||
auto task = [self{std::move(self)}, aReason]() {
|
||||
if (self->mUpgradeListener) {
|
||||
Unused << self->mUpgradeListener->OnUpgradeFailed(aReason);
|
||||
self->mUpgradeListener = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
DispatchHelper(mEventTarget, "WebSocketConnectionParent::RecvOnUpgradeFailed",
|
||||
std::move(task));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebSocketConnectionParent::RecvOnTCPClosed() {
|
||||
LOG(("WebSocketConnectionParent::RecvOnTCPClosed %p\n", this));
|
||||
MOZ_ASSERT(mEventTarget);
|
||||
|
||||
RefPtr<WebSocketConnectionParent> self = this;
|
||||
auto task = [self{std::move(self)}]() {
|
||||
if (self->mListener) {
|
||||
self->mListener->OnTCPClosed();
|
||||
}
|
||||
};
|
||||
|
||||
DispatchHelper(mEventTarget, "WebSocketConnectionParent::RecvOnTCPClosed",
|
||||
std::move(task));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebSocketConnectionParent::RecvOnDataReceived(
|
||||
nsTArray<uint8_t>&& aData) {
|
||||
LOG(("WebSocketConnectionParent::RecvOnDataReceived %p\n", this));
|
||||
MOZ_ASSERT(mEventTarget);
|
||||
|
||||
RefPtr<WebSocketConnectionParent> self = this;
|
||||
auto task = [self{std::move(self)},
|
||||
data = CopyableTArray{std::move(aData)}]() {
|
||||
if (self->mListener) {
|
||||
uint8_t* buffer = const_cast<uint8_t*>(data.Elements());
|
||||
nsresult rv = self->mListener->OnDataReceived(buffer, data.Length());
|
||||
if (NS_FAILED(rv)) {
|
||||
self->mListener->OnError(rv);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DispatchHelper(mEventTarget, "WebSocketConnectionParent::RecvOnDataReceived",
|
||||
std::move(task));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void WebSocketConnectionParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
LOG(("WebSocketConnectionParent::ActorDestroy %p aWhy=%d\n", this, aWhy));
|
||||
if (!mClosed) {
|
||||
// Treat this as an error when IPC is closed before
|
||||
// WebSocketConnectionParent::Close() is called.
|
||||
nsCOMPtr<nsIWebSocketConnectionListener> listener;
|
||||
listener.swap(mListener);
|
||||
if (listener) {
|
||||
listener->OnError(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionParent::Init(nsIWebSocketConnectionListener* aListener,
|
||||
nsIEventTarget* aEventTarget) {
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
NS_ENSURE_ARG_POINTER(aEventTarget);
|
||||
|
||||
mListener = aListener;
|
||||
mEventTarget = aEventTarget;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionParent::Close() {
|
||||
LOG(("WebSocketConnectionParent::Close %p\n", this));
|
||||
|
||||
RefPtr<WebSocketConnectionParent> self = this;
|
||||
auto task = [self{std::move(self)}]() {
|
||||
self->mClosed = true;
|
||||
if (self->CanSend()) {
|
||||
Unused << self->Send__delete__(self);
|
||||
self->mListener = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
DispatchHelper(GetMainThreadEventTarget(), "WebSocketConnectionParent::Close",
|
||||
std::move(task));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionParent::EnqueueOutputData(const uint8_t* aHdrBuf,
|
||||
uint32_t aHdrBufLength,
|
||||
const uint8_t* aPayloadBuf,
|
||||
uint32_t aPayloadBufLength) {
|
||||
LOG(("WebSocketConnectionParent::EnqueueOutputData %p\n", this));
|
||||
|
||||
RefPtr<WebSocketConnectionParent> self = this;
|
||||
nsTArray<uint8_t> header;
|
||||
header.AppendElements(aHdrBuf, aHdrBufLength);
|
||||
nsTArray<uint8_t> payload;
|
||||
payload.AppendElements(aPayloadBuf, aPayloadBufLength);
|
||||
auto task = [self{std::move(self)},
|
||||
header = CopyableTArray{std::move(header)},
|
||||
payload = CopyableTArray{std::move(payload)}]() mutable {
|
||||
if (self->CanSend()) {
|
||||
Unused << self->SendEnqueueOutgoingData(std::move(header),
|
||||
std::move(payload));
|
||||
}
|
||||
};
|
||||
|
||||
DispatchHelper(GetMainThreadEventTarget(),
|
||||
"WebSocketConnectionParent::EnqueOutputData", std::move(task));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionParent::StartReading() {
|
||||
LOG(("WebSocketConnectionParent::StartReading %p\n", this));
|
||||
|
||||
RefPtr<WebSocketConnectionParent> self = this;
|
||||
auto task = [self{std::move(self)}]() {
|
||||
if (self->CanSend()) {
|
||||
Unused << self->SendStartReading();
|
||||
}
|
||||
};
|
||||
|
||||
DispatchHelper(GetMainThreadEventTarget(),
|
||||
"WebSocketConnectionParent::SendStartReading",
|
||||
std::move(task));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionParent::DrainSocketData() {
|
||||
LOG(("WebSocketConnectionParent::DrainSocketData %p\n", this));
|
||||
|
||||
RefPtr<WebSocketConnectionParent> self = this;
|
||||
auto task = [self{std::move(self)}]() {
|
||||
if (self->CanSend()) {
|
||||
Unused << self->SendDrainSocketData();
|
||||
}
|
||||
};
|
||||
|
||||
DispatchHelper(GetMainThreadEventTarget(),
|
||||
"WebSocketConnectionParent::DrainSocketData", std::move(task));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketConnectionParent::GetSecurityInfo(nsISupports** aSecurityInfo) {
|
||||
LOG(("WebSocketConnectionParent::GetSecurityInfo() %p\n", this));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aSecurityInfo);
|
||||
nsCOMPtr<nsISupports> info = mSecurityInfo;
|
||||
info.forget(aSecurityInfo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
67
netwerk/protocol/websocket/WebSocketConnectionParent.h
Normal file
67
netwerk/protocol/websocket/WebSocketConnectionParent.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* 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_WebSocketConnectionParent_h
|
||||
#define mozilla_net_WebSocketConnectionParent_h
|
||||
|
||||
#include "mozilla/net/PWebSocketConnectionParent.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsIWebSocketConnection.h"
|
||||
|
||||
class nsIHttpUpgradeListener;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// WebSocketConnectionParent implements nsIWebSocketConnection and provides
|
||||
// interface for WebSocketChannel to send/receive data. The ownership model for
|
||||
// TransportProvider is that IPDL and WebSocketChannel hold strong reference of
|
||||
// WebSocketConnectionParent. When nsIWebSocketConnection::Close is called, a
|
||||
// __delete__ message will be sent and the IPC actor will be deallocated as
|
||||
// well.
|
||||
|
||||
#define WEB_SOCKET_CONNECTION_PARENT_IID \
|
||||
{ \
|
||||
0x1cc3cb61, 0x0c09, 0x4f58, { \
|
||||
0x9a, 0x64, 0x44, 0xf7, 0x92, 0x86, 0xbc, 0x00 \
|
||||
} \
|
||||
}
|
||||
|
||||
class WebSocketConnectionParent final : public PWebSocketConnectionParent,
|
||||
public nsIWebSocketConnection {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIWEBSOCKETCONNECTION
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(WEB_SOCKET_CONNECTION_PARENT_IID)
|
||||
|
||||
explicit WebSocketConnectionParent(nsIHttpUpgradeListener* aListener);
|
||||
|
||||
mozilla::ipc::IPCResult RecvOnTransportAvailable(
|
||||
const nsCString& aSecurityInfoSerialization);
|
||||
mozilla::ipc::IPCResult RecvOnError(const nsresult& aStatus);
|
||||
mozilla::ipc::IPCResult RecvOnTCPClosed();
|
||||
mozilla::ipc::IPCResult RecvOnDataReceived(nsTArray<uint8_t>&& aData);
|
||||
mozilla::ipc::IPCResult RecvOnUpgradeFailed(const nsresult& aReason);
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
virtual ~WebSocketConnectionParent();
|
||||
|
||||
nsCOMPtr<nsIHttpUpgradeListener> mUpgradeListener;
|
||||
nsCOMPtr<nsIWebSocketConnectionListener> mListener;
|
||||
nsCOMPtr<nsIEventTarget> mEventTarget;
|
||||
nsCOMPtr<nsISupports> mSecurityInfo;
|
||||
bool mClosed;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(WebSocketConnectionParent,
|
||||
WEB_SOCKET_CONNECTION_PARENT_IID)
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_WebSocketConnectionParent_h
|
@ -23,6 +23,8 @@ EXPORTS.mozilla.net += [
|
||||
'WebSocketChannel.h',
|
||||
'WebSocketChannelChild.h',
|
||||
'WebSocketChannelParent.h',
|
||||
'WebSocketConnectionChild.h',
|
||||
'WebSocketConnectionParent.h',
|
||||
'WebSocketEventListenerChild.h',
|
||||
'WebSocketEventListenerParent.h',
|
||||
'WebSocketEventService.h',
|
||||
@ -36,6 +38,8 @@ UNIFIED_SOURCES += [
|
||||
'WebSocketChannel.cpp',
|
||||
'WebSocketChannelChild.cpp',
|
||||
'WebSocketChannelParent.cpp',
|
||||
'WebSocketConnectionChild.cpp',
|
||||
'WebSocketConnectionParent.cpp',
|
||||
'WebSocketEventListenerChild.cpp',
|
||||
'WebSocketEventListenerParent.cpp',
|
||||
'WebSocketEventService.cpp',
|
||||
@ -45,6 +49,7 @@ UNIFIED_SOURCES += [
|
||||
IPDL_SOURCES += [
|
||||
'PTransportProvider.ipdl',
|
||||
'PWebSocket.ipdl',
|
||||
'PWebSocketConnection.ipdl',
|
||||
'PWebSocketEventListener.ipdl',
|
||||
]
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "WebSocketLog.h"
|
||||
#include "nsIOService.h"
|
||||
#include "nsISocketTransport.h"
|
||||
#include "nsSocketTransportService2.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsWebSocketConnection, nsIWebSocketConnection,
|
||||
nsIInputStreamCallback, nsIOutputStreamCallback)
|
||||
@ -29,9 +28,6 @@ nsWebSocketConnection::Init(nsIWebSocketConnectionListener* aListener,
|
||||
NS_ENSURE_ARG_POINTER(aListener);
|
||||
NS_ENSURE_ARG_POINTER(aEventTarget);
|
||||
|
||||
MOZ_ASSERT_IF(nsIOService::UseSocketProcess(), XRE_IsSocketProcess());
|
||||
MOZ_ASSERT_IF(!nsIOService::UseSocketProcess(), XRE_IsParentProcess());
|
||||
|
||||
mListener = aListener;
|
||||
mEventTarget = aEventTarget;
|
||||
|
||||
@ -43,7 +39,7 @@ nsWebSocketConnection::Init(nsIWebSocketConnectionListener* aListener,
|
||||
nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryInterface(mListener);
|
||||
mTransport->SetSecurityCallbacks(callbacks);
|
||||
} else {
|
||||
// TODO: deal with security callbacks in bug 1512479
|
||||
// NOTE: we don't use security callbacks in socket process.
|
||||
mTransport->SetSecurityCallbacks(nullptr);
|
||||
}
|
||||
return mTransport->SetEventSink(nullptr, nullptr);
|
||||
@ -74,18 +70,12 @@ nsWebSocketConnection::Close() {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketConnection::EnqueueOutputData(const uint8_t* aHdrBuf,
|
||||
uint32_t aHdrBufLength,
|
||||
const uint8_t* aPayloadBuf,
|
||||
uint32_t aPayloadBufLength) {
|
||||
LOG(("nsWebSocketConnection::EnqueueOutputData %p\n", this));
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
nsresult nsWebSocketConnection::EnqueueOutputData(
|
||||
nsTArray<uint8_t>&& aHeader, nsTArray<uint8_t>&& aPayload) {
|
||||
MOZ_ASSERT(mEventTarget->IsOnCurrentThread());
|
||||
|
||||
nsTArray<uint8_t> data;
|
||||
data.AppendElements(aHdrBuf, aHdrBufLength);
|
||||
data.AppendElements(aPayloadBuf, aPayloadBufLength);
|
||||
mOutputQueue.emplace_back(std::move(data));
|
||||
mOutputQueue.emplace_back(std::move(aHeader));
|
||||
mOutputQueue.emplace_back(std::move(aPayload));
|
||||
|
||||
if (mSocketOut) {
|
||||
mSocketOut->AsyncWait(this, 0, 0, mEventTarget);
|
||||
@ -94,6 +84,20 @@ nsWebSocketConnection::EnqueueOutputData(const uint8_t* aHdrBuf,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketConnection::EnqueueOutputData(const uint8_t* aHdrBuf,
|
||||
uint32_t aHdrBufLength,
|
||||
const uint8_t* aPayloadBuf,
|
||||
uint32_t aPayloadBufLength) {
|
||||
LOG(("nsWebSocketConnection::EnqueueOutputData %p\n", this));
|
||||
|
||||
nsTArray<uint8_t> header;
|
||||
header.AppendElements(aHdrBuf, aHdrBufLength);
|
||||
nsTArray<uint8_t> payload;
|
||||
payload.AppendElements(aPayloadBuf, aPayloadBufLength);
|
||||
return EnqueueOutputData(std::move(header), std::move(payload));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketConnection::StartReading() {
|
||||
if (!mSocketIn) {
|
||||
@ -107,7 +111,7 @@ nsWebSocketConnection::StartReading() {
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketConnection::DrainSocketData() {
|
||||
MOZ_ASSERT(OnSocketThread());
|
||||
MOZ_ASSERT(mEventTarget->IsOnCurrentThread());
|
||||
|
||||
if (!mSocketIn || !mListener) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
@ -148,7 +152,7 @@ nsWebSocketConnection::GetSecurityInfo(nsISupports** aSecurityInfo) {
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketConnection::OnInputStreamReady(nsIAsyncInputStream* aStream) {
|
||||
LOG(("nsWebSocketConnection::OnInputStreamReady() %p\n", this));
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
MOZ_ASSERT(mEventTarget->IsOnCurrentThread());
|
||||
|
||||
if (!mSocketIn) // did we we clean up the socket after scheduling InputReady?
|
||||
return NS_OK;
|
||||
@ -193,7 +197,7 @@ nsWebSocketConnection::OnInputStreamReady(nsIAsyncInputStream* aStream) {
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketConnection::OnOutputStreamReady(nsIAsyncOutputStream* aStream) {
|
||||
LOG(("nsWebSocketConnection::OnOutputStreamReady() %p\n", this));
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
MOZ_ASSERT(mEventTarget->IsOnCurrentThread());
|
||||
|
||||
if (!mListener) return NS_OK;
|
||||
|
||||
|
@ -33,6 +33,9 @@ class nsWebSocketConnection : public nsIWebSocketConnection,
|
||||
nsIAsyncInputStream* aInputStream,
|
||||
nsIAsyncOutputStream* aOutputStream);
|
||||
|
||||
nsresult EnqueueOutputData(nsTArray<uint8_t>&& aHeader,
|
||||
nsTArray<uint8_t>&& aPayload);
|
||||
|
||||
private:
|
||||
virtual ~nsWebSocketConnection() = default;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user