Skip to content

Commit

Permalink
Bug 745283 - Part 3: Support send input stream and multicast operatio…
Browse files Browse the repository at this point in the history
…n via PUDPSocket.ipdl. r=jduell, r=mt
  • Loading branch information
schien committed May 6, 2014
1 parent d101e58 commit 6fb3b1c
Show file tree
Hide file tree
Showing 12 changed files with 477 additions and 358 deletions.
29 changes: 19 additions & 10 deletions dom/network/interfaces/nsIUDPSocketChild.idl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "nsINetAddr.idl"

interface nsIUDPSocketInternal;
interface nsIInputStream;

%{ C++
namespace mozilla {
Expand All @@ -17,15 +18,16 @@ 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;
readonly attribute AUTF8String localAddress;
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,
Expand All @@ -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);
};
46 changes: 21 additions & 25 deletions dom/network/src/PUDPSocket.ipdl
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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 {
Expand All @@ -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__();
};

Expand Down
159 changes: 103 additions & 56 deletions dom/network/src/UDPSocketChild.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand All @@ -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);
Expand All @@ -111,31 +108,76 @@ 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;
}

InfallibleTArray<uint8_t> array;
array.SwapElements(fallibleArray);
SendDataWithAddress(array, *aAddr);

SendOutgoingData(array, aAddr);

return NS_OK;
}

NS_IMETHODIMP
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::GetLocalPort(uint16_t *aLocalPort)
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);

Expand All @@ -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.
Expand All @@ -162,47 +204,52 @@ UDPSocketChild::SetFilterName(const nsACString &aFilterName)
}

NS_IMETHODIMP
UDPSocketChild::GetFilterName(nsACString &aFilterName)
UDPSocketChild::GetFilterName(nsACString& aFilterName)
{
aFilterName = mFilterName;
return NS_OK;
}

// PUDPSocketChild Methods
bool
UDPSocketChild::RecvCallback(const nsCString &aType,
const UDPCallbackData &aData,
const nsCString &aState)
{
if (NS_FAILED(mSocket->UpdateReadyState(aState)))
NS_ERROR("Shouldn't fail!");

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!");
}
UDPSocketChild::RecvCallbackOpened(const UDPAddressInfo& aAddressInfo)
{
mLocalAddress = aAddressInfo.addr();
mLocalPort = aAddressInfo.port();

NS_ENSURE_SUCCESS(rv, true);
nsresult rv = mSocket->CallListenerOpened();
mozilla::unused << NS_WARN_IF(NS_FAILED(rv));

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;
}
Expand Down
Loading

0 comments on commit 6fb3b1c

Please sign in to comment.