Bug 1194259: update ICE IP restriction code to not call PR_Connect() on the PBackground thread r?drno,mcmanus
--- a/dom/network/UDPSocketParent.cpp
+++ b/dom/network/UDPSocketParent.cpp
@@ -16,16 +16,17 @@
#include "mozilla/net/NeckoCommon.h"
#include "mozilla/net/PNeckoParent.h"
#include "nsNetUtil.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/TabParent.h"
#include "nsIPermissionManager.h"
#include "nsIScriptSecurityManager.h"
#include "mozilla/ipc/PBackgroundParent.h"
+#include "mtransport/runnable_utils.h"
//
// set NSPR_LOG_MODULES=UDPSocket:5
//
extern mozilla::LazyLogModule gUDPSocketLog;
#define UDPSOCKET_LOG(args) MOZ_LOG(gUDPSocketLog, mozilla::LogLevel::Debug, args)
#define UDPSOCKET_LOG_ENABLED() MOZ_LOG_TEST(gUDPSocketLog, mozilla::LogLevel::Debug)
@@ -240,43 +241,94 @@ UDPSocketParent::BindInternal(const nsCS
return rv;
}
mSocket = sock;
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) {
+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()))) {
- FireInternalError(__LINE__);
- return true;
+ SendInternalError(aReturnThread, __LINE__);
+ return;
}
+ CheckSTSThread();
nsCOMPtr<nsINetAddr> localAddr;
- mSocket->GetLocalAddr(getter_AddRefs(localAddr));
+ aSocket->GetLocalAddr(getter_AddRefs(localAddr));
nsCString addr;
if (NS_FAILED(localAddr->GetAddress(addr))) {
- FireInternalError(__LINE__);
- return true;
+ SendInternalError(aReturnThread, __LINE__);
+ return;
}
uint16_t port;
if (NS_FAILED(localAddr->GetPort(&port))) {
- FireInternalError(__LINE__);
- return true;
+ SendInternalError(aReturnThread, __LINE__);
+ return;
}
- UDPSOCKET_LOG(("%s: SendCallbackConnected: %s:%u", __FUNCTION__, addr.get(), port));
- mozilla::Unused << SendCallbackConnected(UDPAddressInfo(addr, port));
-
- return true;
+ 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));
@@ -536,10 +588,22 @@ UDPSocketParent::FireInternalError(uint3
if (!mIPCOpen) {
return;
}
mozilla::Unused << SendCallbackError(NS_LITERAL_CSTRING("Internal error"),
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
--- a/dom/network/UDPSocketParent.h
+++ b/dom/network/UDPSocketParent.h
@@ -32,16 +32,21 @@ public:
explicit UDPSocketParent(PBackgroundParent* aManager);
explicit UDPSocketParent(PNeckoParent* aManager);
bool Init(const IPC::Principal& aPrincipal, const nsACString& aFilter);
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;
virtual bool RecvClose() override;
virtual bool RecvRequestDelete() override;
virtual bool RecvJoinMulticast(const nsCString& aMulticastAddress,
const nsCString& aInterface) override;
virtual bool RecvLeaveMulticast(const nsCString& aMulticastAddress,
@@ -54,16 +59,18 @@ private:
virtual void ActorDestroy(ActorDestroyReason why) 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);
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;
PNeckoParent* mNeckoManager;
bool mIPCOpen;
nsCOMPtr<nsIUDPSocket> mSocket;
nsCOMPtr<nsIUDPSocketFilter> mFilter;
--- a/media/mtransport/nr_socket_prsock.cpp
+++ b/media/mtransport/nr_socket_prsock.cpp
@@ -1080,18 +1080,18 @@ NrUdpSocketIpc::~NrUdpSocketIpc()
// IUDPSocketInternal interfaces
// callback while error happened in UDP socket operation
NS_IMETHODIMP NrUdpSocketIpc::CallListenerError(const nsACString &message,
const nsACString &filename,
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;
monitor_.NotifyAll();
return NS_OK;
}
@@ -1182,32 +1182,34 @@ NS_IMETHODIMP NrUdpSocketIpc::SetAddress
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_INFO, "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_INFO, "UDP socket connected this=%p", (void*) this);
MOZ_ASSERT(state_ == NR_CONNECTED);
nsresult rv = SetAddress();
if (NS_FAILED(rv)) {
mon.NotifyAll();
return rv;
}
@@ -1218,16 +1220,17 @@ NS_IMETHODIMP NrUdpSocketIpc::CallListen
}
// callback while UDP socket is closed
NS_IMETHODIMP NrUdpSocketIpc::CallListenerClosed() {
ASSERT_ON_THREAD(io_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
+ r_log(LOG_GENERIC, LOG_INFO, "UDP socket closed this=%p", (void*) this);
MOZ_ASSERT(state_ == NR_CONNECTED || state_ == NR_CLOSING);
state_ = NR_CLOSED;
return NS_OK;
}
//
// NrSocketBase methods.
@@ -1389,33 +1392,34 @@ int NrUdpSocketIpc::getaddr(nr_transport
}
int NrUdpSocketIpc::connect(nr_transport_addr *addr) {
int r,_status;
int32_t port;
nsCString host;
ReentrantMonitorAutoEnter mon(monitor_);
- r_log(LOG_GENERIC, LOG_DEBUG, "NrUdpSocketIpc::connect(%s)", addr->as_string);
+ 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 completed err_ = %s",
- err_ ? "true" : "false");
+ 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;