1 /*
2 * Copyright 2017 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/peer_connection_wrapper.h"
12
13 #include <stdint.h>
14
15 #include <utility>
16 #include <vector>
17
18 #include "api/function_view.h"
19 #include "api/set_remote_description_observer_interface.h"
20 #include "pc/sdp_utils.h"
21 #include "pc/test/fake_video_track_source.h"
22 #include "rtc_base/checks.h"
23 #include "rtc_base/gunit.h"
24 #include "rtc_base/logging.h"
25 #include "test/gtest.h"
26
27 namespace webrtc {
28
29 using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
30
31 namespace {
32 const uint32_t kDefaultTimeout = 10000U;
33 }
34
PeerConnectionWrapper(rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory,rtc::scoped_refptr<PeerConnectionInterface> pc,std::unique_ptr<MockPeerConnectionObserver> observer)35 PeerConnectionWrapper::PeerConnectionWrapper(
36 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory,
37 rtc::scoped_refptr<PeerConnectionInterface> pc,
38 std::unique_ptr<MockPeerConnectionObserver> observer)
39 : pc_factory_(std::move(pc_factory)),
40 observer_(std::move(observer)),
41 pc_(std::move(pc)) {
42 RTC_DCHECK(pc_factory_);
43 RTC_DCHECK(pc_);
44 RTC_DCHECK(observer_);
45 observer_->SetPeerConnectionInterface(pc_.get());
46 }
47
~PeerConnectionWrapper()48 PeerConnectionWrapper::~PeerConnectionWrapper() {
49 if (pc_)
50 pc_->Close();
51 }
52
pc_factory()53 PeerConnectionFactoryInterface* PeerConnectionWrapper::pc_factory() {
54 return pc_factory_.get();
55 }
56
pc()57 PeerConnectionInterface* PeerConnectionWrapper::pc() {
58 return pc_.get();
59 }
60
observer()61 MockPeerConnectionObserver* PeerConnectionWrapper::observer() {
62 return observer_.get();
63 }
64
65 std::unique_ptr<SessionDescriptionInterface>
CreateOffer()66 PeerConnectionWrapper::CreateOffer() {
67 return CreateOffer(RTCOfferAnswerOptions());
68 }
69
CreateOffer(const PeerConnectionInterface::RTCOfferAnswerOptions & options,std::string * error_out)70 std::unique_ptr<SessionDescriptionInterface> PeerConnectionWrapper::CreateOffer(
71 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
72 std::string* error_out) {
73 return CreateSdp(
74 [this, options](CreateSessionDescriptionObserver* observer) {
75 pc()->CreateOffer(observer, options);
76 },
77 error_out);
78 }
79
80 std::unique_ptr<SessionDescriptionInterface>
CreateOfferAndSetAsLocal()81 PeerConnectionWrapper::CreateOfferAndSetAsLocal() {
82 return CreateOfferAndSetAsLocal(RTCOfferAnswerOptions());
83 }
84
85 std::unique_ptr<SessionDescriptionInterface>
CreateOfferAndSetAsLocal(const PeerConnectionInterface::RTCOfferAnswerOptions & options)86 PeerConnectionWrapper::CreateOfferAndSetAsLocal(
87 const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
88 auto offer = CreateOffer(options);
89 if (!offer) {
90 return nullptr;
91 }
92 EXPECT_TRUE(SetLocalDescription(CloneSessionDescription(offer.get())));
93 return offer;
94 }
95
96 std::unique_ptr<SessionDescriptionInterface>
CreateAnswer()97 PeerConnectionWrapper::CreateAnswer() {
98 return CreateAnswer(RTCOfferAnswerOptions());
99 }
100
101 std::unique_ptr<SessionDescriptionInterface>
CreateAnswer(const PeerConnectionInterface::RTCOfferAnswerOptions & options,std::string * error_out)102 PeerConnectionWrapper::CreateAnswer(
103 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
104 std::string* error_out) {
105 return CreateSdp(
106 [this, options](CreateSessionDescriptionObserver* observer) {
107 pc()->CreateAnswer(observer, options);
108 },
109 error_out);
110 }
111
112 std::unique_ptr<SessionDescriptionInterface>
CreateAnswerAndSetAsLocal()113 PeerConnectionWrapper::CreateAnswerAndSetAsLocal() {
114 return CreateAnswerAndSetAsLocal(RTCOfferAnswerOptions());
115 }
116
117 std::unique_ptr<SessionDescriptionInterface>
CreateAnswerAndSetAsLocal(const PeerConnectionInterface::RTCOfferAnswerOptions & options)118 PeerConnectionWrapper::CreateAnswerAndSetAsLocal(
119 const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
120 auto answer = CreateAnswer(options);
121 if (!answer) {
122 return nullptr;
123 }
124 EXPECT_TRUE(SetLocalDescription(CloneSessionDescription(answer.get())));
125 return answer;
126 }
127
128 std::unique_ptr<SessionDescriptionInterface>
CreateRollback()129 PeerConnectionWrapper::CreateRollback() {
130 return CreateSessionDescription(SdpType::kRollback, "");
131 }
132
CreateSdp(rtc::FunctionView<void (CreateSessionDescriptionObserver *)> fn,std::string * error_out)133 std::unique_ptr<SessionDescriptionInterface> PeerConnectionWrapper::CreateSdp(
134 rtc::FunctionView<void(CreateSessionDescriptionObserver*)> fn,
135 std::string* error_out) {
136 auto observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
137 fn(observer.get());
138 EXPECT_EQ_WAIT(true, observer->called(), kDefaultTimeout);
139 if (error_out && !observer->result()) {
140 *error_out = observer->error();
141 }
142 return observer->MoveDescription();
143 }
144
SetLocalDescription(std::unique_ptr<SessionDescriptionInterface> desc,std::string * error_out)145 bool PeerConnectionWrapper::SetLocalDescription(
146 std::unique_ptr<SessionDescriptionInterface> desc,
147 std::string* error_out) {
148 return SetSdp(
149 [this, &desc](SetSessionDescriptionObserver* observer) {
150 pc()->SetLocalDescription(observer, desc.release());
151 },
152 error_out);
153 }
154
SetRemoteDescription(std::unique_ptr<SessionDescriptionInterface> desc,std::string * error_out)155 bool PeerConnectionWrapper::SetRemoteDescription(
156 std::unique_ptr<SessionDescriptionInterface> desc,
157 std::string* error_out) {
158 return SetSdp(
159 [this, &desc](SetSessionDescriptionObserver* observer) {
160 pc()->SetRemoteDescription(observer, desc.release());
161 },
162 error_out);
163 }
164
SetRemoteDescription(std::unique_ptr<SessionDescriptionInterface> desc,RTCError * error_out)165 bool PeerConnectionWrapper::SetRemoteDescription(
166 std::unique_ptr<SessionDescriptionInterface> desc,
167 RTCError* error_out) {
168 auto observer = rtc::make_ref_counted<FakeSetRemoteDescriptionObserver>();
169 pc()->SetRemoteDescription(std::move(desc), observer);
170 EXPECT_EQ_WAIT(true, observer->called(), kDefaultTimeout);
171 bool ok = observer->error().ok();
172 if (error_out)
173 *error_out = std::move(observer->error());
174 return ok;
175 }
176
SetSdp(rtc::FunctionView<void (SetSessionDescriptionObserver *)> fn,std::string * error_out)177 bool PeerConnectionWrapper::SetSdp(
178 rtc::FunctionView<void(SetSessionDescriptionObserver*)> fn,
179 std::string* error_out) {
180 auto observer = rtc::make_ref_counted<MockSetSessionDescriptionObserver>();
181 fn(observer.get());
182 EXPECT_EQ_WAIT(true, observer->called(), kDefaultTimeout);
183 if (error_out && !observer->result()) {
184 *error_out = observer->error();
185 }
186 return observer->result();
187 }
188
ExchangeOfferAnswerWith(PeerConnectionWrapper * answerer)189 bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
190 PeerConnectionWrapper* answerer) {
191 return ExchangeOfferAnswerWith(answerer, RTCOfferAnswerOptions(),
192 RTCOfferAnswerOptions());
193 }
194
ExchangeOfferAnswerWith(PeerConnectionWrapper * answerer,const PeerConnectionInterface::RTCOfferAnswerOptions & offer_options,const PeerConnectionInterface::RTCOfferAnswerOptions & answer_options)195 bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
196 PeerConnectionWrapper* answerer,
197 const PeerConnectionInterface::RTCOfferAnswerOptions& offer_options,
198 const PeerConnectionInterface::RTCOfferAnswerOptions& answer_options) {
199 RTC_DCHECK(answerer);
200 if (answerer == this) {
201 RTC_LOG(LS_ERROR) << "Cannot exchange offer/answer with ourself!";
202 return false;
203 }
204 auto offer = CreateOffer(offer_options);
205 EXPECT_TRUE(offer);
206 if (!offer) {
207 return false;
208 }
209 bool set_local_offer =
210 SetLocalDescription(CloneSessionDescription(offer.get()));
211 EXPECT_TRUE(set_local_offer);
212 if (!set_local_offer) {
213 return false;
214 }
215 bool set_remote_offer = answerer->SetRemoteDescription(std::move(offer));
216 EXPECT_TRUE(set_remote_offer);
217 if (!set_remote_offer) {
218 return false;
219 }
220 auto answer = answerer->CreateAnswer(answer_options);
221 EXPECT_TRUE(answer);
222 if (!answer) {
223 return false;
224 }
225 bool set_local_answer =
226 answerer->SetLocalDescription(CloneSessionDescription(answer.get()));
227 EXPECT_TRUE(set_local_answer);
228 if (!set_local_answer) {
229 return false;
230 }
231 bool set_remote_answer = SetRemoteDescription(std::move(answer));
232 EXPECT_TRUE(set_remote_answer);
233 return set_remote_answer;
234 }
235
236 rtc::scoped_refptr<RtpTransceiverInterface>
AddTransceiver(cricket::MediaType media_type)237 PeerConnectionWrapper::AddTransceiver(cricket::MediaType media_type) {
238 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
239 pc()->AddTransceiver(media_type);
240 EXPECT_EQ(RTCErrorType::NONE, result.error().type());
241 return result.MoveValue();
242 }
243
244 rtc::scoped_refptr<RtpTransceiverInterface>
AddTransceiver(cricket::MediaType media_type,const RtpTransceiverInit & init)245 PeerConnectionWrapper::AddTransceiver(cricket::MediaType media_type,
246 const RtpTransceiverInit& init) {
247 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
248 pc()->AddTransceiver(media_type, init);
249 EXPECT_EQ(RTCErrorType::NONE, result.error().type());
250 return result.MoveValue();
251 }
252
253 rtc::scoped_refptr<RtpTransceiverInterface>
AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track)254 PeerConnectionWrapper::AddTransceiver(
255 rtc::scoped_refptr<MediaStreamTrackInterface> track) {
256 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
257 pc()->AddTransceiver(track);
258 EXPECT_EQ(RTCErrorType::NONE, result.error().type());
259 return result.MoveValue();
260 }
261
262 rtc::scoped_refptr<RtpTransceiverInterface>
AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track,const RtpTransceiverInit & init)263 PeerConnectionWrapper::AddTransceiver(
264 rtc::scoped_refptr<MediaStreamTrackInterface> track,
265 const RtpTransceiverInit& init) {
266 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
267 pc()->AddTransceiver(track, init);
268 EXPECT_EQ(RTCErrorType::NONE, result.error().type());
269 return result.MoveValue();
270 }
271
CreateAudioTrack(const std::string & label)272 rtc::scoped_refptr<AudioTrackInterface> PeerConnectionWrapper::CreateAudioTrack(
273 const std::string& label) {
274 return pc_factory()->CreateAudioTrack(label, nullptr);
275 }
276
CreateVideoTrack(const std::string & label)277 rtc::scoped_refptr<VideoTrackInterface> PeerConnectionWrapper::CreateVideoTrack(
278 const std::string& label) {
279 return pc_factory()->CreateVideoTrack(label,
280 FakeVideoTrackSource::Create().get());
281 }
282
AddTrack(rtc::scoped_refptr<MediaStreamTrackInterface> track,const std::vector<std::string> & stream_ids)283 rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddTrack(
284 rtc::scoped_refptr<MediaStreamTrackInterface> track,
285 const std::vector<std::string>& stream_ids) {
286 RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> result =
287 pc()->AddTrack(track, stream_ids);
288 EXPECT_EQ(RTCErrorType::NONE, result.error().type());
289 return result.MoveValue();
290 }
291
AddTrack(rtc::scoped_refptr<MediaStreamTrackInterface> track,const std::vector<std::string> & stream_ids,const std::vector<RtpEncodingParameters> & init_send_encodings)292 rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddTrack(
293 rtc::scoped_refptr<MediaStreamTrackInterface> track,
294 const std::vector<std::string>& stream_ids,
295 const std::vector<RtpEncodingParameters>& init_send_encodings) {
296 RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> result =
297 pc()->AddTrack(track, stream_ids, init_send_encodings);
298 EXPECT_EQ(RTCErrorType::NONE, result.error().type());
299 return result.MoveValue();
300 }
301
AddAudioTrack(const std::string & track_label,const std::vector<std::string> & stream_ids)302 rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddAudioTrack(
303 const std::string& track_label,
304 const std::vector<std::string>& stream_ids) {
305 return AddTrack(CreateAudioTrack(track_label), stream_ids);
306 }
307
AddVideoTrack(const std::string & track_label,const std::vector<std::string> & stream_ids)308 rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddVideoTrack(
309 const std::string& track_label,
310 const std::vector<std::string>& stream_ids) {
311 return AddTrack(CreateVideoTrack(track_label), stream_ids);
312 }
313
314 rtc::scoped_refptr<DataChannelInterface>
CreateDataChannel(const std::string & label)315 PeerConnectionWrapper::CreateDataChannel(const std::string& label) {
316 auto result = pc()->CreateDataChannelOrError(label, nullptr);
317 if (!result.ok()) {
318 RTC_LOG(LS_ERROR) << "CreateDataChannel failed: "
319 << ToString(result.error().type()) << " "
320 << result.error().message();
321 return nullptr;
322 }
323 return result.MoveValue();
324 }
325
326 PeerConnectionInterface::SignalingState
signaling_state()327 PeerConnectionWrapper::signaling_state() {
328 return pc()->signaling_state();
329 }
330
IsIceGatheringDone()331 bool PeerConnectionWrapper::IsIceGatheringDone() {
332 return observer()->ice_gathering_complete_;
333 }
334
IsIceConnected()335 bool PeerConnectionWrapper::IsIceConnected() {
336 return observer()->ice_connected_;
337 }
338
339 rtc::scoped_refptr<const webrtc::RTCStatsReport>
GetStats()340 PeerConnectionWrapper::GetStats() {
341 auto callback = rtc::make_ref_counted<MockRTCStatsCollectorCallback>();
342 pc()->GetStats(callback.get());
343 EXPECT_TRUE_WAIT(callback->called(), kDefaultTimeout);
344 return callback->report();
345 }
346
347 } // namespace webrtc
348