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