• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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