1 /*
2 * Copyright 2020 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 #include "pc/connection_context.h"
12
13 #include <type_traits>
14 #include <utility>
15 #include <vector>
16
17 #include "api/transport/field_trial_based_config.h"
18 #include "media/base/media_engine.h"
19 #include "media/sctp/sctp_transport_factory.h"
20 #include "rtc_base/helpers.h"
21 #include "rtc_base/internal/default_socket_server.h"
22 #include "rtc_base/socket_server.h"
23 #include "rtc_base/time_utils.h"
24
25 namespace webrtc {
26
27 namespace {
28
MaybeStartNetworkThread(rtc::Thread * old_thread,std::unique_ptr<rtc::SocketFactory> & socket_factory_holder,std::unique_ptr<rtc::Thread> & thread_holder)29 rtc::Thread* MaybeStartNetworkThread(
30 rtc::Thread* old_thread,
31 std::unique_ptr<rtc::SocketFactory>& socket_factory_holder,
32 std::unique_ptr<rtc::Thread>& thread_holder) {
33 if (old_thread) {
34 return old_thread;
35 }
36 std::unique_ptr<rtc::SocketServer> socket_server =
37 rtc::CreateDefaultSocketServer();
38 thread_holder = std::make_unique<rtc::Thread>(socket_server.get());
39 socket_factory_holder = std::move(socket_server);
40
41 thread_holder->SetName("pc_network_thread", nullptr);
42 thread_holder->Start();
43 return thread_holder.get();
44 }
45
MaybeWrapThread(rtc::Thread * signaling_thread,bool & wraps_current_thread)46 rtc::Thread* MaybeWrapThread(rtc::Thread* signaling_thread,
47 bool& wraps_current_thread) {
48 wraps_current_thread = false;
49 if (signaling_thread) {
50 return signaling_thread;
51 }
52 auto this_thread = rtc::Thread::Current();
53 if (!this_thread) {
54 // If this thread isn't already wrapped by an rtc::Thread, create a
55 // wrapper and own it in this class.
56 this_thread = rtc::ThreadManager::Instance()->WrapCurrentThread();
57 wraps_current_thread = true;
58 }
59 return this_thread;
60 }
61
MaybeCreateSctpFactory(std::unique_ptr<SctpTransportFactoryInterface> factory,rtc::Thread * network_thread,const FieldTrialsView & field_trials)62 std::unique_ptr<SctpTransportFactoryInterface> MaybeCreateSctpFactory(
63 std::unique_ptr<SctpTransportFactoryInterface> factory,
64 rtc::Thread* network_thread,
65 const FieldTrialsView& field_trials) {
66 if (factory) {
67 return factory;
68 }
69 #ifdef WEBRTC_HAVE_SCTP
70 return std::make_unique<cricket::SctpTransportFactory>(network_thread);
71 #else
72 return nullptr;
73 #endif
74 }
75
76 } // namespace
77
78 // Static
Create(PeerConnectionFactoryDependencies * dependencies)79 rtc::scoped_refptr<ConnectionContext> ConnectionContext::Create(
80 PeerConnectionFactoryDependencies* dependencies) {
81 return rtc::scoped_refptr<ConnectionContext>(
82 new ConnectionContext(dependencies));
83 }
84
ConnectionContext(PeerConnectionFactoryDependencies * dependencies)85 ConnectionContext::ConnectionContext(
86 PeerConnectionFactoryDependencies* dependencies)
87 : network_thread_(MaybeStartNetworkThread(dependencies->network_thread,
88 owned_socket_factory_,
89 owned_network_thread_)),
90 worker_thread_(dependencies->worker_thread,
91 []() {
92 auto thread_holder = rtc::Thread::Create();
93 thread_holder->SetName("pc_worker_thread", nullptr);
94 thread_holder->Start();
95 return thread_holder;
96 }),
97 signaling_thread_(MaybeWrapThread(dependencies->signaling_thread,
98 wraps_current_thread_)),
99 trials_(dependencies->trials ? std::move(dependencies->trials)
100 : std::make_unique<FieldTrialBasedConfig>()),
101 media_engine_(std::move(dependencies->media_engine)),
102 network_monitor_factory_(
103 std::move(dependencies->network_monitor_factory)),
104 default_network_manager_(std::move(dependencies->network_manager)),
105 call_factory_(std::move(dependencies->call_factory)),
106 default_socket_factory_(std::move(dependencies->packet_socket_factory)),
107 sctp_factory_(
108 MaybeCreateSctpFactory(std::move(dependencies->sctp_factory),
109 network_thread(),
110 *trials_.get())) {
111 RTC_DCHECK_RUN_ON(signaling_thread_);
112 RTC_DCHECK(!(default_network_manager_ && network_monitor_factory_))
113 << "You can't set both network_manager and network_monitor_factory.";
114
115 signaling_thread_->AllowInvokesToThread(worker_thread());
116 signaling_thread_->AllowInvokesToThread(network_thread_);
117 worker_thread_->AllowInvokesToThread(network_thread_);
118 if (!network_thread_->IsCurrent()) {
119 // network_thread_->IsCurrent() == true means signaling_thread_ is
120 // network_thread_. In this case, no further action is required as
121 // signaling_thread_ can already invoke network_thread_.
122 network_thread_->PostTask(
__anon9978e9d60302null123 [thread = network_thread_, worker_thread = worker_thread_.get()] {
124 thread->DisallowBlockingCalls();
125 thread->DisallowAllInvokes();
126 if (worker_thread == thread) {
127 // In this case, worker_thread_ == network_thread_
128 thread->AllowInvokesToThread(thread);
129 }
130 });
131 }
132
133 rtc::InitRandom(rtc::Time32());
134
135 rtc::SocketFactory* socket_factory = dependencies->socket_factory;
136 if (socket_factory == nullptr) {
137 if (owned_socket_factory_) {
138 socket_factory = owned_socket_factory_.get();
139 } else {
140 // TODO(bugs.webrtc.org/13145): This case should be deleted. Either
141 // require that a PacketSocketFactory and NetworkManager always are
142 // injected (with no need to construct these default objects), or require
143 // that if a network_thread is injected, an approprite rtc::SocketServer
144 // should be injected too.
145 socket_factory = network_thread()->socketserver();
146 }
147 }
148 if (!default_network_manager_) {
149 // If network_monitor_factory_ is non-null, it will be used to create a
150 // network monitor while on the network thread.
151 default_network_manager_ = std::make_unique<rtc::BasicNetworkManager>(
152 network_monitor_factory_.get(), socket_factory, &field_trials());
153 }
154 if (!default_socket_factory_) {
155 default_socket_factory_ =
156 std::make_unique<rtc::BasicPacketSocketFactory>(socket_factory);
157 }
158 // Set warning levels on the threads, to give warnings when response
159 // may be slower than is expected of the thread.
160 // Since some of the threads may be the same, start with the least
161 // restrictive limits and end with the least permissive ones.
162 // This will give warnings for all cases.
163 signaling_thread_->SetDispatchWarningMs(100);
164 worker_thread_->SetDispatchWarningMs(30);
165 network_thread_->SetDispatchWarningMs(10);
166
167 if (media_engine_) {
168 // TODO(tommi): Change VoiceEngine to do ctor time initialization so that
169 // this isn't necessary.
__anon9978e9d60402null170 worker_thread_->BlockingCall([&] { media_engine_->Init(); });
171 }
172 }
173
~ConnectionContext()174 ConnectionContext::~ConnectionContext() {
175 RTC_DCHECK_RUN_ON(signaling_thread_);
176 worker_thread_->BlockingCall([&] {
177 RTC_DCHECK_RUN_ON(worker_thread());
178 // While `media_engine_` is const throughout the ConnectionContext's
179 // lifetime, it requires destruction to happen on the worker thread. Instead
180 // of marking the pointer as non-const, we live with this const_cast<> in
181 // the destructor.
182 const_cast<std::unique_ptr<cricket::MediaEngineInterface>&>(media_engine_)
183 .reset();
184 });
185
186 // Make sure `worker_thread()` and `signaling_thread()` outlive
187 // `default_socket_factory_` and `default_network_manager_`.
188 default_socket_factory_ = nullptr;
189 default_network_manager_ = nullptr;
190
191 if (wraps_current_thread_)
192 rtc::ThreadManager::Instance()->UnwrapCurrentThread();
193 }
194
195 } // namespace webrtc
196