2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-09-24 22:53:49 +04:00
|
|
|
/* 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/. */
|
|
|
|
|
2013-07-29 21:36:43 +04:00
|
|
|
#include <algorithm>
|
2012-09-24 22:53:49 +04:00
|
|
|
#include "TCPSocketChild.h"
|
2013-07-29 21:36:43 +04:00
|
|
|
#include "mozilla/unused.h"
|
2014-10-07 21:44:07 +04:00
|
|
|
#include "mozilla/UniquePtr.h"
|
2012-09-24 22:53:49 +04:00
|
|
|
#include "mozilla/net/NeckoChild.h"
|
|
|
|
#include "mozilla/dom/PBrowserChild.h"
|
|
|
|
#include "mozilla/dom/TabChild.h"
|
2015-03-25 17:36:56 +03:00
|
|
|
#include "TCPSocket.h"
|
2012-09-24 22:53:49 +04:00
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "jsapi.h"
|
|
|
|
#include "jsfriendapi.h"
|
|
|
|
|
|
|
|
using mozilla::net::gNeckoChild;
|
|
|
|
|
|
|
|
namespace IPC {
|
|
|
|
|
|
|
|
bool
|
2015-03-25 17:36:56 +03:00
|
|
|
DeserializeArrayBuffer(JSContext* cx,
|
2013-04-19 13:25:33 +04:00
|
|
|
const InfallibleTArray<uint8_t>& aBuffer,
|
2013-05-11 06:39:45 +04:00
|
|
|
JS::MutableHandle<JS::Value> aVal)
|
2012-09-24 22:53:49 +04:00
|
|
|
{
|
2014-10-07 21:44:07 +04:00
|
|
|
mozilla::UniquePtr<uint8_t[], JS::FreePolicy> data(js_pod_malloc<uint8_t>(aBuffer.Length()));
|
2012-09-24 22:53:49 +04:00
|
|
|
if (!data)
|
2014-10-07 21:44:07 +04:00
|
|
|
return false;
|
|
|
|
memcpy(data.get(), aBuffer.Elements(), aBuffer.Length());
|
|
|
|
|
|
|
|
JSObject* obj = JS_NewArrayBufferWithContents(cx, aBuffer.Length(), data.get());
|
|
|
|
if (!obj)
|
|
|
|
return false;
|
|
|
|
data.release();
|
|
|
|
|
|
|
|
aVal.setObject(*obj);
|
2012-09-24 22:53:49 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace IPC
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
2015-07-08 23:06:33 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(TCPSocketChildBase)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TCPSocketChildBase)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSocket)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TCPSocketChildBase)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSocket)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(TCPSocketChildBase)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
|
|
|
2012-09-24 22:53:49 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(TCPSocketChildBase)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(TCPSocketChildBase)
|
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPSocketChildBase)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
|
|
|
TCPSocketChildBase::TCPSocketChildBase()
|
|
|
|
: mIPCOpen(false)
|
|
|
|
{
|
2015-07-08 23:06:33 +03:00
|
|
|
mozilla::HoldJSObjects(this);
|
2012-09-24 22:53:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
TCPSocketChildBase::~TCPSocketChildBase()
|
|
|
|
{
|
2015-07-08 23:06:33 +03:00
|
|
|
mozilla::DropJSObjects(this);
|
2012-09-24 22:53:49 +04:00
|
|
|
}
|
|
|
|
|
2014-03-28 00:38:33 +04:00
|
|
|
NS_IMETHODIMP_(MozExternalRefCountType) TCPSocketChild::Release(void)
|
2012-09-24 22:53:49 +04:00
|
|
|
{
|
|
|
|
nsrefcnt refcnt = TCPSocketChildBase::Release();
|
|
|
|
if (refcnt == 1 && mIPCOpen) {
|
|
|
|
PTCPSocketChild::SendRequestDelete();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return refcnt;
|
|
|
|
}
|
|
|
|
|
2015-03-25 17:36:56 +03:00
|
|
|
TCPSocketChild::TCPSocketChild(const nsAString& aHost, const uint16_t& aPort)
|
|
|
|
: mHost(aHost)
|
|
|
|
, mPort(aPort)
|
2012-09-24 22:53:49 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-03-25 17:36:56 +03:00
|
|
|
void
|
|
|
|
TCPSocketChild::SendOpen(TCPSocket* aSocket, bool aUseSSL, bool aUseArrayBuffers)
|
2012-09-24 22:53:49 +04:00
|
|
|
{
|
|
|
|
mSocket = aSocket;
|
2013-07-29 21:36:43 +04:00
|
|
|
|
2012-09-24 22:53:49 +04:00
|
|
|
AddIPDLReference();
|
2015-03-25 17:36:56 +03:00
|
|
|
gNeckoChild->SendPTCPSocketConstructor(this, mHost, mPort);
|
|
|
|
PTCPSocketChild::SendOpen(mHost, mPort, aUseSSL, aUseArrayBuffers);
|
2012-09-24 22:53:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TCPSocketChildBase::ReleaseIPDLReference()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mIPCOpen);
|
|
|
|
mIPCOpen = false;
|
|
|
|
this->Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TCPSocketChildBase::AddIPDLReference()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!mIPCOpen);
|
|
|
|
mIPCOpen = true;
|
|
|
|
this->AddRef();
|
|
|
|
}
|
|
|
|
|
|
|
|
TCPSocketChild::~TCPSocketChild()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-11-14 12:00:28 +04:00
|
|
|
bool
|
|
|
|
TCPSocketChild::RecvUpdateBufferedAmount(const uint32_t& aBuffered,
|
|
|
|
const uint32_t& aTrackingNumber)
|
|
|
|
{
|
2015-03-25 17:36:56 +03:00
|
|
|
mSocket->UpdateBufferedAmount(aBuffered, aTrackingNumber);
|
2013-11-14 12:00:28 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-09-24 22:53:49 +04:00
|
|
|
bool
|
|
|
|
TCPSocketChild::RecvCallback(const nsString& aType,
|
|
|
|
const CallbackData& aData,
|
2015-03-25 17:36:56 +03:00
|
|
|
const uint32_t& aReadyState)
|
2012-09-24 22:53:49 +04:00
|
|
|
{
|
2015-03-25 17:36:56 +03:00
|
|
|
mSocket->UpdateReadyState(aReadyState);
|
2012-09-24 22:53:49 +04:00
|
|
|
|
|
|
|
if (aData.type() == CallbackData::Tvoid_t) {
|
2015-03-25 17:36:56 +03:00
|
|
|
mSocket->FireEvent(aType);
|
2012-09-24 22:53:49 +04:00
|
|
|
|
2013-05-02 11:51:54 +04:00
|
|
|
} else if (aData.type() == CallbackData::TTCPError) {
|
|
|
|
const TCPError& err(aData.get_TCPError());
|
2015-03-25 17:36:56 +03:00
|
|
|
mSocket->FireErrorEvent(err.name(), err.message());
|
2012-09-24 22:53:49 +04:00
|
|
|
|
|
|
|
} else if (aData.type() == CallbackData::TSendableData) {
|
|
|
|
const SendableData& data = aData.get_SendableData();
|
|
|
|
|
2015-03-25 17:36:56 +03:00
|
|
|
AutoJSAPI api;
|
|
|
|
if (NS_WARN_IF(!api.Init(mSocket->GetOwner()))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
JSContext* cx = api.cx();
|
|
|
|
JS::Rooted<JS::Value> val(cx);
|
|
|
|
|
2012-09-24 22:53:49 +04:00
|
|
|
if (data.type() == SendableData::TArrayOfuint8_t) {
|
2015-03-25 17:36:56 +03:00
|
|
|
bool ok = IPC::DeserializeArrayBuffer(cx, data.get_ArrayOfuint8_t(), &val);
|
2013-04-23 20:05:06 +04:00
|
|
|
NS_ENSURE_TRUE(ok, true);
|
2012-09-24 22:53:49 +04:00
|
|
|
|
2015-03-25 17:36:56 +03:00
|
|
|
} else if (data.type() == SendableData::TnsCString) {
|
|
|
|
bool ok = ToJSValue(cx, NS_ConvertASCIItoUTF16(data.get_nsCString()), &val);
|
|
|
|
NS_ENSURE_TRUE(ok, true);
|
2012-09-24 22:53:49 +04:00
|
|
|
|
|
|
|
} else {
|
2013-06-29 05:38:30 +04:00
|
|
|
MOZ_CRASH("Invalid callback data type!");
|
2012-09-24 22:53:49 +04:00
|
|
|
}
|
2015-03-25 17:36:56 +03:00
|
|
|
mSocket->FireDataEvent(cx, aType, val);
|
2012-09-24 22:53:49 +04:00
|
|
|
|
|
|
|
} else {
|
2013-06-29 05:38:30 +04:00
|
|
|
MOZ_CRASH("Invalid callback type!");
|
2012-09-24 22:53:49 +04:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-03-25 17:36:56 +03:00
|
|
|
void
|
|
|
|
TCPSocketChild::SendSend(const nsACString& aData, uint32_t aTrackingNumber)
|
2012-09-24 22:53:49 +04:00
|
|
|
{
|
2015-03-25 17:36:56 +03:00
|
|
|
SendData(nsCString(aData), aTrackingNumber);
|
2012-09-24 22:53:49 +04:00
|
|
|
}
|
|
|
|
|
2015-03-25 17:36:56 +03:00
|
|
|
nsresult
|
|
|
|
TCPSocketChild::SendSend(const ArrayBuffer& aData,
|
2013-11-14 11:59:55 +04:00
|
|
|
uint32_t aByteOffset,
|
|
|
|
uint32_t aByteLength,
|
2015-03-25 17:36:56 +03:00
|
|
|
uint32_t aTrackingNumber)
|
|
|
|
{
|
|
|
|
uint32_t buflen = aData.Length();
|
|
|
|
uint32_t offset = std::min(buflen, aByteOffset);
|
|
|
|
uint32_t nbytes = std::min(buflen - aByteOffset, aByteLength);
|
|
|
|
FallibleTArray<uint8_t> fallibleArr;
|
|
|
|
if (!fallibleArr.InsertElementsAt(0, aData.Data() + offset, nbytes, fallible)) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2012-09-24 22:53:49 +04:00
|
|
|
}
|
2015-03-25 17:36:56 +03:00
|
|
|
|
|
|
|
InfallibleTArray<uint8_t> arr;
|
|
|
|
arr.SwapElements(fallibleArr);
|
|
|
|
SendData(arr, aTrackingNumber);
|
2012-09-24 22:53:49 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-03-25 17:36:56 +03:00
|
|
|
void
|
|
|
|
TCPSocketChild::SetSocket(TCPSocket* aSocket)
|
2013-07-29 21:36:43 +04:00
|
|
|
{
|
|
|
|
mSocket = aSocket;
|
|
|
|
}
|
|
|
|
|
2015-03-25 17:36:56 +03:00
|
|
|
void
|
2013-12-19 07:21:12 +04:00
|
|
|
TCPSocketChild::GetHost(nsAString& aHost)
|
|
|
|
{
|
|
|
|
aHost = mHost;
|
|
|
|
}
|
|
|
|
|
2015-03-25 17:36:56 +03:00
|
|
|
void
|
2013-12-19 07:21:12 +04:00
|
|
|
TCPSocketChild::GetPort(uint16_t* aPort)
|
|
|
|
{
|
|
|
|
*aPort = mPort;
|
|
|
|
}
|
|
|
|
|
2013-07-29 21:36:43 +04:00
|
|
|
bool
|
|
|
|
TCPSocketChild::RecvRequestDelete()
|
|
|
|
{
|
|
|
|
mozilla::unused << Send__delete__(this);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-09-24 22:53:49 +04:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|