1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "TCPSocketParent.h"
9 #include "jsfriendapi.h"
10 #include "nsJSUtils.h"
11 #include "mozilla/Unused.h"
12 #include "mozilla/net/NeckoCommon.h"
13 #include "mozilla/net/PNeckoParent.h"
14 #include "mozilla/dom/ScriptSettings.h"
15 #include "mozilla/dom/BrowserParent.h"
16 #include "mozilla/HoldDropJSObjects.h"
17 #include "nsISocketTransport.h"
18 #include "nsNetUtil.h"
19 #include "TCPSocket.h"
23 // Defined in TCPSocketChild.cpp
24 extern bool DeserializeArrayBuffer(JSContext
* aCx
,
25 const nsTArray
<uint8_t>& aBuffer
,
26 JS::MutableHandle
<JS::Value
> aVal
);
34 // set MOZ_LOG=TCPSocket:5
36 extern LazyLogModule gTCPSocketLog
;
37 #define TCPSOCKET_LOG(args) MOZ_LOG(gTCPSocketLog, LogLevel::Debug, args)
38 #define TCPSOCKET_LOG_ENABLED() MOZ_LOG_TEST(gTCPSocketLog, LogLevel::Debug)
45 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPSocketParentBase
)
46 NS_INTERFACE_MAP_ENTRY(nsISupports
)
49 NS_IMPL_CYCLE_COLLECTION(TCPSocketParentBase
, mSocket
)
50 NS_IMPL_CYCLE_COLLECTING_ADDREF(TCPSocketParentBase
)
51 NS_IMPL_CYCLE_COLLECTING_RELEASE(TCPSocketParentBase
)
53 TCPSocketParentBase::TCPSocketParentBase() : mIPCOpen(false) {}
55 TCPSocketParentBase::~TCPSocketParentBase() = default;
57 void TCPSocketParentBase::ReleaseIPDLReference() {
63 void TCPSocketParentBase::AddIPDLReference() {
64 MOZ_ASSERT(!mIPCOpen
);
69 NS_IMETHODIMP_(MozExternalRefCountType
) TCPSocketParent::Release(void) {
70 nsrefcnt refcnt
= TCPSocketParentBase::Release();
71 if (refcnt
== 1 && mIPCOpen
) {
72 mozilla::Unused
<< PTCPSocketParent::SendRequestDelete();
78 mozilla::ipc::IPCResult
TCPSocketParent::RecvOpen(
79 const nsString
& aHost
, const uint16_t& aPort
, const bool& aUseSSL
,
80 const bool& aUseArrayBuffers
) {
81 mSocket
= new TCPSocket(nullptr, aHost
, aPort
, aUseSSL
, aUseArrayBuffers
);
82 mSocket
->SetSocketBridgeParent(this);
83 NS_ENSURE_SUCCESS(mSocket
->Init(nullptr), IPC_OK());
87 mozilla::ipc::IPCResult
TCPSocketParent::RecvStartTLS() {
88 NS_ENSURE_TRUE(mSocket
, IPC_OK());
90 mSocket
->UpgradeToSecure(rv
);
91 if (NS_WARN_IF(rv
.Failed())) {
92 rv
.SuppressException();
98 mozilla::ipc::IPCResult
TCPSocketParent::RecvSuspend() {
99 NS_ENSURE_TRUE(mSocket
, IPC_OK());
104 mozilla::ipc::IPCResult
TCPSocketParent::RecvResume() {
105 NS_ENSURE_TRUE(mSocket
, IPC_OK());
108 if (NS_WARN_IF(rv
.Failed())) {
109 rv
.SuppressException();
115 mozilla::ipc::IPCResult
TCPSocketParent::RecvData(const SendableData
& aData
) {
118 switch (aData
.type()) {
119 case SendableData::TArrayOfuint8_t
: {
120 AutoSafeJSContext autoCx
;
121 JS::Rooted
<JS::Value
> val(autoCx
);
122 const nsTArray
<uint8_t>& buffer
= aData
.get_ArrayOfuint8_t();
123 bool ok
= IPC::DeserializeArrayBuffer(autoCx
, buffer
, &val
);
124 NS_ENSURE_TRUE(ok
, IPC_OK());
125 RootedSpiderMonkeyInterface
<ArrayBuffer
> data(autoCx
);
126 if (!data
.Init(&val
.toObject())) {
127 TCPSOCKET_LOG(("%s: Failed to allocate memory", __FUNCTION__
));
128 return IPC_FAIL_NO_REASON(this);
130 Optional
<uint32_t> byteLength(buffer
.Length());
131 mSocket
->Send(data
, 0, byteLength
, rv
);
135 case SendableData::TnsCString
: {
136 const nsCString
& strData
= aData
.get_nsCString();
137 mSocket
->Send(strData
, rv
);
142 MOZ_CRASH("unexpected SendableData type");
144 NS_ENSURE_SUCCESS(rv
.StealNSResult(), IPC_OK());
148 mozilla::ipc::IPCResult
TCPSocketParent::RecvClose() {
149 NS_ENSURE_TRUE(mSocket
, IPC_OK());
154 void TCPSocketParent::FireErrorEvent(const nsAString
& aName
,
155 const nsAString
& aType
, nsresult aError
,
156 TCPReadyState aReadyState
) {
157 SendEvent(u
"error"_ns
, TCPError(nsString(aName
), nsString(aType
), aError
),
161 void TCPSocketParent::FireEvent(const nsAString
& aType
,
162 TCPReadyState aReadyState
) {
163 return SendEvent(aType
, mozilla::void_t(), aReadyState
);
166 void TCPSocketParent::FireArrayBufferDataEvent(nsTArray
<uint8_t>& aBuffer
,
167 TCPReadyState aReadyState
) {
168 nsTArray
<uint8_t> arr
= std::move(aBuffer
);
170 SendableData
data(arr
);
171 SendEvent(u
"data"_ns
, data
, aReadyState
);
174 void TCPSocketParent::FireStringDataEvent(const nsACString
& aData
,
175 TCPReadyState aReadyState
) {
176 SendableData
data((nsCString(aData
)));
178 SendEvent(u
"data"_ns
, data
, aReadyState
);
181 void TCPSocketParent::SendEvent(const nsAString
& aType
, CallbackData aData
,
182 TCPReadyState aReadyState
) {
184 mozilla::Unused
<< PTCPSocketParent::SendCallback(
185 nsString(aType
), aData
, static_cast<uint32_t>(aReadyState
));
189 void TCPSocketParent::SetSocket(TCPSocket
* socket
) { mSocket
= socket
; }
191 nsresult
TCPSocketParent::GetHost(nsAString
& aHost
) {
193 NS_ERROR("No internal socket instance mSocket!");
194 return NS_ERROR_FAILURE
;
196 mSocket
->GetHost(aHost
);
200 nsresult
TCPSocketParent::GetPort(uint16_t* aPort
) {
202 NS_ERROR("No internal socket instance mSocket!");
203 return NS_ERROR_FAILURE
;
205 *aPort
= mSocket
->Port();
209 void TCPSocketParent::ActorDestroy(ActorDestroyReason why
) {
216 mozilla::ipc::IPCResult
TCPSocketParent::RecvRequestDelete() {
217 mozilla::Unused
<< Send__delete__(this);
222 } // namespace mozilla