From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../transport/ipc/StunAddrsRequestParent.cpp | 262 +++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 dom/media/webrtc/transport/ipc/StunAddrsRequestParent.cpp (limited to 'dom/media/webrtc/transport/ipc/StunAddrsRequestParent.cpp') 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(cb); + self->OnQueryComplete(nsCString(hostname), Some(nsCString(addr))); +} + +void mdns_service_timedout(void* cb, const char* hostname) { + StunAddrsRequestParent* self = static_cast(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(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& address) { + RUN_ON_THREAD(mMainThread, + WrapRunnable(RefPtr(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(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& 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::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 -- cgit v1.2.3