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 <memory>
16 #include <string>
17 #include <utility>
18 #include <vector>
19
20 #include "api/function_view.h"
21 #include "api/set_remote_description_observer_interface.h"
22 #include "pc/sdp_utils.h"
23 #include "pc/test/fake_video_track_source.h"
24 #include "rtc_base/checks.h"
25 #include "rtc_base/gunit.h"
26 #include "rtc_base/logging.h"
27 #include "rtc_base/ref_counted_object.h"
28 #include "test/gtest.h"
29
30 namespace webrtc {
31
32 using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
33
34 namespace {
35 const uint32_t kDefaultTimeout = 10000U;
36 }
37
PeerConnectionWrapper(rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory,rtc::scoped_refptr<PeerConnectionInterface> pc,std::unique_ptr<MockPeerConnectionObserver> observer)38 PeerConnectionWrapper::PeerConnectionWrapper(
39 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory,
40 rtc::scoped_refptr<PeerConnectionInterface> pc,
41 std::unique_ptr<MockPeerConnectionObserver> observer)
42 : pc_factory_(std::move(pc_factory)),
43 observer_(std::move(observer)),
44 pc_(std::move(pc)) {
45 RTC_DCHECK(pc_factory_);
46 RTC_DCHECK(pc_);
47 RTC_DCHECK(observer_);
48 observer_->SetPeerConnectionInterface(pc_.get());
49 }
50
51 PeerConnectionWrapper::~PeerConnectionWrapper() = default;
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 rtc::scoped_refptr<MockCreateSessionDescriptionObserver> observer(
137 new rtc::RefCountedObject<MockCreateSessionDescriptionObserver>());
138 fn(observer);
139 EXPECT_EQ_WAIT(true, observer->called(), kDefaultTimeout);
140 if (error_out && !observer->result()) {
141 *error_out = observer->error();
142 }
143 return observer->MoveDescription();
144 }
145
SetLocalDescription(std::unique_ptr<SessionDescriptionInterface> desc,std::string * error_out)146 bool PeerConnectionWrapper::SetLocalDescription(
147 std::unique_ptr<SessionDescriptionInterface> desc,
148 std::string* error_out) {
149 return SetSdp(
150 [this, &desc](SetSessionDescriptionObserver* observer) {
151 pc()->SetLocalDescription(observer, desc.release());
152 },
153 error_out);
154 }
155
SetRemoteDescription(std::unique_ptr<SessionDescriptionInterface> desc,std::string * error_out)156 bool PeerConnectionWrapper::SetRemoteDescription(
157 std::unique_ptr<SessionDescriptionInterface> desc,
158 std::string* error_out) {
159 return SetSdp(
160 [this, &desc](SetSessionDescriptionObserver* observer) {
161 pc()->SetRemoteDescription(observer, desc.release());
162 },
163 error_out);
164 }
165
SetRemoteDescription(std::unique_ptr<SessionDescriptionInterface> desc,RTCError * error_out)166 bool PeerConnectionWrapper::SetRemoteDescription(
167 std::unique_ptr<SessionDescriptionInterface> desc,
168 RTCError* error_out) {
169 rtc::scoped_refptr<MockSetRemoteDescriptionObserver> observer =
170 new MockSetRemoteDescriptionObserver();
171 pc()->SetRemoteDescription(std::move(desc), observer);
172 EXPECT_EQ_WAIT(true, observer->called(), kDefaultTimeout);
173 bool ok = observer->error().ok();
174 if (error_out)
175 *error_out = std::move(observer->error());
176 return ok;
177 }
178
SetSdp(rtc::FunctionView<void (SetSessionDescriptionObserver *)> fn,std::string * error_out)179 bool PeerConnectionWrapper::SetSdp(
180 rtc::FunctionView<void(SetSessionDescriptionObserver*)> fn,
181 std::string* error_out) {
182 rtc::scoped_refptr<MockSetSessionDescriptionObserver> observer(
183 new rtc::RefCountedObject<MockSetSessionDescriptionObserver>());
184 fn(observer);
185 EXPECT_EQ_WAIT(true, observer->called(), kDefaultTimeout);
186 if (error_out && !observer->result()) {
187 *error_out = observer->error();
188 }
189 return observer->result();
190 }
191
ExchangeOfferAnswerWith(PeerConnectionWrapper * answerer)192 bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
193 PeerConnectionWrapper* answerer) {
194 return ExchangeOfferAnswerWith(answerer, RTCOfferAnswerOptions(),
195 RTCOfferAnswerOptions());
196 }
197
ExchangeOfferAnswerWith(PeerConnectionWrapper * answerer,const PeerConnectionInterface::RTCOfferAnswerOptions & offer_options,const PeerConnectionInterface::RTCOfferAnswerOptions & answer_options)198 bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
199 PeerConnectionWrapper* answerer,
200 const PeerConnectionInterface::RTCOfferAnswerOptions& offer_options,
201 const PeerConnectionInterface::RTCOfferAnswerOptions& answer_options) {
202 RTC_DCHECK(answerer);
203 if (answerer == this) {
204 RTC_LOG(LS_ERROR) << "Cannot exchange offer/answer with ourself!";
205 return false;
206 }
207 auto offer = CreateOffer(offer_options);
208 EXPECT_TRUE(offer);
209 if (!offer) {
210 return false;
211 }
212 bool set_local_offer =
213 SetLocalDescription(CloneSessionDescription(offer.get()));
214 EXPECT_TRUE(set_local_offer);
215 if (!set_local_offer) {
216 return false;
217 }
218 bool set_remote_offer = answerer->SetRemoteDescription(std::move(offer));
219 EXPECT_TRUE(set_remote_offer);
220 if (!set_remote_offer) {
221 return false;
222 }
223 auto answer = answerer->CreateAnswer(answer_options);
224 EXPECT_TRUE(answer);
225 if (!answer) {
226 return false;
227 }
228 bool set_local_answer =
229 answerer->SetLocalDescription(CloneSessionDescription(answer.get()));
230 EXPECT_TRUE(set_local_answer);
231 if (!set_local_answer) {
232 return false;
233 }
234 bool set_remote_answer = SetRemoteDescription(std::move(answer));
235 EXPECT_TRUE(set_remote_answer);
236 return set_remote_answer;
237 }
238
239 rtc::scoped_refptr<RtpTransceiverInterface>
AddTransceiver(cricket::MediaType media_type)240 PeerConnectionWrapper::AddTransceiver(cricket::MediaType media_type) {
241 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
242 pc()->AddTransceiver(media_type);
243 EXPECT_EQ(RTCErrorType::NONE, result.error().type());
244 return result.MoveValue();
245 }
246
247 rtc::scoped_refptr<RtpTransceiverInterface>
AddTransceiver(cricket::MediaType media_type,const RtpTransceiverInit & init)248 PeerConnectionWrapper::AddTransceiver(cricket::MediaType media_type,
249 const RtpTransceiverInit& init) {
250 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
251 pc()->AddTransceiver(media_type, init);
252 EXPECT_EQ(RTCErrorType::NONE, result.error().type());
253 return result.MoveValue();
254 }
255
256 rtc::scoped_refptr<RtpTransceiverInterface>
AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track)257 PeerConnectionWrapper::AddTransceiver(
258 rtc::scoped_refptr<MediaStreamTrackInterface> track) {
259 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
260 pc()->AddTransceiver(track);
261 EXPECT_EQ(RTCErrorType::NONE, result.error().type());
262 return result.MoveValue();
263 }
264
265 rtc::scoped_refptr<RtpTransceiverInterface>
AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track,const RtpTransceiverInit & init)266 PeerConnectionWrapper::AddTransceiver(
267 rtc::scoped_refptr<MediaStreamTrackInterface> track,
268 const RtpTransceiverInit& init) {
269 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
270 pc()->AddTransceiver(track, init);
271 EXPECT_EQ(RTCErrorType::NONE, result.error().type());
272 return result.MoveValue();
273 }
274
CreateAudioTrack(const std::string & label)275 rtc::scoped_refptr<AudioTrackInterface> PeerConnectionWrapper::CreateAudioTrack(
276 const std::string& label) {
277 return pc_factory()->CreateAudioTrack(label, nullptr);
278 }
279
CreateVideoTrack(const std::string & label)280 rtc::scoped_refptr<VideoTrackInterface> PeerConnectionWrapper::CreateVideoTrack(
281 const std::string& label) {
282 return pc_factory()->CreateVideoTrack(label, FakeVideoTrackSource::Create());
283 }
284
AddTrack(rtc::scoped_refptr<MediaStreamTrackInterface> track,const std::vector<std::string> & stream_ids)285 rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddTrack(
286 rtc::scoped_refptr<MediaStreamTrackInterface> track,
287 const std::vector<std::string>& stream_ids) {
288 RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> result =
289 pc()->AddTrack(track, stream_ids);
290 EXPECT_EQ(RTCErrorType::NONE, result.error().type());
291 return result.MoveValue();
292 }
293
AddAudioTrack(const std::string & track_label,const std::vector<std::string> & stream_ids)294 rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddAudioTrack(
295 const std::string& track_label,
296 const std::vector<std::string>& stream_ids) {
297 return AddTrack(CreateAudioTrack(track_label), stream_ids);
298 }
299
AddVideoTrack(const std::string & track_label,const std::vector<std::string> & stream_ids)300 rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddVideoTrack(
301 const std::string& track_label,
302 const std::vector<std::string>& stream_ids) {
303 return AddTrack(CreateVideoTrack(track_label), stream_ids);
304 }
305
306 rtc::scoped_refptr<DataChannelInterface>
CreateDataChannel(const std::string & label)307 PeerConnectionWrapper::CreateDataChannel(const std::string& label) {
308 return pc()->CreateDataChannel(label, nullptr);
309 }
310
311 PeerConnectionInterface::SignalingState
signaling_state()312 PeerConnectionWrapper::signaling_state() {
313 return pc()->signaling_state();
314 }
315
IsIceGatheringDone()316 bool PeerConnectionWrapper::IsIceGatheringDone() {
317 return observer()->ice_gathering_complete_;
318 }
319
IsIceConnected()320 bool PeerConnectionWrapper::IsIceConnected() {
321 return observer()->ice_connected_;
322 }
323
324 rtc::scoped_refptr<const webrtc::RTCStatsReport>
GetStats()325 PeerConnectionWrapper::GetStats() {
326 rtc::scoped_refptr<webrtc::MockRTCStatsCollectorCallback> callback(
327 new rtc::RefCountedObject<webrtc::MockRTCStatsCollectorCallback>());
328 pc()->GetStats(callback);
329 EXPECT_TRUE_WAIT(callback->called(), kDefaultTimeout);
330 return callback->report();
331 }
332
333 } // namespace webrtc
334