summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/transport/ipc/StunAddrsRequestParent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/webrtc/transport/ipc/StunAddrsRequestParent.cpp')
-rw-r--r--dom/media/webrtc/transport/ipc/StunAddrsRequestParent.cpp262
1 files changed, 262 insertions, 0 deletions
diff --git a/dom/media/webrtc/transport/ipc/StunAddrsRequestParent.cpp b/dom/media/webrtc/transport/ipc/StunAddrsRequestParent.cpp
new file mode 100644
index 0000000000..23ef6dea73
--- /dev/null
+++ b/dom/media/webrtc/transport/ipc/StunAddrsRequestParent.cpp
@@ -0,0 +1,262 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "StunAddrsRequestParent.h"
+
+#include "../runnable_utils.h"
+#include "mozilla/StaticPtr.h"
+#include "nsIThread.h"
+#include "nsNetUtil.h"
+
+#include "transport/nricectx.h"
+#include "transport/nricemediastream.h" // needed only for including nricectx.h
+#include "transport/nricestunaddr.h"
+
+#include "../mdns_service/mdns_service.h"
+
+extern "C" {
+#include "local_addr.h"
+}
+
+using namespace mozilla::ipc;
+
+namespace mozilla::net {
+
+static void mdns_service_resolved(void* cb, const char* hostname,
+ const char* addr) {
+ StunAddrsRequestParent* self = static_cast<StunAddrsRequestParent*>(cb);
+ self->OnQueryComplete(nsCString(hostname), Some(nsCString(addr)));
+}
+
+void mdns_service_timedout(void* cb, const char* hostname) {
+ StunAddrsRequestParent* self = static_cast<StunAddrsRequestParent*>(cb);
+ self->OnQueryComplete(nsCString(hostname), Nothing());
+}
+
+StunAddrsRequestParent::StunAddrsRequestParent() : mIPCClosed(false) {
+ NS_GetMainThread(getter_AddRefs(mMainThread));
+
+ nsresult res;
+ mSTSThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res);
+ MOZ_ASSERT(mSTSThread);
+}
+
+StunAddrsRequestParent::~StunAddrsRequestParent() {
+ ASSERT_ON_THREAD(mMainThread);
+}
+
+mozilla::ipc::IPCResult StunAddrsRequestParent::RecvGetStunAddrs() {
+ ASSERT_ON_THREAD(mMainThread);
+
+ if (mIPCClosed) {
+ return IPC_OK();
+ }
+
+ RUN_ON_THREAD(mSTSThread,
+ WrapRunnable(RefPtr<StunAddrsRequestParent>(this),
+ &StunAddrsRequestParent::GetStunAddrs_s),
+ NS_DISPATCH_NORMAL);
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult StunAddrsRequestParent::RecvRegisterMDNSHostname(
+ const nsACString& aHostname, const nsACString& aAddress) {
+ ASSERT_ON_THREAD(mMainThread);
+
+ if (mIPCClosed) {
+ return IPC_OK();
+ }
+
+ if (mSharedMDNSService) {
+ mSharedMDNSService->RegisterHostname(aHostname.BeginReading(),
+ aAddress.BeginReading());
+ }
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult StunAddrsRequestParent::RecvQueryMDNSHostname(
+ const nsACString& aHostname) {
+ ASSERT_ON_THREAD(mMainThread);
+
+ if (mIPCClosed) {
+ return IPC_OK();
+ }
+
+ if (mSharedMDNSService) {
+ mSharedMDNSService->QueryHostname(this, aHostname.BeginReading());
+ }
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult StunAddrsRequestParent::RecvUnregisterMDNSHostname(
+ const nsACString& aHostname) {
+ ASSERT_ON_THREAD(mMainThread);
+
+ if (mIPCClosed) {
+ return IPC_OK();
+ }
+
+ if (mSharedMDNSService) {
+ mSharedMDNSService->UnregisterHostname(aHostname.BeginReading());
+ }
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult StunAddrsRequestParent::Recv__delete__() {
+ // see note below in ActorDestroy
+ mIPCClosed = true;
+ return IPC_OK();
+}
+
+void StunAddrsRequestParent::OnQueryComplete(const nsACString& hostname,
+ const Maybe<nsCString>& address) {
+ RUN_ON_THREAD(mMainThread,
+ WrapRunnable(RefPtr<StunAddrsRequestParent>(this),
+ &StunAddrsRequestParent::OnQueryComplete_m,
+ nsCString(hostname), address),
+ NS_DISPATCH_NORMAL);
+}
+
+void StunAddrsRequestParent::ActorDestroy(ActorDestroyReason why) {
+ // We may still have refcount>0 if we haven't made it through
+ // GetStunAddrs_s and SendStunAddrs_m yet, but child process
+ // has crashed. We must not send any more msgs to child, or
+ // IPDL will kill chrome process, too.
+ mIPCClosed = true;
+
+ // We need to stop the mDNS service here to ensure that we don't
+ // end up with any messages queued for the main thread after the
+ // destructors run. Because of Bug 1569311, all of the
+ // StunAddrsRequestParent instances end up being destroyed one
+ // after the other, so it is ok to free the shared service when
+ // the first one is destroyed rather than waiting for the last one.
+ // If this behaviour changes, we would potentially end up starting
+ // and stopping instances repeatedly and should add a refcount and
+ // a way of cancelling pending queries to avoid churn in that case.
+ if (mSharedMDNSService) {
+ mSharedMDNSService = nullptr;
+ }
+}
+
+void StunAddrsRequestParent::GetStunAddrs_s() {
+ ASSERT_ON_THREAD(mSTSThread);
+
+ // get the stun addresses while on STS thread
+ NrIceStunAddrArray addrs = NrIceCtx::GetStunAddrs();
+
+ if (mIPCClosed) {
+ return;
+ }
+
+ // in order to return the result over IPC, we need to be on main thread
+ RUN_ON_THREAD(
+ mMainThread,
+ WrapRunnable(RefPtr<StunAddrsRequestParent>(this),
+ &StunAddrsRequestParent::SendStunAddrs_m, std::move(addrs)),
+ NS_DISPATCH_NORMAL);
+}
+
+void StunAddrsRequestParent::SendStunAddrs_m(const NrIceStunAddrArray& addrs) {
+ ASSERT_ON_THREAD(mMainThread);
+
+ if (mIPCClosed) {
+ // nothing to do: child probably crashed
+ return;
+ }
+
+ // This means that the mDNS service will continue running until shutdown
+ // once started. The StunAddrsRequestParent destructor does not run until
+ // shutdown anyway (see Bug 1569311), so there is not much we can do about
+ // this here. One option would be to add a check if there are no hostnames
+ // registered after UnregisterHostname is called, and if so, stop the mDNS
+ // service at that time (see Bug 1569955.)
+ if (!mSharedMDNSService) {
+ std::ostringstream o;
+ char buffer[16];
+ for (auto& addr : addrs) {
+ if (addr.localAddr().addr.ip_version == NR_IPV4 &&
+ !nr_transport_addr_is_loopback(&addr.localAddr().addr)) {
+ nr_transport_addr_get_addrstring(&addr.localAddr().addr, buffer, 16);
+ o << buffer << ";";
+ }
+ }
+ std::string addrstring = o.str();
+ if (!addrstring.empty()) {
+ mSharedMDNSService = new MDNSServiceWrapper(addrstring);
+ }
+ }
+
+ // send the new addresses back to the child
+ Unused << SendOnStunAddrsAvailable(addrs);
+}
+
+void StunAddrsRequestParent::OnQueryComplete_m(
+ const nsACString& hostname, const Maybe<nsCString>& address) {
+ ASSERT_ON_THREAD(mMainThread);
+
+ if (mIPCClosed) {
+ // nothing to do: child probably crashed
+ return;
+ }
+
+ // send the hostname and address back to the child
+ Unused << SendOnMDNSQueryComplete(hostname, address);
+}
+
+StaticRefPtr<StunAddrsRequestParent::MDNSServiceWrapper>
+ StunAddrsRequestParent::mSharedMDNSService;
+
+NS_IMPL_ADDREF(StunAddrsRequestParent)
+NS_IMPL_RELEASE(StunAddrsRequestParent)
+
+StunAddrsRequestParent::MDNSServiceWrapper::MDNSServiceWrapper(
+ const std::string& ifaddr)
+ : ifaddr(ifaddr) {}
+
+void StunAddrsRequestParent::MDNSServiceWrapper::RegisterHostname(
+ const char* hostname, const char* address) {
+ StartIfRequired();
+ if (mMDNSService) {
+ mdns_service_register_hostname(mMDNSService, hostname, address);
+ }
+}
+
+void StunAddrsRequestParent::MDNSServiceWrapper::QueryHostname(
+ void* data, const char* hostname) {
+ StartIfRequired();
+ if (mMDNSService) {
+ mdns_service_query_hostname(mMDNSService, data, mdns_service_resolved,
+ mdns_service_timedout, hostname);
+ }
+}
+
+void StunAddrsRequestParent::MDNSServiceWrapper::UnregisterHostname(
+ const char* hostname) {
+ StartIfRequired();
+ if (mMDNSService) {
+ mdns_service_unregister_hostname(mMDNSService, hostname);
+ }
+}
+
+StunAddrsRequestParent::MDNSServiceWrapper::~MDNSServiceWrapper() {
+ if (mMDNSService) {
+ mdns_service_stop(mMDNSService);
+ mMDNSService = nullptr;
+ }
+}
+
+void StunAddrsRequestParent::MDNSServiceWrapper::StartIfRequired() {
+ if (!mMDNSService) {
+ mMDNSService = mdns_service_start(ifaddr.c_str());
+ }
+}
+
+NS_IMPL_ADDREF(StunAddrsRequestParent::MDNSServiceWrapper)
+NS_IMPL_RELEASE(StunAddrsRequestParent::MDNSServiceWrapper)
+
+} // namespace mozilla::net