1 /*
2 * Copyright (c) 2019 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 #include "test/peer_scenario/scenario_connection.h"
11
12 #include "absl/memory/memory.h"
13 #include "media/base/rtp_utils.h"
14 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
15 #include "p2p/client/basic_port_allocator.h"
16 #include "pc/jsep_transport_controller.h"
17 #include "pc/rtp_transport_internal.h"
18 #include "pc/session_description.h"
19
20 namespace webrtc {
21 class ScenarioIceConnectionImpl : public ScenarioIceConnection,
22 public sigslot::has_slots<>,
23 private JsepTransportController::Observer,
24 private RtpPacketSinkInterface {
25 public:
26 ScenarioIceConnectionImpl(test::NetworkEmulationManagerImpl* net,
27 IceConnectionObserver* observer);
28 ~ScenarioIceConnectionImpl() override;
29
30 void SendRtpPacket(rtc::ArrayView<const uint8_t> packet_view) override;
31 void SendRtcpPacket(rtc::ArrayView<const uint8_t> packet_view) override;
32
33 void SetRemoteSdp(SdpType type, const std::string& remote_sdp) override;
34 void SetLocalSdp(SdpType type, const std::string& local_sdp) override;
35
endpoint()36 EmulatedEndpoint* endpoint() override { return endpoint_; }
transport_description() const37 const cricket::TransportDescription& transport_description() const override {
38 return transport_description_;
39 }
40
41 private:
42 JsepTransportController::Config CreateJsepConfig();
43 bool OnTransportChanged(
44 const std::string& mid,
45 RtpTransportInternal* rtp_transport,
46 rtc::scoped_refptr<DtlsTransport> dtls_transport,
47 DataChannelTransportInterface* data_channel_transport) override;
48
49 void OnRtpPacket(const RtpPacketReceived& packet) override;
50 void OnCandidates(const std::string& mid,
51 const std::vector<cricket::Candidate>& candidates);
52
53 IceConnectionObserver* const observer_;
54 EmulatedEndpoint* const endpoint_;
55 EmulatedNetworkManagerInterface* const manager_;
56 rtc::Thread* const signaling_thread_;
57 rtc::Thread* const network_thread_;
58 rtc::scoped_refptr<rtc::RTCCertificate> const certificate_
59 RTC_GUARDED_BY(network_thread_);
60 cricket::TransportDescription const transport_description_
61 RTC_GUARDED_BY(signaling_thread_);
62 std::unique_ptr<cricket::BasicPortAllocator> port_allocator_
63 RTC_GUARDED_BY(network_thread_);
64 std::unique_ptr<JsepTransportController> jsep_controller_;
65 RtpTransportInternal* rtp_transport_ RTC_GUARDED_BY(network_thread_) =
66 nullptr;
67 std::unique_ptr<SessionDescriptionInterface> remote_description_
68 RTC_GUARDED_BY(signaling_thread_);
69 std::unique_ptr<SessionDescriptionInterface> local_description_
70 RTC_GUARDED_BY(signaling_thread_);
71 };
72
Create(webrtc::test::NetworkEmulationManagerImpl * net,IceConnectionObserver * observer)73 std::unique_ptr<ScenarioIceConnection> ScenarioIceConnection::Create(
74 webrtc::test::NetworkEmulationManagerImpl* net,
75 IceConnectionObserver* observer) {
76 return std::make_unique<ScenarioIceConnectionImpl>(net, observer);
77 }
78
ScenarioIceConnectionImpl(test::NetworkEmulationManagerImpl * net,IceConnectionObserver * observer)79 ScenarioIceConnectionImpl::ScenarioIceConnectionImpl(
80 test::NetworkEmulationManagerImpl* net,
81 IceConnectionObserver* observer)
82 : observer_(observer),
83 endpoint_(net->CreateEndpoint(EmulatedEndpointConfig())),
84 manager_(net->CreateEmulatedNetworkManagerInterface({endpoint_})),
85 signaling_thread_(rtc::Thread::Current()),
86 network_thread_(manager_->network_thread()),
87 certificate_(rtc::RTCCertificate::Create(
88 rtc::SSLIdentity::Create("", ::rtc::KT_DEFAULT))),
89 transport_description_(
90 /*transport_options*/ {},
91 rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH),
92 rtc::CreateRandomString(cricket::ICE_PWD_LENGTH),
93 cricket::IceMode::ICEMODE_FULL,
94 cricket::ConnectionRole::CONNECTIONROLE_PASSIVE,
95 rtc::SSLFingerprint::CreateFromCertificate(*certificate_.get())
96 .get()),
97 port_allocator_(
98 new cricket::BasicPortAllocator(manager_->network_manager())),
99 jsep_controller_(
100 new JsepTransportController(signaling_thread_,
101 network_thread_,
102 port_allocator_.get(),
103 /*async_resolver_factory*/ nullptr,
104 CreateJsepConfig())) {
__anonbd0cb4c70102null105 network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
106 RTC_DCHECK_RUN_ON(network_thread_);
107 uint32_t flags = cricket::PORTALLOCATOR_DISABLE_TCP;
108 port_allocator_->set_flags(port_allocator_->flags() | flags);
109 port_allocator_->Initialize();
110 RTC_CHECK(port_allocator_->SetConfiguration(/*stun_servers*/ {},
111 /*turn_servers*/ {}, 0,
112 webrtc::NO_PRUNE));
113 jsep_controller_->SetLocalCertificate(certificate_);
114 });
115 }
116
~ScenarioIceConnectionImpl()117 ScenarioIceConnectionImpl::~ScenarioIceConnectionImpl() {
118 network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
119 RTC_DCHECK_RUN_ON(network_thread_);
120 jsep_controller_.reset();
121 port_allocator_.reset();
122 rtp_transport_ = nullptr;
123 });
124 }
125
CreateJsepConfig()126 JsepTransportController::Config ScenarioIceConnectionImpl::CreateJsepConfig() {
127 JsepTransportController::Config config;
128 config.transport_observer = this;
129 config.bundle_policy =
130 PeerConnectionInterface::BundlePolicy::kBundlePolicyMaxBundle;
131 config.rtcp_handler = [this](const rtc::CopyOnWriteBuffer& packet,
132 int64_t packet_time_us) {
133 RTC_DCHECK_RUN_ON(network_thread_);
134 observer_->OnPacketReceived(packet);
135 };
136 return config;
137 }
138
SendRtpPacket(rtc::ArrayView<const uint8_t> packet_view)139 void ScenarioIceConnectionImpl::SendRtpPacket(
140 rtc::ArrayView<const uint8_t> packet_view) {
141 rtc::CopyOnWriteBuffer packet(packet_view.data(), packet_view.size(),
142 ::cricket::kMaxRtpPacketLen);
143 network_thread_->PostTask(
144 RTC_FROM_HERE, [this, packet = std::move(packet)]() mutable {
145 RTC_DCHECK_RUN_ON(network_thread_);
146 if (rtp_transport_ != nullptr)
147 rtp_transport_->SendRtpPacket(&packet, rtc::PacketOptions(),
148 cricket::PF_SRTP_BYPASS);
149 });
150 }
151
SendRtcpPacket(rtc::ArrayView<const uint8_t> packet_view)152 void ScenarioIceConnectionImpl::SendRtcpPacket(
153 rtc::ArrayView<const uint8_t> packet_view) {
154 rtc::CopyOnWriteBuffer packet(packet_view.data(), packet_view.size(),
155 ::cricket::kMaxRtpPacketLen);
156 network_thread_->PostTask(
157 RTC_FROM_HERE, [this, packet = std::move(packet)]() mutable {
158 RTC_DCHECK_RUN_ON(network_thread_);
159 if (rtp_transport_ != nullptr)
160 rtp_transport_->SendRtcpPacket(&packet, rtc::PacketOptions(),
161 cricket::PF_SRTP_BYPASS);
162 });
163 }
SetRemoteSdp(SdpType type,const std::string & remote_sdp)164 void ScenarioIceConnectionImpl::SetRemoteSdp(SdpType type,
165 const std::string& remote_sdp) {
166 RTC_DCHECK_RUN_ON(signaling_thread_);
167 remote_description_ = webrtc::CreateSessionDescription(type, remote_sdp);
168 jsep_controller_->SignalIceCandidatesGathered.connect(
169 this, &ScenarioIceConnectionImpl::OnCandidates);
170 auto res = jsep_controller_->SetRemoteDescription(
171 remote_description_->GetType(), remote_description_->description());
172 RTC_CHECK(res.ok()) << res.message();
173 RtpDemuxerCriteria criteria;
174 for (const auto& content : remote_description_->description()->contents()) {
175 if (content.media_description()->as_audio()) {
176 for (const auto& codec :
177 content.media_description()->as_audio()->codecs()) {
178 criteria.payload_types.insert(codec.id);
179 }
180 }
181 if (content.media_description()->as_video()) {
182 for (const auto& codec :
183 content.media_description()->as_video()->codecs()) {
184 criteria.payload_types.insert(codec.id);
185 }
186 }
187 }
188
189 network_thread_->PostTask(RTC_FROM_HERE, [this, criteria]() {
190 RTC_DCHECK_RUN_ON(network_thread_);
191 RTC_DCHECK(rtp_transport_);
192 rtp_transport_->RegisterRtpDemuxerSink(criteria, this);
193 });
194 }
195
SetLocalSdp(SdpType type,const std::string & local_sdp)196 void ScenarioIceConnectionImpl::SetLocalSdp(SdpType type,
197 const std::string& local_sdp) {
198 RTC_DCHECK_RUN_ON(signaling_thread_);
199 local_description_ = webrtc::CreateSessionDescription(type, local_sdp);
200 auto res = jsep_controller_->SetLocalDescription(
201 local_description_->GetType(), local_description_->description());
202 RTC_CHECK(res.ok()) << res.message();
203 jsep_controller_->MaybeStartGathering();
204 }
205
OnTransportChanged(const std::string & mid,RtpTransportInternal * rtp_transport,rtc::scoped_refptr<DtlsTransport> dtls_transport,DataChannelTransportInterface * data_channel_transport)206 bool ScenarioIceConnectionImpl::OnTransportChanged(
207 const std::string& mid,
208 RtpTransportInternal* rtp_transport,
209 rtc::scoped_refptr<DtlsTransport> dtls_transport,
210 DataChannelTransportInterface* data_channel_transport) {
211 RTC_DCHECK_RUN_ON(network_thread_);
212 if (rtp_transport == nullptr) {
213 rtp_transport_->UnregisterRtpDemuxerSink(this);
214 } else {
215 RTC_DCHECK(rtp_transport_ == nullptr || rtp_transport_ == rtp_transport);
216 if (rtp_transport_ != rtp_transport) {
217 rtp_transport_ = rtp_transport;
218 }
219 RtpDemuxerCriteria criteria;
220 criteria.mid = mid;
221 rtp_transport_->RegisterRtpDemuxerSink(criteria, this);
222 }
223 return true;
224 }
225
OnRtpPacket(const RtpPacketReceived & packet)226 void ScenarioIceConnectionImpl::OnRtpPacket(const RtpPacketReceived& packet) {
227 RTC_DCHECK_RUN_ON(network_thread_);
228 observer_->OnPacketReceived(packet.Buffer());
229 }
230
OnCandidates(const std::string & mid,const std::vector<cricket::Candidate> & candidates)231 void ScenarioIceConnectionImpl::OnCandidates(
232 const std::string& mid,
233 const std::vector<cricket::Candidate>& candidates) {
234 RTC_DCHECK_RUN_ON(signaling_thread_);
235 observer_->OnIceCandidates(mid, candidates);
236 }
237
238 } // namespace webrtc
239