Bug 1194259: Make ICE IP restriction to default routes work in E10S r=jesup,mcmanus,drno

--HG--
extra : commitid : 2LptzIDH6lK
This commit is contained in:
Randell Jesup 2016-01-22 02:47:01 -05:00
Родитель 4385f97f0c
Коммит 22b767c6eb
12 изменённых файлов: 351 добавлений и 28 удалений

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

@ -42,6 +42,7 @@ protocol PUDPSocket
parent:
Bind(UDPAddressInfo addressInfo, bool addressReuse, bool loopback);
Connect(UDPAddressInfo addressInfo);
OutgoingData(UDPData data, UDPSocketAddr addr);
@ -54,6 +55,7 @@ parent:
child:
CallbackOpened(UDPAddressInfo addressInfo);
CallbackConnected(UDPAddressInfo addressInfo);
CallbackClosed();
CallbackReceivedData(UDPAddressInfo addressInfo, uint8_t[] data);
CallbackError(nsCString message, nsCString filename, uint32_t lineNumber);

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

@ -739,6 +739,15 @@ UDPSocket::CallListenerOpened()
return NS_OK;
}
NS_IMETHODIMP
UDPSocket::CallListenerConnected()
{
// This shouldn't be called here.
MOZ_CRASH();
return NS_OK;
}
NS_IMETHODIMP
UDPSocket::CallListenerClosed()
{

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

@ -194,6 +194,18 @@ UDPSocketChild::Bind(nsIUDPSocketInternal* aSocket,
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::Connect(nsIUDPSocketInternal* aSocket, const nsACString & aHost, uint16_t aPort)
{
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort));
mSocket = aSocket;
SendConnect(UDPAddressInfo(nsCString(aHost), aPort));
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::Close()
{
@ -344,6 +356,20 @@ UDPSocketChild::RecvCallbackOpened(const UDPAddressInfo& aAddressInfo)
return true;
}
// PUDPSocketChild Methods
bool
UDPSocketChild::RecvCallbackConnected(const UDPAddressInfo& aAddressInfo)
{
mLocalAddress = aAddressInfo.addr();
mLocalPort = aAddressInfo.port();
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, mLocalAddress.get(), mLocalPort));
nsresult rv = mSocket->CallListenerConnected();
mozilla::Unused << NS_WARN_IF(NS_FAILED(rv));
return true;
}
bool
UDPSocketChild::RecvCallbackClosed()
{

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

@ -45,6 +45,7 @@ public:
nsresult CreatePBackgroundSpinUntilDone();
virtual bool RecvCallbackOpened(const UDPAddressInfo& aAddressInfo) override;
virtual bool RecvCallbackConnected(const UDPAddressInfo& aAddressInfo) override;
virtual bool RecvCallbackClosed() override;
virtual bool RecvCallbackReceivedData(const UDPAddressInfo& aAddressInfo,
InfallibleTArray<uint8_t>&& aData) override;

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

@ -21,6 +21,7 @@
#include "nsIPermissionManager.h"
#include "nsIScriptSecurityManager.h"
#include "mozilla/ipc/PBackgroundParent.h"
#include "mtransport/runnable_utils.h"
//
// set NSPR_LOG_MODULES=UDPSocket:5
@ -100,7 +101,7 @@ UDPSocketParent::Init(const IPC::Principal& aPrincipal,
// will be used once we move all UDPSocket to PBackground, or
// if we add in Principal checking for mtransport
Unused << mBackgroundManager;
mPrincipal = aPrincipal;
if (net::UsingNeckoIPCSecurity() &&
mPrincipal &&
@ -196,7 +197,7 @@ UDPSocketParent::BindInternal(const nsCString& aHost, const uint16_t& aPort,
{
nsresult rv;
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, nsCString(aHost).get(), aPort));
UDPSOCKET_LOG(("%s: [this=%p] %s:%u addressReuse: %d loopback: %d", __FUNCTION__, this, nsCString(aHost).get(), aPort, aAddressReuse, aLoopback));
nsCOMPtr<nsIUDPSocket> sock =
do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv);
@ -226,10 +227,22 @@ UDPSocketParent::BindInternal(const nsCString& aHost, const uint16_t& aPort,
return rv;
}
rv = sock->SetMulticastLoopback(aLoopback);
nsCOMPtr<nsINetAddr> laddr;
rv = sock->GetLocalAddr(getter_AddRefs(laddr));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
uint16_t family;
rv = laddr->GetFamily(&family);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (family == nsINetAddr::FAMILY_INET) {
rv = sock->SetMulticastLoopback(aLoopback);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// register listener
rv = sock->AsyncListen(this);
@ -242,6 +255,110 @@ UDPSocketParent::BindInternal(const nsCString& aHost, const uint16_t& aPort,
return NS_OK;
}
static nsCOMPtr<nsIEventTarget> GetSTSThread()
{
nsresult rv;
nsCOMPtr<nsIEventTarget> sts_thread;
sts_thread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
MOZ_ASSERT(NS_SUCCEEDED(rv));
return sts_thread;
}
static void CheckSTSThread()
{
nsCOMPtr<nsIEventTarget> sts_thread = GetSTSThread();
ASSERT_ON_THREAD(sts_thread);
}
// Proxy the Connect() request to the STS thread, since it may block and
// should be done there.
bool
UDPSocketParent::RecvConnect(const UDPAddressInfo& aAddressInfo)
{
nsCOMPtr<nsIEventTarget> thread(NS_GetCurrentThread());
NS_WARN_IF(NS_FAILED(GetSTSThread()->Dispatch(WrapRunnable(
this,
&UDPSocketParent::DoConnect,
mSocket,
thread,
aAddressInfo),
NS_DISPATCH_NORMAL)));
return true;
}
void
UDPSocketParent::SendConnectResponse(nsIEventTarget *aThread,
const UDPAddressInfo& aAddressInfo)
{
NS_WARN_IF(NS_FAILED(aThread->Dispatch(WrapRunnable(
this,
&UDPSocketParent::SendCallbackConnected,
aAddressInfo),
NS_DISPATCH_NORMAL)));
}
// Runs on STS thread
void
UDPSocketParent::DoConnect(nsCOMPtr<nsIUDPSocket>& aSocket,
nsCOMPtr<nsIEventTarget>& aReturnThread,
const UDPAddressInfo& aAddressInfo)
{
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, aAddressInfo.addr().get(), aAddressInfo.port()));
if (NS_FAILED(ConnectInternal(aAddressInfo.addr(), aAddressInfo.port()))) {
SendInternalError(aReturnThread, __LINE__);
return;
}
CheckSTSThread();
nsCOMPtr<nsINetAddr> localAddr;
aSocket->GetLocalAddr(getter_AddRefs(localAddr));
nsCString addr;
if (NS_FAILED(localAddr->GetAddress(addr))) {
SendInternalError(aReturnThread, __LINE__);
return;
}
uint16_t port;
if (NS_FAILED(localAddr->GetPort(&port))) {
SendInternalError(aReturnThread, __LINE__);
return;
}
UDPSOCKET_LOG(("%s: SendConnectResponse: %s:%u", __FUNCTION__, addr.get(), port));
SendConnectResponse(aReturnThread, UDPAddressInfo(addr, port));
}
nsresult
UDPSocketParent::ConnectInternal(const nsCString& aHost, const uint16_t& aPort)
{
nsresult rv;
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, nsCString(aHost).get(), aPort));
PRNetAddr prAddr;
PR_InitializeNetAddr(PR_IpAddrAny, aPort, &prAddr);
PRStatus status = PR_StringToNetAddr(aHost.BeginReading(), &prAddr);
if (status != PR_SUCCESS) {
return NS_ERROR_FAILURE;
}
mozilla::net::NetAddr addr;
PRNetAddrToNetAddr(&prAddr, &addr);
rv = mSocket->Connect(&addr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
bool
UDPSocketParent::RecvOutgoingData(const UDPData& aData,
const UDPSocketAddr& aAddr)
@ -485,5 +602,17 @@ UDPSocketParent::FireInternalError(uint32_t aLineNo)
NS_LITERAL_CSTRING(__FILE__), aLineNo);
}
void
UDPSocketParent::SendInternalError(nsIEventTarget *aThread,
uint32_t aLineNo)
{
UDPSOCKET_LOG(("SendInternalError: %u", aLineNo));
NS_WARN_IF(NS_FAILED(aThread->Dispatch(WrapRunnable(
this,
&UDPSocketParent::FireInternalError,
aLineNo),
NS_DISPATCH_NORMAL)));
}
} // namespace dom
} // namespace mozilla

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

@ -36,6 +36,12 @@ public:
virtual bool RecvBind(const UDPAddressInfo& aAddressInfo,
const bool& aAddressReuse, const bool& aLoopback) override;
virtual bool RecvConnect(const UDPAddressInfo& aAddressInfo) override;
void SendConnectResponse(nsIEventTarget *aThread,
const UDPAddressInfo& aAddressInfo);
void DoConnect(nsCOMPtr<nsIUDPSocket>& aSocket,
nsCOMPtr<nsIEventTarget>& aReturnThread,
const UDPAddressInfo& aAddressInfo);
virtual bool RecvOutgoingData(const UDPData& aData, const UDPSocketAddr& aAddr) override;
@ -56,8 +62,10 @@ private:
void Send(const InputStreamParams& aStream, const UDPSocketAddr& aAddr);
nsresult BindInternal(const nsCString& aHost, const uint16_t& aPort,
const bool& aAddressReuse, const bool& aLoopback);
nsresult ConnectInternal(const nsCString& aHost, const uint16_t& aPort);
void FireInternalError(uint32_t aLineNo);
void SendInternalError(nsIEventTarget *aThread,
uint32_t aLineNo);
// One of these will be null and the other non-null.
PBackgroundParent* mBackgroundManager;

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

@ -19,7 +19,7 @@ union NetAddr;
native NetAddr(mozilla::net::NetAddr);
[ptr] native NetAddrPtr(mozilla::net::NetAddr);
[scriptable, uuid(481f15ce-224a-40b6-9927-7effbc326776)]
[scriptable, uuid(1e6ad73b-6c05-4d78-9a88-2d357b88f58b)]
interface nsIUDPSocketChild : nsISupports
{
readonly attribute unsigned short localPort;
@ -34,6 +34,9 @@ interface nsIUDPSocketChild : nsISupports
in AUTF8String host, in unsigned short port,
in bool addressReuse, in bool loopback);
// Tell the chrome process to connect the UDP socket to a given remote host and port
void connect(in nsIUDPSocketInternal socket, in AUTF8String host, in unsigned short port);
// Tell the chrome process to perform equivalent operations to all following methods
void send(in AUTF8String host, in unsigned short port,
[const, array, size_is(byteLength)] in uint8_t bytes,
@ -56,11 +59,13 @@ interface nsIUDPSocketChild : nsISupports
/*
* Internal interface for callback from chrome process
*/
[scriptable, uuid(44cd9ad5-d574-4169-baf9-e1af0648a143)]
[scriptable, uuid(613dd3ad-598b-4da9-ad63-bbda50c20098)]
interface nsIUDPSocketInternal : nsISupports
{
// callback while socket is opened. localPort and localAddress is ready until this time.
void callListenerOpened();
// callback while socket is connected.
void callListenerConnected();
// callback while socket is closed.
void callListenerClosed();
// callback while incoming packet is received.

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

@ -498,7 +498,7 @@ int nr_netaddr_to_transport_addr(const net::NetAddr *netaddr,
MOZ_ASSERT(false);
ABORT(R_BAD_ARGS);
}
_status=0;
_status = 0;
abort:
return(_status);
}
@ -536,7 +536,7 @@ int nr_praddr_to_transport_addr(const PRNetAddr *praddr,
ABORT(R_BAD_ARGS);
}
_status=0;
_status = 0;
abort:
return(_status);
}
@ -563,7 +563,7 @@ int nr_transport_addr_get_addrstring_and_port(nr_transport_addr *addr,
*host = addr_string;
_status=0;
_status = 0;
abort:
return(_status);
}
@ -765,7 +765,7 @@ int NrSocket::sendto(const void *msg, size_t len,
ABORT(R_IO_ERROR);
}
_status=0;
_status = 0;
abort:
return(_status);
}
@ -785,14 +785,14 @@ int NrSocket::recvfrom(void * buf, size_t maxlen,
r_log(LOG_GENERIC, LOG_INFO, "Error in recvfrom: %d", (int)PR_GetError());
ABORT(R_IO_ERROR);
}
*len=status;
*len = status;
if((r=nr_praddr_to_transport_addr(&nfrom,from,my_addr_.protocol,0)))
ABORT(r);
//r_log(LOG_GENERIC,LOG_DEBUG,"Read %d bytes from %s",*len,addr->as_string);
_status=0;
_status = 0;
abort:
return(_status);
}
@ -848,7 +848,7 @@ int NrSocket::connect(nr_transport_addr *addr) {
ABORT(R_WOULDBLOCK);
}
_status=0;
_status = 0;
abort:
return(_status);
}
@ -872,7 +872,7 @@ int NrSocket::write(const void *msg, size_t len, size_t *written) {
*written = status;
_status=0;
_status = 0;
abort:
return _status;
}
@ -912,7 +912,7 @@ int NrSocket::listen(int backlog) {
ABORT(R_IO_ERROR);
}
_status=0;
_status = 0;
abort:
return(_status);
}
@ -990,7 +990,7 @@ int NrSocket::accept(nr_transport_addr *addrp, nr_socket **sockp) {
// Add a reference so that we can delete it in destroy()
sock->AddRef();
_status=0;
_status = 0;
abort:
if (_status) {
delete sock;
@ -1044,6 +1044,12 @@ NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerOpened() {
return socket_->CallListenerOpened();
}
// callback while UDP socket is connected
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerConnected() {
return socket_->CallListenerConnected();
return NS_OK;
}
// callback while UDP socket is closed
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerClosed() {
return socket_->CallListenerClosed();
@ -1079,8 +1085,8 @@ NS_IMETHODIMP NrUdpSocketIpc::CallListenerError(const nsACString &message,
uint32_t line_number) {
ASSERT_ON_THREAD(io_thread_);
r_log(LOG_GENERIC, LOG_ERR, "UDP socket error:%s at %s:%d",
message.BeginReading(), filename.BeginReading(), line_number );
r_log(LOG_GENERIC, LOG_ERR, "UDP socket error:%s at %s:%d this=%p",
message.BeginReading(), filename.BeginReading(), line_number, (void*) this );
ReentrantMonitorAutoEnter mon(monitor_);
err_ = true;
@ -1127,11 +1133,7 @@ NS_IMETHODIMP NrUdpSocketIpc::CallListenerReceivedData(const nsACString &host,
return NS_OK;
}
// callback while UDP socket is opened
NS_IMETHODIMP NrUdpSocketIpc::CallListenerOpened() {
ASSERT_ON_THREAD(io_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
NS_IMETHODIMP NrUdpSocketIpc::SetAddress() {
uint16_t port;
if (NS_FAILED(socket_child_->GetLocalPort(&port))) {
err_ = true;
@ -1170,12 +1172,48 @@ NS_IMETHODIMP NrUdpSocketIpc::CallListenerOpened() {
MOZ_ASSERT(false, "Failed to copy local host to my_addr_");
}
if (nr_transport_addr_cmp(&expected_addr, &my_addr_,
if (!nr_transport_addr_is_wildcard(&expected_addr) &&
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");
}
return NS_OK;
}
// callback while UDP socket is opened
NS_IMETHODIMP NrUdpSocketIpc::CallListenerOpened() {
ASSERT_ON_THREAD(io_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
r_log(LOG_GENERIC, LOG_DEBUG, "UDP socket opened this=%p", (void*) this);
nsresult rv = SetAddress();
if (NS_FAILED(rv)) {
return rv;
}
mon.NotifyAll();
return NS_OK;
}
// callback while UDP socket is connected
NS_IMETHODIMP NrUdpSocketIpc::CallListenerConnected() {
ASSERT_ON_THREAD(io_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
r_log(LOG_GENERIC, LOG_DEBUG, "UDP socket connected this=%p", (void*) this);
MOZ_ASSERT(state_ == NR_CONNECTED);
nsresult rv = SetAddress();
if (NS_FAILED(rv)) {
mon.NotifyAll();
return rv;
}
r_log(LOG_GENERIC, LOG_INFO, "Exit UDP socket connected");
mon.NotifyAll();
return NS_OK;
@ -1187,6 +1225,7 @@ NS_IMETHODIMP NrUdpSocketIpc::CallListenerClosed() {
ReentrantMonitorAutoEnter mon(monitor_);
r_log(LOG_GENERIC, LOG_DEBUG, "UDP socket closed this=%p", (void*) this);
MOZ_ASSERT(state_ == NR_CONNECTED || state_ == NR_CLOSING);
state_ = NR_CLOSED;
@ -1279,6 +1318,8 @@ int NrUdpSocketIpc::sendto(const void *msg, size_t len, int flags,
}
void NrUdpSocketIpc::close() {
r_log(LOG_GENERIC, LOG_DEBUG, "NrUdpSocketIpc::close()");
ASSERT_ON_THREAD(sts_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
@ -1351,8 +1392,37 @@ int NrUdpSocketIpc::getaddr(nr_transport_addr *addrp) {
}
int NrUdpSocketIpc::connect(nr_transport_addr *addr) {
MOZ_ASSERT(false);
return R_INTERNAL;
int r,_status;
int32_t port;
nsCString host;
ReentrantMonitorAutoEnter mon(monitor_);
r_log(LOG_GENERIC, LOG_DEBUG, "NrUdpSocketIpc::connect(%s) this=%p", addr->as_string,
(void*) this);
if ((r=nr_transport_addr_get_addrstring_and_port(addr, &host, &port))) {
ABORT(r);
}
RUN_ON_THREAD(io_thread_,
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
&NrUdpSocketIpc::connect_i,
host, static_cast<uint16_t>(port)),
NS_DISPATCH_NORMAL);
// Wait until connect() completes.
mon.Wait();
r_log(LOG_GENERIC, LOG_DEBUG, "NrUdpSocketIpc::connect this=%p completed err_ = %s",
(void*) this, err_ ? "true" : "false");
if (err_) {
ABORT(R_INTERNAL);
}
_status = 0;
abort:
return _status;
}
int NrUdpSocketIpc::write(const void *msg, size_t len, size_t *written) {
@ -1418,6 +1488,28 @@ void NrUdpSocketIpc::create_i(const nsACString &host, const uint16_t port) {
}
}
void NrUdpSocketIpc::connect_i(const nsACString &host, const uint16_t port) {
ASSERT_ON_THREAD(io_thread_);
nsresult rv;
ReentrantMonitorAutoEnter mon(monitor_);
RefPtr<NrUdpSocketIpcProxy> proxy(new NrUdpSocketIpcProxy);
rv = proxy->Init(this);
if (NS_FAILED(rv)) {
err_ = true;
mon.NotifyAll();
return;
}
if (NS_FAILED(socket_child_->Connect(proxy, host, port))) {
err_ = true;
MOZ_ASSERT(false, "Failed to connect UDP socket");
mon.NotifyAll();
return;
}
}
void NrUdpSocketIpc::sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf) {
ASSERT_ON_THREAD(io_thread_);
@ -2017,7 +2109,7 @@ static int nr_socket_local_destroy(void **objp) {
return 0;
NrSocketBase *sock = static_cast<NrSocketBase *>(*objp);
*objp=0;
*objp = 0;
sock->close(); // Signal STS that we want not to listen
sock->Release(); // Decrement the ref count

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

@ -243,6 +243,7 @@ public:
const uint8_t *data,
uint32_t data_length);
NS_IMETHODIMP CallListenerOpened();
NS_IMETHODIMP CallListenerConnected();
NS_IMETHODIMP CallListenerClosed();
NrUdpSocketIpc();
@ -267,8 +268,11 @@ private:
DISALLOW_COPY_ASSIGN(NrUdpSocketIpc);
nsresult SetAddress(); // Set the local address from parent info.
// Main or private thread executors of the NrSocketBase APIs
void create_i(const nsACString &host, const uint16_t port);
void connect_i(const nsACString &host, const uint16_t port);
void sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf);
void close_i();
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)

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

@ -601,6 +601,8 @@ static int nr_ice_get_default_address(nr_ice_ctx *ctx, int ip_version, nr_transp
if ((r=nr_socket_getaddr(sock, addrp)))
ABORT(r);
r_log(LOG_GENERIC, LOG_DEBUG, "Default address: %s", addrp->as_string);
_status=0;
abort:
nr_socket_destroy(&sock);

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

@ -30,7 +30,7 @@ native NetAddr(mozilla::net::NetAddr);
*
* An interface to a UDP socket that can accept incoming connections.
*/
[scriptable, uuid(e0377f7b-34a9-4d0f-8191-7e0cba77a52f)]
[scriptable, uuid(d423bf4e-4499-40cf-bc03-153e2bf206d1)]
interface nsIUDPSocket : nsISupports
{
/**
@ -102,6 +102,16 @@ interface nsIUDPSocket : nsISupports
*/
void asyncListen(in nsIUDPSocketListener aListener);
/**
* connect
*
* This method connects the UDP socket to a remote UDP address.
*
* @param aRemoteAddr
* The remote address to connect to
*/
void connect([const] in NetAddrPtr aAddr);
/**
* Returns the local address of this UDP socket
*/

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

@ -675,6 +675,41 @@ fail:
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsUDPSocket::Connect(const NetAddr *aAddr)
{
UDPSOCKET_LOG(("nsUDPSocket::Connect [this=%p]\n", this));
NS_ENSURE_ARG(aAddr);
bool onSTSThread = false;
mSts->IsOnCurrentThread(&onSTSThread);
NS_ASSERTION(onSTSThread, "NOT ON STS THREAD");
if (!onSTSThread) {
return NS_ERROR_FAILURE;
}
PRNetAddr prAddr;
NetAddrToPRNetAddr(aAddr, &prAddr);
if (PR_Connect(mFD, &prAddr, PR_INTERVAL_NO_WAIT) != PR_SUCCESS) {
NS_WARNING("Cannot PR_Connect");
return NS_ERROR_FAILURE;
}
// get the resulting socket address, which may have been updated.
PRNetAddr addr;
if (PR_GetSockName(mFD, &addr) != PR_SUCCESS)
{
NS_WARNING("cannot get socket name");
return NS_ERROR_FAILURE;
}
PRNetAddrToNetAddr(&addr, &mAddr);
return NS_OK;
}
NS_IMETHODIMP
nsUDPSocket::Close()
{