blob: 5155b0f52862a6ed6cbb583eeae059da61b247d2 [file] [log] [blame]
Harald Alvestrand985310e2021-10-01 15:11:17 +00001/*
2 * Copyright 2021 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef API_WRAPPING_ASYNC_DNS_RESOLVER_H_
12#define API_WRAPPING_ASYNC_DNS_RESOLVER_H_
13
14#include <functional>
15#include <memory>
Sameer Vijaykarb787e262022-08-11 11:52:57 +020016#include <utility>
Harald Alvestrand985310e2021-10-01 15:11:17 +000017
18#include "absl/memory/memory.h"
19#include "api/async_dns_resolver.h"
20#include "api/sequence_checker.h"
21#include "rtc_base/async_resolver.h"
22#include "rtc_base/async_resolver_interface.h"
23#include "rtc_base/checks.h"
24#include "rtc_base/socket_address.h"
25#include "rtc_base/third_party/sigslot/sigslot.h"
26#include "rtc_base/thread_annotations.h"
27
28// This file defines a DNS resolver that wraps an old-style
29// AsyncResolver.
30// It is part of the conversion to the newer interface, and will go away
31// once conversion is finished.
32// TODO(bugs.webrtc.org/12598): Delete this API.
33
34namespace webrtc {
35
36class WrappingAsyncDnsResolver;
37
38class RTC_EXPORT WrappingAsyncDnsResolverResult
39 : public AsyncDnsResolverResult {
40 public:
41 explicit WrappingAsyncDnsResolverResult(WrappingAsyncDnsResolver* owner)
42 : owner_(owner) {}
43 ~WrappingAsyncDnsResolverResult() {}
44
45 // Note: Inline declaration not possible, since it refers to
46 // WrappingAsyncDnsResolver.
47 bool GetResolvedAddress(int family, rtc::SocketAddress* addr) const override;
48 int GetError() const override;
49
50 private:
51 WrappingAsyncDnsResolver* const owner_;
52};
53
54class RTC_EXPORT WrappingAsyncDnsResolver : public AsyncDnsResolverInterface,
55 public sigslot::has_slots<> {
56 public:
57 explicit WrappingAsyncDnsResolver(rtc::AsyncResolverInterface* wrapped)
58 : wrapped_(absl::WrapUnique(wrapped)), result_(this) {}
59
60 ~WrappingAsyncDnsResolver() override {
61 // Workaround to get around the fact that sigslot-using objects can't be
62 // destroyed from within their callback: Alert class users early.
63 // TODO(bugs.webrtc.org/12651): Delete this class once the sigslot users are
64 // gone.
65 RTC_CHECK(!within_resolve_result_);
66 wrapped_.release()->Destroy(false);
67 }
68
69 void Start(const rtc::SocketAddress& addr,
70 std::function<void()> callback) override {
71 RTC_DCHECK_RUN_ON(&sequence_checker_);
Sameer Vijaykarb787e262022-08-11 11:52:57 +020072 PrepareToResolve(std::move(callback));
Harald Alvestrand985310e2021-10-01 15:11:17 +000073 wrapped_->Start(addr);
74 }
75
Sameer Vijaykarb787e262022-08-11 11:52:57 +020076 void Start(const rtc::SocketAddress& addr,
77 int family,
78 std::function<void()> callback) override {
79 RTC_DCHECK_RUN_ON(&sequence_checker_);
80 PrepareToResolve(std::move(callback));
81 wrapped_->Start(addr, family);
82 }
83
Harald Alvestrand985310e2021-10-01 15:11:17 +000084 const AsyncDnsResolverResult& result() const override {
85 RTC_DCHECK_RUN_ON(&sequence_checker_);
86 RTC_DCHECK_EQ(State::kResolved, state_);
87 return result_;
88 }
89
90 private:
91 enum class State { kNotStarted, kStarted, kResolved };
92
93 friend class WrappingAsyncDnsResolverResult;
94 // For use by WrappingAsyncDnsResolverResult
95 rtc::AsyncResolverInterface* wrapped() const {
96 RTC_DCHECK_RUN_ON(&sequence_checker_);
97 return wrapped_.get();
98 }
99
Sameer Vijaykarb787e262022-08-11 11:52:57 +0200100 void PrepareToResolve(std::function<void()> callback) {
101 RTC_DCHECK_RUN_ON(&sequence_checker_);
102 RTC_DCHECK_EQ(State::kNotStarted, state_);
103 state_ = State::kStarted;
104 callback_ = std::move(callback);
105 wrapped_->SignalDone.connect(this,
106 &WrappingAsyncDnsResolver::OnResolveResult);
107 }
108
Harald Alvestrand985310e2021-10-01 15:11:17 +0000109 void OnResolveResult(rtc::AsyncResolverInterface* ref) {
110 RTC_DCHECK_RUN_ON(&sequence_checker_);
111 RTC_DCHECK(state_ == State::kStarted);
112 RTC_DCHECK_EQ(ref, wrapped_.get());
113 state_ = State::kResolved;
114 within_resolve_result_ = true;
115 callback_();
116 within_resolve_result_ = false;
117 }
118
119 // The class variables need to be accessed on a single thread.
120 SequenceChecker sequence_checker_;
121 std::function<void()> callback_ RTC_GUARDED_BY(sequence_checker_);
122 std::unique_ptr<rtc::AsyncResolverInterface> wrapped_
123 RTC_GUARDED_BY(sequence_checker_);
124 State state_ RTC_GUARDED_BY(sequence_checker_) = State::kNotStarted;
125 WrappingAsyncDnsResolverResult result_ RTC_GUARDED_BY(sequence_checker_);
126 bool within_resolve_result_ RTC_GUARDED_BY(sequence_checker_) = false;
127};
128
129} // namespace webrtc
130
131#endif // API_WRAPPING_ASYNC_DNS_RESOLVER_H_