summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/rtc_base/async_resolver.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/libwebrtc/rtc_base/async_resolver.cc
parentInitial commit. (diff)
downloadfirefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz
firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/rtc_base/async_resolver.cc')
-rw-r--r--third_party/libwebrtc/rtc_base/async_resolver.cc239
1 files changed, 239 insertions, 0 deletions
diff --git a/third_party/libwebrtc/rtc_base/async_resolver.cc b/third_party/libwebrtc/rtc_base/async_resolver.cc
new file mode 100644
index 0000000000..7c1a6fe78d
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/async_resolver.cc
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2008 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/async_resolver.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "absl/strings/string_view.h"
+#include "api/ref_counted_base.h"
+#include "rtc_base/synchronization/mutex.h"
+#include "rtc_base/thread_annotations.h"
+
+#if defined(WEBRTC_WIN)
+#include <ws2spi.h>
+#include <ws2tcpip.h>
+
+#include "rtc_base/win32.h"
+#endif
+#if defined(WEBRTC_POSIX) && !defined(__native_client__)
+#if defined(WEBRTC_ANDROID)
+#include "rtc_base/ifaddrs_android.h"
+#else
+#include <ifaddrs.h>
+#endif
+#endif // defined(WEBRTC_POSIX) && !defined(__native_client__)
+
+#include "api/task_queue/task_queue_base.h"
+#include "rtc_base/ip_address.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/platform_thread.h"
+#include "rtc_base/task_queue.h"
+#include "rtc_base/third_party/sigslot/sigslot.h" // for signal_with_thread...
+
+#if defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
+#include <dispatch/dispatch.h>
+#endif
+
+namespace rtc {
+
+#if defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
+namespace {
+
+void GlobalGcdRunTask(void* context) {
+ std::unique_ptr<absl::AnyInvocable<void() &&>> task(
+ static_cast<absl::AnyInvocable<void() &&>*>(context));
+ std::move (*task)();
+}
+
+// Post a task into the system-defined global concurrent queue.
+void PostTaskToGlobalQueue(
+ std::unique_ptr<absl::AnyInvocable<void() &&>> task) {
+ dispatch_queue_global_t global_queue =
+ dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+ dispatch_async_f(global_queue, task.release(), &GlobalGcdRunTask);
+}
+
+} // namespace
+#endif
+
+int ResolveHostname(absl::string_view hostname,
+ int family,
+ std::vector<IPAddress>* addresses) {
+#ifdef __native_client__
+ RTC_DCHECK_NOTREACHED();
+ RTC_LOG(LS_WARNING) << "ResolveHostname() is not implemented for NaCl";
+ return -1;
+#else // __native_client__
+ if (!addresses) {
+ return -1;
+ }
+ addresses->clear();
+ struct addrinfo* result = nullptr;
+ struct addrinfo hints = {0};
+ hints.ai_family = family;
+ // `family` here will almost always be AF_UNSPEC, because `family` comes from
+ // AsyncResolver::addr_.family(), which comes from a SocketAddress constructed
+ // with a hostname. When a SocketAddress is constructed with a hostname, its
+ // family is AF_UNSPEC. However, if someday in the future we construct
+ // a SocketAddress with both a hostname and a family other than AF_UNSPEC,
+ // then it would be possible to get a specific family value here.
+
+ // The behavior of AF_UNSPEC is roughly "get both ipv4 and ipv6", as
+ // documented by the various operating systems:
+ // Linux: http://man7.org/linux/man-pages/man3/getaddrinfo.3.html
+ // Windows: https://msdn.microsoft.com/en-us/library/windows/desktop/
+ // ms738520(v=vs.85).aspx
+ // Mac: https://developer.apple.com/legacy/library/documentation/Darwin/
+ // Reference/ManPages/man3/getaddrinfo.3.html
+ // Android (source code, not documentation):
+ // https://android.googlesource.com/platform/bionic/+/
+ // 7e0bfb511e85834d7c6cb9631206b62f82701d60/libc/netbsd/net/getaddrinfo.c#1657
+ hints.ai_flags = AI_ADDRCONFIG;
+ int ret =
+ getaddrinfo(std::string(hostname).c_str(), nullptr, &hints, &result);
+ if (ret != 0) {
+ return ret;
+ }
+ struct addrinfo* cursor = result;
+ for (; cursor; cursor = cursor->ai_next) {
+ if (family == AF_UNSPEC || cursor->ai_family == family) {
+ IPAddress ip;
+ if (IPFromAddrInfo(cursor, &ip)) {
+ addresses->push_back(ip);
+ }
+ }
+ }
+ freeaddrinfo(result);
+ return 0;
+#endif // !__native_client__
+}
+
+struct AsyncResolver::State : public RefCountedBase {
+ webrtc::Mutex mutex;
+ enum class Status {
+ kLive,
+ kDead
+ } status RTC_GUARDED_BY(mutex) = Status::kLive;
+};
+
+AsyncResolver::AsyncResolver() : error_(-1), state_(new State) {}
+
+AsyncResolver::~AsyncResolver() {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+
+ // Ensure the thread isn't using a stale reference to the current task queue,
+ // or calling into ResolveDone post destruction.
+ webrtc::MutexLock lock(&state_->mutex);
+ state_->status = State::Status::kDead;
+}
+
+void RunResolution(void* obj) {
+ std::function<void()>* function_ptr =
+ static_cast<std::function<void()>*>(obj);
+ (*function_ptr)();
+ delete function_ptr;
+}
+
+void AsyncResolver::Start(const SocketAddress& addr) {
+ Start(addr, addr.family());
+}
+
+void AsyncResolver::Start(const SocketAddress& addr, int family) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK(!destroy_called_);
+ addr_ = addr;
+ auto thread_function =
+ [this, addr, family, caller_task_queue = webrtc::TaskQueueBase::Current(),
+ state = state_] {
+ std::vector<IPAddress> addresses;
+ int error = ResolveHostname(addr.hostname(), family, &addresses);
+ webrtc::MutexLock lock(&state->mutex);
+ if (state->status == State::Status::kLive) {
+ caller_task_queue->PostTask(
+ [this, error, addresses = std::move(addresses), state] {
+ bool live;
+ {
+ // ResolveDone can lead to instance destruction, so make sure
+ // we don't deadlock.
+ webrtc::MutexLock lock(&state->mutex);
+ live = state->status == State::Status::kLive;
+ }
+ if (live) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ ResolveDone(std::move(addresses), error);
+ }
+ });
+ }
+ };
+#if defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
+ PostTaskToGlobalQueue(
+ std::make_unique<absl::AnyInvocable<void() &&>>(thread_function));
+#else
+ PlatformThread::SpawnDetached(std::move(thread_function), "AsyncResolver");
+#endif
+}
+
+bool AsyncResolver::GetResolvedAddress(int family, SocketAddress* addr) const {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK(!destroy_called_);
+ if (error_ != 0 || addresses_.empty())
+ return false;
+
+ *addr = addr_;
+ for (size_t i = 0; i < addresses_.size(); ++i) {
+ if (family == addresses_[i].family()) {
+ addr->SetResolvedIP(addresses_[i]);
+ return true;
+ }
+ }
+ return false;
+}
+
+int AsyncResolver::GetError() const {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK(!destroy_called_);
+ return error_;
+}
+
+void AsyncResolver::Destroy(bool wait) {
+ // Some callers have trouble guaranteeing that Destroy is called on the
+ // sequence guarded by `sequence_checker_`.
+ // RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK(!destroy_called_);
+ destroy_called_ = true;
+ MaybeSelfDestruct();
+}
+
+const std::vector<IPAddress>& AsyncResolver::addresses() const {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK(!destroy_called_);
+ return addresses_;
+}
+
+void AsyncResolver::ResolveDone(std::vector<IPAddress> addresses, int error) {
+ addresses_ = addresses;
+ error_ = error;
+ recursion_check_ = true;
+ SignalDone(this);
+ MaybeSelfDestruct();
+}
+
+void AsyncResolver::MaybeSelfDestruct() {
+ if (!recursion_check_) {
+ delete this;
+ } else {
+ recursion_check_ = false;
+ }
+}
+
+} // namespace rtc