Bug 745283 - Part 3: Support send input stream and multicast operation via PUDPSocket.ipdl. r=jduell, r=mt

This commit is contained in:
Shih-Chiang Chien 2014-05-06 18:32:25 +08:00
Родитель d101e58326
Коммит 6fb3b1ce8f
12 изменённых файлов: 491 добавлений и 372 удалений

Просмотреть файл

@ -6,6 +6,7 @@
#include "nsINetAddr.idl"
interface nsIUDPSocketInternal;
interface nsIInputStream;
%{ C++
namespace mozilla {
@ -17,7 +18,7 @@ union NetAddr;
native NetAddr(mozilla::net::NetAddr);
[ptr] native NetAddrPtr(mozilla::net::NetAddr);
[scriptable, uuid(B47E5A0F-D384-48EF-8885-4259793D9CF0)]
[scriptable, uuid(5bb7de5a-8766-4c13-b9ed-14e63168dabf)]
interface nsIUDPSocketChild : nsISupports
{
readonly attribute unsigned short localPort;
@ -25,7 +26,8 @@ interface nsIUDPSocketChild : nsISupports
attribute AUTF8String filterName;
// Tell the chrome process to bind the UDP socket to a given local host and port
void bind(in nsIUDPSocketInternal socket, in AUTF8String host, in unsigned short port);
void bind(in nsIUDPSocketInternal socket, in AUTF8String host, in unsigned short port,
in bool addressReuse, in bool loopback);
// Tell the chrome process to perform equivalent operations to all following methods
void send(in AUTF8String host, in unsigned short port,
@ -38,21 +40,28 @@ interface nsIUDPSocketChild : nsISupports
[noscript] void sendWithAddress([const] in NetAddrPtr addr,
[const, array, size_is(byteLength)] in uint8_t bytes,
in unsigned long byteLength);
// Send input stream. This must be a buffered stream implementation.
void sendBinaryStream(in AUTF8String host, in unsigned short port, in nsIInputStream stream);
void close();
void joinMulticast(in AUTF8String multicastAddress, in AUTF8String iface);
void leaveMulticast(in AUTF8String multicastAddress, in AUTF8String iface);
};
/*
* Internal interface for callback from chrome process
*/
[scriptable, uuid(1E27E9B3-C1C8-4B05-A415-1A2C1A641C60)]
[scriptable, uuid(44cd9ad5-d574-4169-baf9-e1af0648a143)]
interface nsIUDPSocketInternal : nsISupports
{
void callListenerError(in AUTF8String type, in AUTF8String message, in AUTF8String filename,
in uint32_t lineNumber, in uint32_t columnNumber);
void callListenerReceivedData(in AUTF8String type, in AUTF8String host, in unsigned short port,
[array, size_is(dataLength)] in uint8_t data,
// callback while socket is opened. localPort and localAddress is ready until this time.
void callListenerOpened();
// callback while socket is closed.
void callListenerClosed();
// callback while incoming packet is received.
void callListenerReceivedData(in AUTF8String host, in unsigned short port,
[const, array, size_is(dataLength)] in uint8_t data,
in unsigned long dataLength);
void callListenerVoid(in AUTF8String type);
void callListenerSent(in AUTF8String type, in nsresult status);
void updateReadyState(in AUTF8String readyState);
// callback while any error happened.
void callListenerError(in AUTF8String message, in AUTF8String filename, in uint32_t lineNumber);
};

Просмотреть файл

@ -6,6 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PNecko;
include protocol PBlob;
include InputStreamParams;
include "mozilla/net/NeckoMessageUtils.h";
include "mozilla/net/DNS.h";
@ -14,34 +16,19 @@ include "prio.h";
using mozilla::net::NetAddr from "mozilla/net/DNS.h";
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
struct UDPError {
nsCString message;
nsCString filename;
uint32_t lineNumber;
uint32_t columnNumber;
};
struct UDPMessage {
nsCString fromAddr;
uint16_t port;
uint8_t[] data;
};
struct UDPAddressInfo {
nsCString local;
nsCString addr;
uint16_t port;
};
struct UDPSendResult {
nsresult value;
union UDPSocketAddr {
UDPAddressInfo;
NetAddr;
};
union UDPCallbackData {
void_t;
UDPMessage;
UDPAddressInfo;
UDPSendResult;
UDPError;
union UDPData {
uint8_t[];
InputStreamParams;
};
namespace mozilla {
@ -53,13 +40,22 @@ protocol PUDPSocket
manager PNecko;
parent:
Data(uint8_t[] data, nsCString remoteAddress, uint16_t port);
DataWithAddress(uint8_t[] data, NetAddr addr);
Bind(UDPAddressInfo addressInfo, bool addressReuse, bool loopback);
OutgoingData(UDPData data, UDPSocketAddr addr);
JoinMulticast(nsCString multicastAddress, nsCString iface);
LeaveMulticast(nsCString multicastAddress, nsCString iface);
Close();
RequestDelete();
child:
Callback(nsCString type, UDPCallbackData data, nsCString aState);
CallbackOpened(UDPAddressInfo addressInfo);
CallbackClosed();
CallbackReceivedData(UDPAddressInfo addressInfo, uint8_t[] data);
CallbackError(nsCString message, nsCString filename, uint32_t lineNumber);
__delete__();
};

Просмотреть файл

@ -3,6 +3,8 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "UDPSocketChild.h"
#include "mozilla/unused.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/net/NeckoChild.h"
using mozilla::net::gNeckoChild;
@ -59,17 +61,20 @@ UDPSocketChild::~UDPSocketChild()
// nsIUDPSocketChild Methods
NS_IMETHODIMP
UDPSocketChild::Bind(nsIUDPSocketInternal *aSocket,
UDPSocketChild::Bind(nsIUDPSocketInternal* aSocket,
const nsACString& aHost,
uint16_t aPort)
uint16_t aPort,
bool aAddressReuse,
bool aLoopback)
{
NS_ENSURE_ARG(aSocket);
mSocket = aSocket;
AddIPDLReference();
gNeckoChild->SendPUDPSocketConstructor(this, nsCString(aHost), aPort, mFilterName);
gNeckoChild->SendPUDPSocketConstructor(this, mFilterName);
SendBind(UDPAddressInfo(nsCString(aHost), aPort), aAddressReuse, aLoopback);
return NS_OK;
}
@ -83,26 +88,18 @@ UDPSocketChild::Close()
NS_IMETHODIMP
UDPSocketChild::Send(const nsACString& aHost,
uint16_t aPort,
const uint8_t *aData,
const uint8_t* aData,
uint32_t aByteLength)
{
NS_ENSURE_ARG(aData);
FallibleTArray<uint8_t> fallibleArray;
if (!fallibleArray.InsertElementsAt(0, aData, aByteLength)) {
return NS_ERROR_OUT_OF_MEMORY;
}
InfallibleTArray<uint8_t> array;
array.SwapElements(fallibleArray);
SendData(array, nsCString(aHost), aPort);
return NS_OK;
return SendDataInternal(UDPSocketAddr(UDPAddressInfo(nsCString(aHost), aPort)),
aData, aByteLength);
}
NS_IMETHODIMP
UDPSocketChild::SendWithAddr(nsINetAddr *aAddr,
const uint8_t *aData,
UDPSocketChild::SendWithAddr(nsINetAddr* aAddr,
const uint8_t* aData,
uint32_t aByteLength)
{
NS_ENSURE_ARG(aAddr);
@ -111,17 +108,27 @@ UDPSocketChild::SendWithAddr(nsINetAddr *aAddr,
NetAddr addr;
aAddr->GetNetAddr(&addr);
return SendWithAddress(&addr, aData, aByteLength);
return SendDataInternal(UDPSocketAddr(addr), aData, aByteLength);
}
NS_IMETHODIMP
UDPSocketChild::SendWithAddress(const NetAddr *aAddr,
const uint8_t *aData,
UDPSocketChild::SendWithAddress(const NetAddr* aAddr,
const uint8_t* aData,
uint32_t aByteLength)
{
NS_ENSURE_ARG(aAddr);
NS_ENSURE_ARG(aData);
return SendDataInternal(UDPSocketAddr(*aAddr), aData, aByteLength);
}
nsresult
UDPSocketChild::SendDataInternal(const UDPSocketAddr& aAddr,
const uint8_t* aData,
const uint32_t aByteLength)
{
NS_ENSURE_ARG(aData);
FallibleTArray<uint8_t> fallibleArray;
if (!fallibleArray.InsertElementsAt(0, aData, aByteLength)) {
return NS_ERROR_OUT_OF_MEMORY;
@ -129,13 +136,48 @@ UDPSocketChild::SendWithAddress(const NetAddr *aAddr,
InfallibleTArray<uint8_t> array;
array.SwapElements(fallibleArray);
SendDataWithAddress(array, *aAddr);
SendOutgoingData(array, aAddr);
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::GetLocalPort(uint16_t *aLocalPort)
UDPSocketChild::SendBinaryStream(const nsACString& aHost,
uint16_t aPort,
nsIInputStream* aStream)
{
NS_ENSURE_ARG(aStream);
OptionalInputStreamParams stream;
nsTArray<mozilla::ipc::FileDescriptor> fds;
SerializeInputStream(aStream, stream, fds);
MOZ_ASSERT(fds.IsEmpty());
SendOutgoingData(UDPData(stream), UDPSocketAddr(UDPAddressInfo(nsCString(aHost), aPort)));
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::JoinMulticast(const nsACString& aMulticastAddress,
const nsACString& aInterface)
{
SendJoinMulticast(nsCString(aMulticastAddress), nsCString(aInterface));
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::LeaveMulticast(const nsACString& aMulticastAddress,
const nsACString& aInterface)
{
SendLeaveMulticast(nsCString(aMulticastAddress), nsCString(aInterface));
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::GetLocalPort(uint16_t* aLocalPort)
{
NS_ENSURE_ARG_POINTER(aLocalPort);
@ -144,14 +186,14 @@ UDPSocketChild::GetLocalPort(uint16_t *aLocalPort)
}
NS_IMETHODIMP
UDPSocketChild::GetLocalAddress(nsACString &aLocalAddress)
UDPSocketChild::GetLocalAddress(nsACString& aLocalAddress)
{
aLocalAddress = mLocalAddress;
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::SetFilterName(const nsACString &aFilterName)
UDPSocketChild::SetFilterName(const nsACString& aFilterName)
{
if (!mFilterName.IsEmpty()) {
// filter name can only be set once.
@ -162,7 +204,7 @@ UDPSocketChild::SetFilterName(const nsACString &aFilterName)
}
NS_IMETHODIMP
UDPSocketChild::GetFilterName(nsACString &aFilterName)
UDPSocketChild::GetFilterName(nsACString& aFilterName)
{
aFilterName = mFilterName;
return NS_OK;
@ -170,39 +212,44 @@ UDPSocketChild::GetFilterName(nsACString &aFilterName)
// PUDPSocketChild Methods
bool
UDPSocketChild::RecvCallback(const nsCString &aType,
const UDPCallbackData &aData,
const nsCString &aState)
UDPSocketChild::RecvCallbackOpened(const UDPAddressInfo& aAddressInfo)
{
if (NS_FAILED(mSocket->UpdateReadyState(aState)))
NS_ERROR("Shouldn't fail!");
mLocalAddress = aAddressInfo.addr();
mLocalPort = aAddressInfo.port();
nsresult rv = NS_ERROR_FAILURE;
if (aData.type() == UDPCallbackData::Tvoid_t) {
rv = mSocket->CallListenerVoid(aType);
} else if (aData.type() == UDPCallbackData::TUDPError) {
const UDPError& err(aData.get_UDPError());
rv = mSocket->CallListenerError(aType, err.message(), err.filename(),
err.lineNumber(), err.columnNumber());
} else if (aData.type() == UDPCallbackData::TUDPMessage) {
const UDPMessage& message(aData.get_UDPMessage());
InfallibleTArray<uint8_t> data(message.data());
rv = mSocket->CallListenerReceivedData(aType, message.fromAddr(), message.port(),
data.Elements(), data.Length());
} else if (aData.type() == UDPCallbackData::TUDPAddressInfo) {
//update local address and port.
const UDPAddressInfo& addressInfo(aData.get_UDPAddressInfo());
mLocalAddress = addressInfo.local();
mLocalPort = addressInfo.port();
rv = mSocket->CallListenerVoid(aType);
} else if (aData.type() == UDPCallbackData::TUDPSendResult) {
const UDPSendResult& returnValue(aData.get_UDPSendResult());
rv = mSocket->CallListenerSent(aType, returnValue.value());
} else {
MOZ_ASSERT(false, "Invalid callback type!");
}
nsresult rv = mSocket->CallListenerOpened();
mozilla::unused << NS_WARN_IF(NS_FAILED(rv));
NS_ENSURE_SUCCESS(rv, true);
return true;
}
bool
UDPSocketChild::RecvCallbackClosed()
{
nsresult rv = mSocket->CallListenerClosed();
mozilla::unused << NS_WARN_IF(NS_FAILED(rv));
return true;
}
bool
UDPSocketChild::RecvCallbackReceivedData(const UDPAddressInfo& aAddressInfo,
const InfallibleTArray<uint8_t>& aData)
{
nsresult rv = mSocket->CallListenerReceivedData(aAddressInfo.addr(), aAddressInfo.port(),
aData.Elements(), aData.Length());
mozilla::unused << NS_WARN_IF(NS_FAILED(rv));
return true;
}
bool
UDPSocketChild::RecvCallbackError(const nsCString& aMessage,
const nsCString& aFilename,
const uint32_t& aLineNumber)
{
nsresult rv = mSocket->CallListenerError(aMessage, aFilename, aLineNumber);
mozilla::unused << NS_WARN_IF(NS_FAILED(rv));
return true;
}

Просмотреть файл

@ -40,10 +40,19 @@ public:
UDPSocketChild();
virtual ~UDPSocketChild();
virtual bool RecvCallback(const nsCString& aType,
const UDPCallbackData& aData,
const nsCString& aState) MOZ_OVERRIDE;
virtual bool RecvCallbackOpened(const UDPAddressInfo& aAddressInfo) MOZ_OVERRIDE;
virtual bool RecvCallbackClosed() MOZ_OVERRIDE;
virtual bool RecvCallbackReceivedData(const UDPAddressInfo& aAddressInfo,
const InfallibleTArray<uint8_t>& aData) MOZ_OVERRIDE;
virtual bool RecvCallbackError(const nsCString& aMessage,
const nsCString& aFilename,
const uint32_t& aLineNumber) MOZ_OVERRIDE;
private:
nsresult SendDataInternal(const UDPSocketAddr& aAddr,
const uint8_t* aData,
const uint32_t aByteLength);
uint16_t mLocalPort;
nsCString mLocalAddress;
nsCString mFilterName;

Просмотреть файл

@ -9,181 +9,279 @@
#include "nsComponentManagerUtils.h"
#include "nsIUDPSocket.h"
#include "nsINetAddr.h"
#include "mozilla/AppProcessChecker.h"
#include "mozilla/unused.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/net/DNS.h"
#include "mozilla/net/NeckoCommon.h"
#include "mozilla/net/PNeckoParent.h"
namespace mozilla {
namespace dom {
static void
FireInternalError(mozilla::net::PUDPSocketParent *aActor, uint32_t aLineNo)
{
mozilla::unused <<
aActor->SendCallback(NS_LITERAL_CSTRING("onerror"),
UDPError(NS_LITERAL_CSTRING("Internal error"),
NS_LITERAL_CSTRING(__FILE__), aLineNo, 0),
NS_LITERAL_CSTRING("connecting"));
}
static nsresult
ConvertNetAddrToString(mozilla::net::NetAddr &netAddr, nsACString *address, uint16_t *port)
{
NS_ENSURE_ARG_POINTER(address);
NS_ENSURE_ARG_POINTER(port);
*port = 0;
uint32_t bufSize = 0;
switch(netAddr.raw.family) {
case AF_INET:
*port = PR_ntohs(netAddr.inet.port);
bufSize = mozilla::net::kIPv4CStrBufSize;
break;
case AF_INET6:
*port = PR_ntohs(netAddr.inet6.port);
bufSize = mozilla::net::kIPv6CStrBufSize;
break;
default:
//impossible
MOZ_ASSERT(false, "Unexpected address family");
return NS_ERROR_INVALID_ARG;
}
address->SetCapacity(bufSize);
NetAddrToString(&netAddr, address->BeginWriting(), bufSize);
address->SetLength(strlen(address->BeginReading()));
return NS_OK;
}
NS_IMPL_ISUPPORTS(UDPSocketParent, nsIUDPSocketListener)
UDPSocketParent::~UDPSocketParent()
{
}
bool
UDPSocketParent::Init(const nsACString& aFilter)
{
if (!aFilter.IsEmpty()) {
nsAutoCString contractId(NS_NETWORK_UDP_SOCKET_FILTER_HANDLER_PREFIX);
contractId.Append(aFilter);
nsCOMPtr<nsIUDPSocketFilterHandler> filterHandler =
do_GetService(contractId.get());
if (filterHandler) {
nsresult rv = filterHandler->NewFilter(getter_AddRefs(mFilter));
if (NS_FAILED(rv)) {
printf_stderr("Cannot create filter that content specified. "
"filter name: %s, error code: %d.", aFilter.BeginReading(), rv);
return false;
}
} else {
printf_stderr("Content doesn't have a valid filter. "
"filter name: %s.", aFilter.BeginReading());
return false;
}
}
return true;
}
// PUDPSocketParent methods
bool
UDPSocketParent::Init(const nsCString &aHost, const uint16_t aPort)
UDPSocketParent::RecvBind(const UDPAddressInfo& aAddressInfo,
const bool& aAddressReuse, const bool& aLoopback)
{
nsresult rv;
NS_ASSERTION(mFilter, "No packet filter");
// We don't have browser actors in xpcshell, and hence can't run automated
// tests without this loophole.
if (net::UsingNeckoIPCSecurity() && !mFilter &&
!AssertAppProcessPermission(Manager()->Manager(), "udp-socket")) {
FireInternalError(__LINE__);
return false;
}
nsCOMPtr<nsIUDPSocket> sock =
do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv);
if (NS_FAILED(rv)) {
FireInternalError(this, __LINE__);
if (NS_FAILED(BindInternal(aAddressInfo.addr(), aAddressInfo.port(), aAddressReuse, aLoopback))) {
FireInternalError(__LINE__);
return true;
}
nsCOMPtr<nsINetAddr> localAddr;
mSocket->GetLocalAddr(getter_AddRefs(localAddr));
nsCString addr;
if (NS_FAILED(localAddr->GetAddress(addr))) {
FireInternalError(__LINE__);
return true;
}
uint16_t port;
if (NS_FAILED(localAddr->GetPort(&port))) {
FireInternalError(__LINE__);
return true;
}
mozilla::unused << SendCallbackOpened(UDPAddressInfo(addr, port));
return true;
}
nsresult
UDPSocketParent::BindInternal(const nsCString& aHost, const uint16_t& aPort,
const bool& aAddressReuse, const bool& aLoopback)
{
nsresult rv;
nsCOMPtr<nsIUDPSocket> sock =
do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (aHost.IsEmpty()) {
rv = sock->Init(aPort, false);
rv = sock->Init(aPort, false, aAddressReuse, /* optional_argc = */ 1);
} else {
PRNetAddr prAddr;
PR_InitializeNetAddr(PR_IpAddrAny, aPort, &prAddr);
PRStatus status = PR_StringToNetAddr(aHost.BeginReading(), &prAddr);
if (status != PR_SUCCESS) {
FireInternalError(this, __LINE__);
return true;
return NS_ERROR_FAILURE;
}
mozilla::net::NetAddr addr;
PRNetAddrToNetAddr(&prAddr, &addr);
rv = sock->InitWithAddress(&addr);
rv = sock->InitWithAddress(&addr, aAddressReuse, /* optional_argc = */ 1);
}
if (NS_FAILED(rv)) {
FireInternalError(this, __LINE__);
return true;
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = sock->SetMulticastLoopback(aLoopback);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// register listener
rv = sock->AsyncListen(this);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mSocket = sock;
net::NetAddr localAddr;
mSocket->GetAddress(&localAddr);
return NS_OK;
}
uint16_t port;
nsCString addr;
rv = ConvertNetAddrToString(localAddr, &addr, &port);
bool
UDPSocketParent::RecvOutgoingData(const UDPData& aData,
const UDPSocketAddr& aAddr)
{
MOZ_ASSERT(mSocket);
if (NS_FAILED(rv)) {
FireInternalError(this, __LINE__);
return true;
nsresult rv;
if (mFilter) {
// TODO, Bug 933102, filter packets that are sent with hostname.
// Until then we simply throw away packets that are sent to a hostname.
if (aAddr.type() != UDPSocketAddr::TNetAddr) {
return true;
}
// TODO, Packet filter doesn't support input stream yet.
if (aData.type() != UDPData::TArrayOfuint8_t) {
return true;
}
bool allowed;
const InfallibleTArray<uint8_t>& data(aData.get_ArrayOfuint8_t());
rv = mFilter->FilterPacket(&aAddr.get_NetAddr(), data.Elements(),
data.Length(), nsIUDPSocketFilter::SF_OUTGOING,
&allowed);
// Sending unallowed data, kill content.
if (NS_WARN_IF(NS_FAILED(rv)) || !allowed) {
return false;
}
}
// register listener
mSocket->AsyncListen(this);
mozilla::unused <<
PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onopen"),
UDPAddressInfo(addr, port),
NS_LITERAL_CSTRING("connected"));
switch(aData.type()) {
case UDPData::TArrayOfuint8_t:
Send(aData.get_ArrayOfuint8_t(), aAddr);
break;
case UDPData::TInputStreamParams:
Send(aData.get_InputStreamParams(), aAddr);
break;
default:
MOZ_ASSERT(false, "Invalid data type!");
return true;
}
return true;
}
bool
UDPSocketParent::RecvData(const InfallibleTArray<uint8_t> &aData,
const nsCString& aRemoteAddress,
const uint16_t& aPort)
void
UDPSocketParent::Send(const InfallibleTArray<uint8_t>& aData,
const UDPSocketAddr& aAddr)
{
NS_ENSURE_TRUE(mSocket, true);
NS_ASSERTION(mFilter, "No packet filter");
// TODO, Bug 933102, filter packets that are sent with hostname.
// Until then we simply throw away packets that are sent to a hostname.
return true;
#if 0
// Enable this once we have filtering working with hostname delivery.
uint32_t count;
nsresult rv = mSocket->Send(aRemoteAddress,
aPort, aData.Elements(),
aData.Length(), &count);
mozilla::unused <<
PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onsent"),
UDPSendResult(rv),
NS_LITERAL_CSTRING("connected"));
NS_ENSURE_SUCCESS(rv, true);
NS_ENSURE_TRUE(count > 0, true);
return true;
#endif
}
bool
UDPSocketParent::RecvDataWithAddress(const InfallibleTArray<uint8_t>& aData,
const mozilla::net::NetAddr& aAddr)
{
NS_ENSURE_TRUE(mSocket, true);
NS_ASSERTION(mFilter, "No packet filter");
uint32_t count;
nsresult rv;
bool allowed;
rv = mFilter->FilterPacket(&aAddr, aData.Elements(),
aData.Length(), nsIUDPSocketFilter::SF_OUTGOING,
&allowed);
// Sending unallowed data, kill content.
NS_ENSURE_SUCCESS(rv, false);
NS_ENSURE_TRUE(allowed, false);
uint32_t count;
switch(aAddr.type()) {
case UDPSocketAddr::TUDPAddressInfo: {
const UDPAddressInfo& addrInfo(aAddr.get_UDPAddressInfo());
rv = mSocket->Send(addrInfo.addr(), addrInfo.port(),
aData.Elements(), aData.Length(), &count);
break;
}
case UDPSocketAddr::TNetAddr: {
const NetAddr& addr(aAddr.get_NetAddr());
rv = mSocket->SendWithAddress(&addr, aData.Elements(),
aData.Length(), &count);
break;
}
default:
MOZ_ASSERT(false, "Invalid address type!");
return;
}
if (NS_WARN_IF(NS_FAILED(rv)) || count == 0) {
FireInternalError(__LINE__);
}
}
void
UDPSocketParent::Send(const InputStreamParams& aStream,
const UDPSocketAddr& aAddr)
{
nsTArray<mozilla::ipc::FileDescriptor> fds;
nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(aStream, fds);
if (NS_WARN_IF(!stream)) {
return;
}
nsresult rv;
switch(aAddr.type()) {
case UDPSocketAddr::TUDPAddressInfo: {
const UDPAddressInfo& addrInfo(aAddr.get_UDPAddressInfo());
rv = mSocket->SendBinaryStream(addrInfo.addr(), addrInfo.port(), stream);
break;
}
case UDPSocketAddr::TNetAddr: {
const NetAddr& addr(aAddr.get_NetAddr());
rv = mSocket->SendBinaryStreamWithAddress(&addr, stream);
break;
}
default:
MOZ_ASSERT(false, "Invalid address type!");
return;
}
if (NS_FAILED(rv)) {
FireInternalError(__LINE__);
}
}
bool
UDPSocketParent::RecvJoinMulticast(const nsCString& aMulticastAddress,
const nsCString& aInterface)
{
nsresult rv = mSocket->JoinMulticast(aMulticastAddress, aInterface);
if (NS_WARN_IF(NS_FAILED(rv))) {
FireInternalError(__LINE__);
}
return true;
}
bool
UDPSocketParent::RecvLeaveMulticast(const nsCString& aMulticastAddress,
const nsCString& aInterface)
{
nsresult rv = mSocket->LeaveMulticast(aMulticastAddress, aInterface);
if (NS_WARN_IF(NS_FAILED(rv))) {
FireInternalError(__LINE__);
}
rv = mSocket->SendWithAddress(&aAddr, aData.Elements(),
aData.Length(), &count);
mozilla::unused <<
PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onsent"),
UDPSendResult(rv),
NS_LITERAL_CSTRING("connected"));
NS_ENSURE_SUCCESS(rv, true);
NS_ENSURE_TRUE(count > 0, true);
return true;
}
bool
UDPSocketParent::RecvClose()
{
NS_ENSURE_TRUE(mSocket, true);
if (!mSocket) {
return true;
}
nsresult rv = mSocket->Close();
mSocket = nullptr;
NS_ENSURE_SUCCESS(rv, true);
mozilla::unused << NS_WARN_IF(NS_FAILED(rv));
return true;
}
@ -214,7 +312,6 @@ UDPSocketParent::OnPacketReceived(nsIUDPSocket* aSocket, nsIUDPMessage* aMessage
if (!mIPCOpen) {
return NS_OK;
}
NS_ASSERTION(mFilter, "No packet filter");
uint16_t port;
nsCString ip;
@ -229,30 +326,30 @@ UDPSocketParent::OnPacketReceived(nsIUDPSocket* aSocket, nsIUDPMessage* aMessage
const char* buffer = data.get();
uint32_t len = data.Length();
bool allowed;
mozilla::net::NetAddr addr;
fromAddr->GetNetAddr(&addr);
nsresult rv = mFilter->FilterPacket(&addr,
(const uint8_t*)buffer, len,
nsIUDPSocketFilter::SF_INCOMING,
&allowed);
// Receiving unallowed data, drop.
NS_ENSURE_SUCCESS(rv, NS_OK);
NS_ENSURE_TRUE(allowed, NS_OK);
if (mFilter) {
bool allowed;
mozilla::net::NetAddr addr;
fromAddr->GetNetAddr(&addr);
nsresult rv = mFilter->FilterPacket(&addr,
(const uint8_t*)buffer, len,
nsIUDPSocketFilter::SF_INCOMING,
&allowed);
// Receiving unallowed data, drop.
if (NS_WARN_IF(NS_FAILED(rv)) || !allowed) {
return NS_OK;
}
}
FallibleTArray<uint8_t> fallibleArray;
if (!fallibleArray.InsertElementsAt(0, buffer, len)) {
FireInternalError(this, __LINE__);
FireInternalError(__LINE__);
return NS_ERROR_OUT_OF_MEMORY;
}
InfallibleTArray<uint8_t> infallibleArray;
infallibleArray.SwapElements(fallibleArray);
// compose callback
mozilla::unused <<
PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("ondata"),
UDPMessage(ip, port, infallibleArray),
NS_LITERAL_CSTRING("connected"));
mozilla::unused << SendCallbackReceivedData(UDPAddressInfo(ip, port), infallibleArray);
return NS_OK;
}
@ -262,13 +359,21 @@ UDPSocketParent::OnStopListening(nsIUDPSocket* aSocket, nsresult aStatus)
{
// underlying socket is dead, send state update to child process
if (mIPCOpen) {
mozilla::unused <<
PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onclose"),
mozilla::void_t(),
NS_LITERAL_CSTRING("closed"));
mozilla::unused << SendCallbackClosed();
}
return NS_OK;
}
void
UDPSocketParent::FireInternalError(uint32_t aLineNo)
{
if (!mIPCOpen) {
return;
}
mozilla::unused << SendCallbackError(NS_LITERAL_CSTRING("Internal error"),
NS_LITERAL_CSTRING(__FILE__), aLineNo);
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -22,24 +22,34 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIUDPSOCKETLISTENER
explicit UDPSocketParent(nsIUDPSocketFilter* filter) :
mIPCOpen(true),
mFilter(filter) {}
UDPSocketParent() :
mIPCOpen(true) {}
bool Init(const nsCString& aHost, const uint16_t aPort);
bool Init(const nsACString& aFilter);
virtual bool RecvBind(const UDPAddressInfo& aAddressInfo,
const bool& aAddressReuse, const bool& aLoopback) MOZ_OVERRIDE;
virtual bool RecvOutgoingData(const UDPData& aData, const UDPSocketAddr& aAddr) MOZ_OVERRIDE;
virtual bool RecvClose() MOZ_OVERRIDE;
virtual bool RecvData(const InfallibleTArray<uint8_t>& aData,
const nsCString& aRemoteAddress,
const uint16_t& aPort) MOZ_OVERRIDE;
virtual bool RecvDataWithAddress( const InfallibleTArray<uint8_t>& data,
const mozilla::net::NetAddr& addr);
virtual bool RecvRequestDelete() MOZ_OVERRIDE;
virtual bool RecvJoinMulticast(const nsCString& aMulticastAddress,
const nsCString& aInterface) MOZ_OVERRIDE;
virtual bool RecvLeaveMulticast(const nsCString& aMulticastAddress,
const nsCString& aInterface) MOZ_OVERRIDE;
private:
virtual ~UDPSocketParent();
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
void Send(const InfallibleTArray<uint8_t>& aData, const UDPSocketAddr& aAddr);
void Send(const InputStreamParams& aStream, const UDPSocketAddr& aAddr);
nsresult BindInternal(const nsCString& aHost, const uint16_t& aPort,
const bool& aAddressReuse, const bool& aLoopback);
void FireInternalError(uint32_t aLineNo);
bool mIPCOpen;
nsCOMPtr<nsIUDPSocket> mSocket;

Просмотреть файл

@ -705,17 +705,13 @@ NrSocketIpc::NrSocketIpc(const nsCOMPtr<nsIEventTarget> &main_thread)
// IUDPSocketInternal interfaces
// callback while error happened in UDP socket operation
NS_IMETHODIMP NrSocketIpc::CallListenerError(const nsACString &type,
const nsACString &message,
NS_IMETHODIMP NrSocketIpc::CallListenerError(const nsACString &message,
const nsACString &filename,
uint32_t line_number,
uint32_t column_number) {
uint32_t line_number) {
ASSERT_ON_THREAD(main_thread_);
MOZ_ASSERT(type.EqualsLiteral("onerror"));
r_log(LOG_GENERIC, LOG_ERR, "UDP socket error:%s at %s:%d:%d",
message.BeginReading(), filename.BeginReading(),
line_number, column_number);
r_log(LOG_GENERIC, LOG_ERR, "UDP socket error:%s at %s:%d",
message.BeginReading(), filename.BeginReading(), line_number );
ReentrantMonitorAutoEnter mon(monitor_);
err_ = true;
@ -725,12 +721,11 @@ NS_IMETHODIMP NrSocketIpc::CallListenerError(const nsACString &type,
}
// callback while receiving UDP packet
NS_IMETHODIMP NrSocketIpc::CallListenerReceivedData(const nsACString &type,
const nsACString &host,
uint16_t port, uint8_t *data,
NS_IMETHODIMP NrSocketIpc::CallListenerReceivedData(const nsACString &host,
uint16_t port,
const uint8_t *data,
uint32_t data_length) {
ASSERT_ON_THREAD(main_thread_);
MOZ_ASSERT(type.EqualsLiteral("ondata"));
PRNetAddr addr;
memset(&addr, 0, sizeof(addr));
@ -763,89 +758,68 @@ NS_IMETHODIMP NrSocketIpc::CallListenerReceivedData(const nsACString &type,
return NS_OK;
}
// callback while UDP socket is opened or closed
NS_IMETHODIMP NrSocketIpc::CallListenerVoid(const nsACString &type) {
// callback while UDP socket is opened
NS_IMETHODIMP NrSocketIpc::CallListenerOpened() {
ASSERT_ON_THREAD(main_thread_);
if (type.EqualsLiteral("onopen")) {
ReentrantMonitorAutoEnter mon(monitor_);
ReentrantMonitorAutoEnter mon(monitor_);
uint16_t port;
if (NS_FAILED(socket_child_->GetLocalPort(&port))) {
err_ = true;
MOZ_ASSERT(false, "Failed to get local port");
return NS_OK;
}
nsAutoCString address;
if(NS_FAILED(socket_child_->GetLocalAddress(address))) {
err_ = true;
MOZ_ASSERT(false, "Failed to get local address");
return NS_OK;
}
PRNetAddr praddr;
if (PR_SUCCESS != PR_InitializeNetAddr(PR_IpAddrAny, port, &praddr)) {
err_ = true;
MOZ_ASSERT(false, "Failed to set port in PRNetAddr");
return NS_OK;
}
if (PR_SUCCESS != PR_StringToNetAddr(address.BeginReading(), &praddr)) {
err_ = true;
MOZ_ASSERT(false, "Failed to convert local host to PRNetAddr");
return NS_OK;
}
nr_transport_addr expected_addr;
if(nr_transport_addr_copy(&expected_addr, &my_addr_)) {
err_ = true;
MOZ_ASSERT(false, "Failed to copy my_addr_");
}
if (nr_praddr_to_transport_addr(&praddr, &my_addr_, IPPROTO_UDP, 1)) {
err_ = true;
MOZ_ASSERT(false, "Failed to copy local host to my_addr_");
}
if (nr_transport_addr_cmp(&expected_addr, &my_addr_,
NR_TRANSPORT_ADDR_CMP_MODE_ADDR)) {
err_ = true;
MOZ_ASSERT(false, "Address of opened socket is not expected");
}
mon.NotifyAll();
} else if (type.EqualsLiteral("onclose")) {
// Already handled in UpdateReadyState, nothing to do here
} else {
MOZ_ASSERT(false, "Received unexpected event");
}
return NS_OK;
}
// callback while UDP packet is sent
NS_IMETHODIMP NrSocketIpc::CallListenerSent(const nsACString &type,
nsresult result) {
ASSERT_ON_THREAD(main_thread_);
MOZ_ASSERT(type.EqualsLiteral("onsent"));
if (NS_FAILED(result)) {
ReentrantMonitorAutoEnter mon(monitor_);
uint16_t port;
if (NS_FAILED(socket_child_->GetLocalPort(&port))) {
err_ = true;
MOZ_ASSERT(false, "Failed to get local port");
return NS_OK;
}
nsAutoCString address;
if(NS_FAILED(socket_child_->GetLocalAddress(address))) {
err_ = true;
MOZ_ASSERT(false, "Failed to get local address");
return NS_OK;
}
PRNetAddr praddr;
if (PR_SUCCESS != PR_InitializeNetAddr(PR_IpAddrAny, port, &praddr)) {
err_ = true;
MOZ_ASSERT(false, "Failed to set port in PRNetAddr");
return NS_OK;
}
if (PR_SUCCESS != PR_StringToNetAddr(address.BeginReading(), &praddr)) {
err_ = true;
MOZ_ASSERT(false, "Failed to convert local host to PRNetAddr");
return NS_OK;
}
nr_transport_addr expected_addr;
if(nr_transport_addr_copy(&expected_addr, &my_addr_)) {
err_ = true;
MOZ_ASSERT(false, "Failed to copy my_addr_");
}
if (nr_praddr_to_transport_addr(&praddr, &my_addr_, IPPROTO_UDP, 1)) {
err_ = true;
MOZ_ASSERT(false, "Failed to copy local host to my_addr_");
}
if (nr_transport_addr_cmp(&expected_addr, &my_addr_,
NR_TRANSPORT_ADDR_CMP_MODE_ADDR)) {
err_ = true;
MOZ_ASSERT(false, "Address of opened socket is not expected");
}
mon.NotifyAll();
return NS_OK;
}
// callback for state update after every socket operation
NS_IMETHODIMP NrSocketIpc::UpdateReadyState(const nsACString &readyState) {
// callback while UDP socket is closed
NS_IMETHODIMP NrSocketIpc::CallListenerClosed() {
ASSERT_ON_THREAD(main_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
if (readyState.EqualsLiteral("closed")) {
MOZ_ASSERT(state_ == NR_CONNECTED || state_ == NR_CLOSING);
state_ = NR_CLOSED;
}
MOZ_ASSERT(state_ == NR_CONNECTED || state_ == NR_CLOSING);
state_ = NR_CLOSED;
return NS_OK;
}
@ -1035,14 +1009,20 @@ void NrSocketIpc::create_m(const nsACString &host, const uint16_t port) {
if (NS_FAILED(rv)) {
err_ = true;
MOZ_ASSERT(false, "Failed to create UDPSocketChild");
mon.NotifyAll();
return;
}
socket_child_ = new nsMainThreadPtrHolder<nsIUDPSocketChild>(socketChild);
socket_child_->SetFilterName(nsCString("stun"));
if (NS_FAILED(socket_child_->Bind(this, host, port))) {
if (NS_FAILED(socket_child_->Bind(this, host, port,
/* reuse = */ false,
/* loopback = */ false))) {
err_ = true;
MOZ_ASSERT(false, "Failed to create UDP socket");
mon.NotifyAll();
return;
}
}

Просмотреть файл

@ -236,9 +236,7 @@ NeckoChild::DeallocPTCPServerSocketChild(PTCPServerSocketChild* child)
}
PUDPSocketChild*
NeckoChild::AllocPUDPSocketChild(const nsCString& aHost,
const uint16_t& aPort,
const nsCString& aFilter)
NeckoChild::AllocPUDPSocketChild(const nsCString& aFilter)
{
NS_NOTREACHED("AllocPUDPSocket should not be called");
return nullptr;

Просмотреть файл

@ -51,9 +51,7 @@ protected:
const uint16_t& aBacklog,
const nsString& aBinaryType) MOZ_OVERRIDE;
virtual bool DeallocPTCPServerSocketChild(PTCPServerSocketChild*) MOZ_OVERRIDE;
virtual PUDPSocketChild* AllocPUDPSocketChild(const nsCString& aHost,
const uint16_t& aPort,
const nsCString& aFilter) MOZ_OVERRIDE;
virtual PUDPSocketChild* AllocPUDPSocketChild(const nsCString& aFilter) MOZ_OVERRIDE;
virtual bool DeallocPUDPSocketChild(PUDPSocketChild*) MOZ_OVERRIDE;
virtual PDNSRequestChild* AllocPDNSRequestChild(const nsCString& aHost,
const uint32_t& aFlags) MOZ_OVERRIDE;

Просмотреть файл

@ -31,7 +31,6 @@
#include "nsPrintfCString.h"
#include "nsHTMLDNSPrefetch.h"
#include "nsIAppsService.h"
#include "nsIUDPSocketFilter.h"
#include "nsEscape.h"
#include "RemoteOpenFileParent.h"
#include "SerializedLoadContext.h"
@ -445,45 +444,18 @@ NeckoParent::DeallocPTCPServerSocketParent(PTCPServerSocketParent* actor)
}
PUDPSocketParent*
NeckoParent::AllocPUDPSocketParent(const nsCString& aHost,
const uint16_t& aPort,
const nsCString& aFilter)
NeckoParent::AllocPUDPSocketParent(const nsCString& /* unused */)
{
UDPSocketParent* p = nullptr;
nsRefPtr<UDPSocketParent> p = new UDPSocketParent();
// Only allow socket if it specifies a valid packet filter.
nsAutoCString contractId(NS_NETWORK_UDP_SOCKET_FILTER_HANDLER_PREFIX);
contractId.Append(aFilter);
if (!aFilter.IsEmpty()) {
nsCOMPtr<nsIUDPSocketFilterHandler> filterHandler =
do_GetService(contractId.get());
if (filterHandler) {
nsCOMPtr<nsIUDPSocketFilter> filter;
nsresult rv = filterHandler->NewFilter(getter_AddRefs(filter));
if (NS_SUCCEEDED(rv)) {
p = new UDPSocketParent(filter);
} else {
printf_stderr("Cannot create filter that content specified. "
"filter name: %s, error code: %d.", aFilter.get(), rv);
}
} else {
printf_stderr("Content doesn't have a valid filter. "
"filter name: %s.", aFilter.get());
}
}
NS_IF_ADDREF(p);
return p;
return p.forget().take();
}
bool
NeckoParent::RecvPUDPSocketConstructor(PUDPSocketParent* aActor,
const nsCString& aHost,
const uint16_t& aPort,
const nsCString& aFilter)
{
return static_cast<UDPSocketParent*>(aActor)->Init(aHost, aPort);
return static_cast<UDPSocketParent*>(aActor)->Init(aFilter);
}
bool

Просмотреть файл

@ -153,13 +153,8 @@ protected:
const uint16_t& aBacklog,
const nsString& aBinaryType) MOZ_OVERRIDE;
virtual bool DeallocPTCPServerSocketParent(PTCPServerSocketParent*) MOZ_OVERRIDE;
virtual PUDPSocketParent* AllocPUDPSocketParent(const nsCString& aHost,
const uint16_t& aPort,
const nsCString& aFilter) MOZ_OVERRIDE;
virtual bool RecvPUDPSocketConstructor(PUDPSocketParent*,
const nsCString& aHost,
const uint16_t& aPort,
const nsCString& aFilter) MOZ_OVERRIDE;
virtual PUDPSocketParent* AllocPUDPSocketParent(const nsCString& aFilter) MOZ_OVERRIDE;
virtual bool RecvPUDPSocketConstructor(PUDPSocketParent*, const nsCString& aFilter) MOZ_OVERRIDE;
virtual bool DeallocPUDPSocketParent(PUDPSocketParent*) MOZ_OVERRIDE;
virtual PDNSRequestParent* AllocPDNSRequestParent(const nsCString& aHost,
const uint32_t& aFlags) MOZ_OVERRIDE;

Просмотреть файл

@ -69,7 +69,7 @@ parent:
PWebSocket(PBrowserOrId browser, SerializedLoadContext loadContext);
PTCPServerSocket(uint16_t localPort, uint16_t backlog, nsString binaryType);
PUDPSocket(nsCString host, uint16_t port, nsCString filter);
PUDPSocket(nsCString filter);
PDNSRequest(nsCString hostName, uint32_t flags);