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