tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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