Bug 1194259: update ICE IP restriction code to not call PR_Connect() on the PBackground thread r?drno,mcmanus draft
authorRandell Jesup <rjesup@jesup.org>
Wed, 20 Jan 2016 02:13:09 -0500
changeset 323383 200b99340ad9503529f236ea615bca97c6692083
parent 323382 f8423823acd5b185097078b21e0a86bca07502c8
child 513206 9f9ad510f4cc6639618b657c6bd61c6d2e62be31
push id9713
push userrjesup@wgate.com
push dateWed, 20 Jan 2016 07:13:39 +0000
reviewersdrno, mcmanus
bugs1194259
milestone46.0a1
Bug 1194259: update ICE IP restriction code to not call PR_Connect() on the PBackground thread r?drno,mcmanus
dom/network/UDPSocketParent.cpp
dom/network/UDPSocketParent.h
media/mtransport/nr_socket_prsock.cpp
--- 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;