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 <string>
14 #include <type_traits>
15 #include <utility>
16 
17 #include "api/transport/field_trial_based_config.h"
18 #include "media/base/rtp_data_engine.h"
19 #include "rtc_base/helpers.h"
20 #include "rtc_base/ref_counted_object.h"
21 #include "rtc_base/task_utils/to_queued_task.h"
22 #include "rtc_base/time_utils.h"
23 
24 namespace webrtc {
25 
26 namespace {
27 
MaybeStartThread(rtc::Thread * old_thread,const std::string & thread_name,bool with_socket_server,std::unique_ptr<rtc::Thread> & thread_holder)28 rtc::Thread* MaybeStartThread(rtc::Thread* old_thread,
29                               const std::string& thread_name,
30                               bool with_socket_server,
31                               std::unique_ptr<rtc::Thread>& thread_holder) {
32   if (old_thread) {
33     return old_thread;
34   }
35   if (with_socket_server) {
36     thread_holder = rtc::Thread::CreateWithSocketServer();
37   } else {
38     thread_holder = rtc::Thread::Create();
39   }
40   thread_holder->SetName(thread_name, nullptr);
41   thread_holder->Start();
42   return thread_holder.get();
43 }
44 
MaybeWrapThread(rtc::Thread * signaling_thread,bool & wraps_current_thread)45 rtc::Thread* MaybeWrapThread(rtc::Thread* signaling_thread,
46                              bool& wraps_current_thread) {
47   wraps_current_thread = false;
48   if (signaling_thread) {
49     return signaling_thread;
50   }
51   auto this_thread = rtc::Thread::Current();
52   if (!this_thread) {
53     // If this thread isn't already wrapped by an rtc::Thread, create a
54     // wrapper and own it in this class.
55     this_thread = rtc::ThreadManager::Instance()->WrapCurrentThread();
56     wraps_current_thread = true;
57   }
58   return this_thread;
59 }
60 
MaybeCreateSctpFactory(std::unique_ptr<SctpTransportFactoryInterface> factory,rtc::Thread * network_thread)61 std::unique_ptr<SctpTransportFactoryInterface> MaybeCreateSctpFactory(
62     std::unique_ptr<SctpTransportFactoryInterface> factory,
63     rtc::Thread* network_thread) {
64   if (factory) {
65     return factory;
66   }
67 #ifdef WEBRTC_HAVE_SCTP
68   return std::make_unique<cricket::SctpTransportFactory>(network_thread);
69 #else
70   return nullptr;
71 #endif
72 }
73 
74 }  // namespace
75 
76 // Static
Create(PeerConnectionFactoryDependencies * dependencies)77 rtc::scoped_refptr<ConnectionContext> ConnectionContext::Create(
78     PeerConnectionFactoryDependencies* dependencies) {
79   return new rtc::RefCountedObject<ConnectionContext>(dependencies);
80 }
81 
ConnectionContext(PeerConnectionFactoryDependencies * dependencies)82 ConnectionContext::ConnectionContext(
83     PeerConnectionFactoryDependencies* dependencies)
84     : network_thread_(MaybeStartThread(dependencies->network_thread,
85                                        "pc_network_thread",
86                                        true,
87                                        owned_network_thread_)),
88       worker_thread_(MaybeStartThread(dependencies->worker_thread,
89                                       "pc_worker_thread",
90                                       false,
91                                       owned_worker_thread_)),
92       signaling_thread_(MaybeWrapThread(dependencies->signaling_thread,
93                                         wraps_current_thread_)),
94       network_monitor_factory_(
95           std::move(dependencies->network_monitor_factory)),
96       call_factory_(std::move(dependencies->call_factory)),
97       sctp_factory_(
98           MaybeCreateSctpFactory(std::move(dependencies->sctp_factory),
99                                  network_thread())),
100       trials_(dependencies->trials
101                   ? std::move(dependencies->trials)
102                   : std::make_unique<FieldTrialBasedConfig>()) {
103   signaling_thread_->AllowInvokesToThread(worker_thread_);
104   signaling_thread_->AllowInvokesToThread(network_thread_);
105   worker_thread_->AllowInvokesToThread(network_thread_);
106   if (network_thread_->IsCurrent()) {
107     network_thread_->DisallowAllInvokes();
108   } else {
109     network_thread_->PostTask(ToQueuedTask([thread = network_thread_] {
110       thread->DisallowBlockingCalls();
111       thread->DisallowAllInvokes();
112     }));
113   }
114 
115   RTC_DCHECK_RUN_ON(signaling_thread_);
116   rtc::InitRandom(rtc::Time32());
117 
118   // If network_monitor_factory_ is non-null, it will be used to create a
119   // network monitor while on the network thread.
120   default_network_manager_ = std::make_unique<rtc::BasicNetworkManager>(
121       network_monitor_factory_.get());
122 
123   default_socket_factory_ =
124       std::make_unique<rtc::BasicPacketSocketFactory>(network_thread());
125 
126   worker_thread_->Invoke<void>(RTC_FROM_HERE, [&]() {
127     channel_manager_ = cricket::ChannelManager::Create(
128         std::move(dependencies->media_engine),
129         std::make_unique<cricket::RtpDataEngine>(), /*enable_rtx=*/true,
130         worker_thread(), network_thread());
131   });
132 
133   // Set warning levels on the threads, to give warnings when response
134   // may be slower than is expected of the thread.
135   // Since some of the threads may be the same, start with the least
136   // restrictive limits and end with the least permissive ones.
137   // This will give warnings for all cases.
138   signaling_thread_->SetDispatchWarningMs(100);
139   worker_thread_->SetDispatchWarningMs(30);
140   network_thread_->SetDispatchWarningMs(10);
141 }
142 
~ConnectionContext()143 ConnectionContext::~ConnectionContext() {
144   RTC_DCHECK_RUN_ON(signaling_thread_);
145   worker_thread_->Invoke<void>(RTC_FROM_HERE,
146                                [&]() { channel_manager_.reset(nullptr); });
147 
148   // Make sure |worker_thread()| and |signaling_thread()| outlive
149   // |default_socket_factory_| and |default_network_manager_|.
150   default_socket_factory_ = nullptr;
151   default_network_manager_ = nullptr;
152 
153   if (wraps_current_thread_)
154     rtc::ThreadManager::Instance()->UnwrapCurrentThread();
155 }
156 
channel_manager() const157 cricket::ChannelManager* ConnectionContext::channel_manager() const {
158   return channel_manager_.get();
159 }
160 
161 }  // namespace webrtc
162