Blame dom/network/TCPSocketChild.cpp

Packit f0b94e
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
Packit f0b94e
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
Packit f0b94e
/* This Source Code Form is subject to the terms of the Mozilla Public
Packit f0b94e
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
Packit f0b94e
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit f0b94e
Packit f0b94e
#include <algorithm>
Packit f0b94e
#include "TCPSocketChild.h"
Packit f0b94e
#include "mozilla/Unused.h"
Packit f0b94e
#include "mozilla/UniquePtr.h"
Packit f0b94e
#include "mozilla/net/NeckoChild.h"
Packit f0b94e
#include "mozilla/dom/PBrowserChild.h"
Packit f0b94e
#include "mozilla/dom/TabChild.h"
Packit f0b94e
#include "nsITCPSocketCallback.h"
Packit f0b94e
#include "TCPSocket.h"
Packit f0b94e
#include "nsContentUtils.h"
Packit f0b94e
#include "jsapi.h"
Packit f0b94e
#include "jsfriendapi.h"
Packit f0b94e
Packit f0b94e
using mozilla::net::gNeckoChild;
Packit f0b94e
Packit f0b94e
namespace IPC {
Packit f0b94e
Packit f0b94e
bool DeserializeArrayBuffer(JSContext* cx,
Packit f0b94e
                            const InfallibleTArray<uint8_t>& aBuffer,
Packit f0b94e
                            JS::MutableHandle<JS::Value> aVal) {
Packit f0b94e
  mozilla::UniquePtr<uint8_t[], JS::FreePolicy> data(
Packit f0b94e
      js_pod_malloc<uint8_t>(aBuffer.Length()));
Packit f0b94e
  if (!data) return false;
Packit f0b94e
  memcpy(data.get(), aBuffer.Elements(), aBuffer.Length());
Packit f0b94e
Packit f0b94e
  JSObject* obj =
Packit f0b94e
      JS_NewArrayBufferWithContents(cx, aBuffer.Length(), data.get());
Packit f0b94e
  if (!obj) return false;
Packit f0b94e
  // If JS_NewArrayBufferWithContents returns non-null, the ownership of
Packit f0b94e
  // the data is transfered to obj, so we release the ownership here.
Packit f0b94e
  mozilla::Unused << data.release();
Packit f0b94e
Packit f0b94e
  aVal.setObject(*obj);
Packit f0b94e
  return true;
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
}  // namespace IPC
Packit f0b94e
Packit f0b94e
namespace mozilla {
Packit f0b94e
namespace dom {
Packit f0b94e
Packit f0b94e
NS_IMPL_CYCLE_COLLECTION_CLASS(TCPSocketChildBase)
Packit f0b94e
Packit f0b94e
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TCPSocketChildBase)
Packit f0b94e
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSocket)
Packit f0b94e
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
Packit f0b94e
Packit f0b94e
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TCPSocketChildBase)
Packit f0b94e
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mSocket)
Packit f0b94e
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
Packit f0b94e
Packit f0b94e
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(TCPSocketChildBase)
Packit f0b94e
NS_IMPL_CYCLE_COLLECTION_TRACE_END
Packit f0b94e
Packit f0b94e
NS_IMPL_CYCLE_COLLECTING_ADDREF(TCPSocketChildBase)
Packit f0b94e
NS_IMPL_CYCLE_COLLECTING_RELEASE(TCPSocketChildBase)
Packit f0b94e
Packit f0b94e
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPSocketChildBase)
Packit f0b94e
  NS_INTERFACE_MAP_ENTRY(nsISupports)
Packit f0b94e
NS_INTERFACE_MAP_END
Packit f0b94e
Packit f0b94e
TCPSocketChildBase::TCPSocketChildBase() : mIPCOpen(false) {
Packit f0b94e
  mozilla::HoldJSObjects(this);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
TCPSocketChildBase::~TCPSocketChildBase() { mozilla::DropJSObjects(this); }
Packit f0b94e
Packit f0b94e
NS_IMETHODIMP_(MozExternalRefCountType) TCPSocketChild::Release(void) {
Packit f0b94e
  nsrefcnt refcnt = TCPSocketChildBase::Release();
Packit f0b94e
  if (refcnt == 1 && mIPCOpen) {
Packit f0b94e
    PTCPSocketChild::SendRequestDelete();
Packit f0b94e
    return 1;
Packit f0b94e
  }
Packit f0b94e
  return refcnt;
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
TCPSocketChild::TCPSocketChild(const nsAString& aHost, const uint16_t& aPort,
Packit f0b94e
                               nsIEventTarget* aTarget)
Packit f0b94e
    : mHost(aHost), mPort(aPort), mIPCEventTarget(aTarget) {}
Packit f0b94e
Packit f0b94e
void TCPSocketChild::SendOpen(nsITCPSocketCallback* aSocket, bool aUseSSL,
Packit f0b94e
                              bool aUseArrayBuffers) {
Packit f0b94e
  mSocket = aSocket;
Packit f0b94e
Packit f0b94e
  if (mIPCEventTarget) {
Packit f0b94e
    gNeckoChild->SetEventTargetForActor(this, mIPCEventTarget);
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  AddIPDLReference();
Packit f0b94e
  gNeckoChild->SendPTCPSocketConstructor(this, mHost, mPort);
Packit f0b94e
  MOZ_ASSERT(mFilterName.IsEmpty());  // Currently nobody should use this
Packit f0b94e
  PTCPSocketChild::SendOpen(mHost, mPort, aUseSSL, aUseArrayBuffers);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
void TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketCallback* aSocket,
Packit f0b94e
                                            const nsACString& aRemoteHost,
Packit f0b94e
                                            uint16_t aRemotePort,
Packit f0b94e
                                            const nsACString& aLocalHost,
Packit f0b94e
                                            uint16_t aLocalPort, bool aUseSSL,
Packit f0b94e
                                            bool aReuseAddrPort) {
Packit f0b94e
  mSocket = aSocket;
Packit f0b94e
Packit f0b94e
  if (mIPCEventTarget) {
Packit f0b94e
    gNeckoChild->SetEventTargetForActor(this, mIPCEventTarget);
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  AddIPDLReference();
Packit f0b94e
  gNeckoChild->SendPTCPSocketConstructor(
Packit f0b94e
      this, NS_ConvertUTF8toUTF16(aRemoteHost), aRemotePort);
Packit f0b94e
  PTCPSocketChild::SendOpenBind(nsCString(aRemoteHost), aRemotePort,
Packit f0b94e
                                nsCString(aLocalHost), aLocalPort, aUseSSL,
Packit f0b94e
                                aReuseAddrPort, true, mFilterName);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
void TCPSocketChildBase::ReleaseIPDLReference() {
Packit f0b94e
  MOZ_ASSERT(mIPCOpen);
Packit f0b94e
  mIPCOpen = false;
Packit f0b94e
  mSocket = nullptr;
Packit f0b94e
  this->Release();
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
void TCPSocketChildBase::AddIPDLReference() {
Packit f0b94e
  MOZ_ASSERT(!mIPCOpen);
Packit f0b94e
  mIPCOpen = true;
Packit f0b94e
  this->AddRef();
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
TCPSocketChild::~TCPSocketChild() {}
Packit f0b94e
Packit f0b94e
mozilla::ipc::IPCResult TCPSocketChild::RecvUpdateBufferedAmount(
Packit f0b94e
    const uint32_t& aBuffered, const uint32_t& aTrackingNumber) {
Packit f0b94e
  mSocket->UpdateBufferedAmount(aBuffered, aTrackingNumber);
Packit f0b94e
  return IPC_OK();
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
mozilla::ipc::IPCResult TCPSocketChild::RecvCallback(
Packit f0b94e
    const nsString& aType, const CallbackData& aData,
Packit f0b94e
    const uint32_t& aReadyState) {
Packit f0b94e
  mSocket->UpdateReadyState(aReadyState);
Packit f0b94e
Packit f0b94e
  if (aData.type() == CallbackData::Tvoid_t) {
Packit f0b94e
    mSocket->FireEvent(aType);
Packit f0b94e
Packit f0b94e
  } else if (aData.type() == CallbackData::TTCPError) {
Packit f0b94e
    const TCPError& err(aData.get_TCPError());
Packit f0b94e
    mSocket->FireErrorEvent(err.name(), err.message());
Packit f0b94e
Packit f0b94e
  } else if (aData.type() == CallbackData::TSendableData) {
Packit f0b94e
    const SendableData& data = aData.get_SendableData();
Packit f0b94e
Packit f0b94e
    if (data.type() == SendableData::TArrayOfuint8_t) {
Packit f0b94e
      mSocket->FireDataArrayEvent(aType, data.get_ArrayOfuint8_t());
Packit f0b94e
    } else if (data.type() == SendableData::TnsCString) {
Packit f0b94e
      mSocket->FireDataStringEvent(aType, data.get_nsCString());
Packit f0b94e
    } else {
Packit f0b94e
      MOZ_CRASH("Invalid callback data type!");
Packit f0b94e
    }
Packit f0b94e
  } else {
Packit f0b94e
    MOZ_CRASH("Invalid callback type!");
Packit f0b94e
  }
Packit f0b94e
  return IPC_OK();
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
void TCPSocketChild::SendSend(const nsACString& aData,
Packit f0b94e
                              uint32_t aTrackingNumber) {
Packit f0b94e
  SendData(nsCString(aData), aTrackingNumber);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
nsresult TCPSocketChild::SendSend(const ArrayBuffer& aData,
Packit f0b94e
                                  uint32_t aByteOffset, uint32_t aByteLength,
Packit f0b94e
                                  uint32_t aTrackingNumber) {
Packit f0b94e
  uint32_t buflen = aData.Length();
Packit f0b94e
  uint32_t offset = std::min(buflen, aByteOffset);
Packit f0b94e
  uint32_t nbytes = std::min(buflen - aByteOffset, aByteLength);
Packit f0b94e
  FallibleTArray<uint8_t> fallibleArr;
Packit f0b94e
  if (!fallibleArr.InsertElementsAt(0, aData.Data() + offset, nbytes,
Packit f0b94e
                                    fallible)) {
Packit f0b94e
    return NS_ERROR_OUT_OF_MEMORY;
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  InfallibleTArray<uint8_t> arr;
Packit f0b94e
  arr.SwapElements(fallibleArr);
Packit f0b94e
  SendData(arr, aTrackingNumber);
Packit f0b94e
  return NS_OK;
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
NS_IMETHODIMP
Packit f0b94e
TCPSocketChild::SendSendArray(nsTArray<uint8_t>& aArray,
Packit f0b94e
                              uint32_t aTrackingNumber) {
Packit f0b94e
  SendData(aArray, aTrackingNumber);
Packit f0b94e
  return NS_OK;
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
void TCPSocketChild::SetSocket(TCPSocket* aSocket) { mSocket = aSocket; }
Packit f0b94e
Packit f0b94e
void TCPSocketChild::GetHost(nsAString& aHost) { aHost = mHost; }
Packit f0b94e
Packit f0b94e
void TCPSocketChild::GetPort(uint16_t* aPort) { *aPort = mPort; }
Packit f0b94e
Packit f0b94e
nsresult TCPSocketChild::SetFilterName(const nsACString& aFilterName) {
Packit f0b94e
  if (!mFilterName.IsEmpty()) {
Packit f0b94e
    // filter name can only be set once.
Packit f0b94e
    return NS_ERROR_FAILURE;
Packit f0b94e
  }
Packit f0b94e
  mFilterName = aFilterName;
Packit f0b94e
  return NS_OK;
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
mozilla::ipc::IPCResult TCPSocketChild::RecvRequestDelete() {
Packit f0b94e
  mozilla::Unused << Send__delete__(this);
Packit f0b94e
  return IPC_OK();
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
}  // namespace dom
Packit f0b94e
}  // namespace mozilla