TCPSocketParent.cpp (6374B)
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/. */ 6 7 #include "TCPSocketParent.h" 8 9 #include "TCPSocket.h" 10 #include "jsapi.h" 11 #include "jsfriendapi.h" 12 #include "mozilla/HoldDropJSObjects.h" 13 #include "mozilla/dom/BrowserParent.h" 14 #include "mozilla/dom/ScriptSettings.h" 15 #include "mozilla/net/NeckoCommon.h" 16 #include "mozilla/net/PNeckoParent.h" 17 #include "nsISocketTransport.h" 18 #include "nsJSUtils.h" 19 #include "nsNetUtil.h" 20 21 namespace IPC { 22 23 // Defined in TCPSocketChild.cpp 24 extern bool DeserializeArrayBuffer(JSContext* aCx, 25 const nsTArray<uint8_t>& aBuffer, 26 JS::MutableHandle<JS::Value> aVal); 27 28 } // namespace IPC 29 30 namespace mozilla { 31 32 namespace net { 33 // 34 // set MOZ_LOG=TCPSocket:5 35 // 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) 39 } // namespace net 40 41 using namespace net; 42 43 namespace dom { 44 45 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPSocketParentBase) 46 NS_INTERFACE_MAP_ENTRY(nsISupports) 47 NS_INTERFACE_MAP_END 48 49 NS_IMPL_CYCLE_COLLECTION(TCPSocketParentBase, mSocket) 50 NS_IMPL_CYCLE_COLLECTING_ADDREF(TCPSocketParentBase) 51 NS_IMPL_CYCLE_COLLECTING_RELEASE(TCPSocketParentBase) 52 53 TCPSocketParentBase::TCPSocketParentBase() : mIPCOpen(false) {} 54 55 TCPSocketParentBase::~TCPSocketParentBase() = default; 56 57 void TCPSocketParentBase::ReleaseIPDLReference() { 58 MOZ_ASSERT(mIPCOpen); 59 mIPCOpen = false; 60 this->Release(); 61 } 62 63 void TCPSocketParentBase::AddIPDLReference() { 64 MOZ_ASSERT(!mIPCOpen); 65 mIPCOpen = true; 66 this->AddRef(); 67 } 68 69 NS_IMETHODIMP_(MozExternalRefCountType) TCPSocketParent::Release(void) { 70 nsrefcnt refcnt = TCPSocketParentBase::Release(); 71 if (refcnt == 1 && mIPCOpen) { 72 (void)PTCPSocketParent::SendRequestDelete(); 73 return 1; 74 } 75 return refcnt; 76 } 77 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()); 84 return IPC_OK(); 85 } 86 87 mozilla::ipc::IPCResult TCPSocketParent::RecvStartTLS() { 88 NS_ENSURE_TRUE(mSocket, IPC_OK()); 89 ErrorResult rv; 90 mSocket->UpgradeToSecure(rv); 91 if (NS_WARN_IF(rv.Failed())) { 92 rv.SuppressException(); 93 } 94 95 return IPC_OK(); 96 } 97 98 mozilla::ipc::IPCResult TCPSocketParent::RecvSuspend() { 99 NS_ENSURE_TRUE(mSocket, IPC_OK()); 100 mSocket->Suspend(); 101 return IPC_OK(); 102 } 103 104 mozilla::ipc::IPCResult TCPSocketParent::RecvResume() { 105 NS_ENSURE_TRUE(mSocket, IPC_OK()); 106 ErrorResult rv; 107 mSocket->Resume(rv); 108 if (NS_WARN_IF(rv.Failed())) { 109 rv.SuppressException(); 110 } 111 112 return IPC_OK(); 113 } 114 115 mozilla::ipc::IPCResult TCPSocketParent::RecvData(const SendableData& aData) { 116 NS_ENSURE_TRUE(mSocket, IPC_OK()); 117 ErrorResult rv; 118 119 switch (aData.type()) { 120 case SendableData::TArrayOfuint8_t: { 121 AutoSafeJSContext autoCx; 122 JS::Rooted<JS::Value> val(autoCx); 123 const nsTArray<uint8_t>& buffer = aData.get_ArrayOfuint8_t(); 124 bool ok = IPC::DeserializeArrayBuffer(autoCx, buffer, &val); 125 NS_ENSURE_TRUE(ok, IPC_OK()); 126 RootedSpiderMonkeyInterface<ArrayBuffer> data(autoCx); 127 if (!data.Init(&val.toObject())) { 128 TCPSOCKET_LOG(("%s: Failed to allocate memory", __FUNCTION__)); 129 return IPC_FAIL_NO_REASON(this); 130 } 131 Optional<uint32_t> byteLength(buffer.Length()); 132 mSocket->Send(data, 0, byteLength, rv); 133 break; 134 } 135 136 case SendableData::TnsCString: { 137 const nsCString& strData = aData.get_nsCString(); 138 mSocket->Send(strData, rv); 139 break; 140 } 141 142 default: 143 MOZ_CRASH("unexpected SendableData type"); 144 } 145 NS_ENSURE_SUCCESS(rv.StealNSResult(), IPC_OK()); 146 return IPC_OK(); 147 } 148 149 mozilla::ipc::IPCResult TCPSocketParent::RecvClose() { 150 NS_ENSURE_TRUE(mSocket, IPC_OK()); 151 mSocket->Close(); 152 return IPC_OK(); 153 } 154 155 void TCPSocketParent::FireErrorEvent(const nsAString& aName, 156 const nsAString& aType, nsresult aError, 157 TCPReadyState aReadyState) { 158 SendEvent(u"error"_ns, TCPError(nsString(aName), nsString(aType), aError), 159 aReadyState); 160 } 161 162 void TCPSocketParent::FireEvent(const nsAString& aType, 163 TCPReadyState aReadyState) { 164 return SendEvent(aType, mozilla::void_t(), aReadyState); 165 } 166 167 void TCPSocketParent::FireArrayBufferDataEvent(nsTArray<uint8_t>& aBuffer, 168 TCPReadyState aReadyState) { 169 nsTArray<uint8_t> arr = std::move(aBuffer); 170 171 SendableData data(arr); 172 SendEvent(u"data"_ns, data, aReadyState); 173 } 174 175 void TCPSocketParent::FireStringDataEvent(const nsACString& aData, 176 TCPReadyState aReadyState) { 177 SendableData data((nsCString(aData))); 178 179 SendEvent(u"data"_ns, data, aReadyState); 180 } 181 182 void TCPSocketParent::SendEvent(const nsAString& aType, CallbackData aData, 183 TCPReadyState aReadyState) { 184 if (mIPCOpen) { 185 (void)PTCPSocketParent::SendCallback(nsString(aType), aData, 186 static_cast<uint32_t>(aReadyState)); 187 } 188 } 189 190 void TCPSocketParent::SetSocket(TCPSocket* socket) { mSocket = socket; } 191 192 nsresult TCPSocketParent::GetHost(nsAString& aHost) { 193 if (!mSocket) { 194 NS_ERROR("No internal socket instance mSocket!"); 195 return NS_ERROR_FAILURE; 196 } 197 mSocket->GetHost(aHost); 198 return NS_OK; 199 } 200 201 nsresult TCPSocketParent::GetPort(uint16_t* aPort) { 202 if (!mSocket) { 203 NS_ERROR("No internal socket instance mSocket!"); 204 return NS_ERROR_FAILURE; 205 } 206 *aPort = mSocket->Port(); 207 return NS_OK; 208 } 209 210 void TCPSocketParent::ActorDestroy(ActorDestroyReason why) { 211 if (mSocket) { 212 mSocket->Close(); 213 } 214 mSocket = nullptr; 215 } 216 217 mozilla::ipc::IPCResult TCPSocketParent::RecvRequestDelete() { 218 (void)Send__delete__(this); 219 return IPC_OK(); 220 } 221 222 } // namespace dom 223 } // namespace mozilla