Multiple derived classes duplcated that code, and one more fixture can benefit from the same direct access to avoid saving reference to port allocator Cleaned includes and build dependencies on the way, in particular left single build target that contains peer_connection_wrapper Bug: webrtc:42232556 Change-Id: Ieb3d5449f3a0285230847716e33fb3b2d1b47882 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/376300 Reviewed-by: Per Kjellander <perkj@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43847}
394 lines
13 KiB
C++
394 lines
13 KiB
C++
/*
|
|
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "pc/peer_connection_wrapper.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "api/data_channel_interface.h"
|
|
#include "api/function_view.h"
|
|
#include "api/jsep.h"
|
|
#include "api/make_ref_counted.h"
|
|
#include "api/media_stream_interface.h"
|
|
#include "api/media_types.h"
|
|
#include "api/peer_connection_interface.h"
|
|
#include "api/rtc_error.h"
|
|
#include "api/rtp_parameters.h"
|
|
#include "api/rtp_sender_interface.h"
|
|
#include "api/rtp_transceiver_interface.h"
|
|
#include "api/scoped_refptr.h"
|
|
#include "api/stats/rtc_stats_report.h"
|
|
#include "api/test/rtc_error_matchers.h"
|
|
#include "pc/peer_connection.h"
|
|
#include "pc/peer_connection_proxy.h"
|
|
#include "pc/sdp_utils.h"
|
|
#include "pc/test/fake_video_track_source.h"
|
|
#include "pc/test/mock_peer_connection_observers.h"
|
|
#include "rtc_base/checks.h"
|
|
#include "rtc_base/logging.h"
|
|
#include "test/gmock.h"
|
|
#include "test/gtest.h"
|
|
#include "test/wait_until.h"
|
|
|
|
namespace webrtc {
|
|
|
|
using ::testing::Eq;
|
|
using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
|
|
|
|
PeerConnectionWrapper::PeerConnectionWrapper(
|
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory,
|
|
rtc::scoped_refptr<PeerConnectionInterface> pc,
|
|
std::unique_ptr<MockPeerConnectionObserver> observer)
|
|
: pc_factory_(std::move(pc_factory)),
|
|
observer_(std::move(observer)),
|
|
pc_(std::move(pc)) {
|
|
RTC_DCHECK(pc_factory_);
|
|
RTC_DCHECK(pc_);
|
|
RTC_DCHECK(observer_);
|
|
observer_->SetPeerConnectionInterface(pc_.get());
|
|
}
|
|
|
|
PeerConnectionWrapper::~PeerConnectionWrapper() {
|
|
if (pc_)
|
|
pc_->Close();
|
|
}
|
|
|
|
PeerConnectionFactoryInterface* PeerConnectionWrapper::pc_factory() {
|
|
return pc_factory_.get();
|
|
}
|
|
|
|
PeerConnectionInterface* PeerConnectionWrapper::pc() {
|
|
return pc_.get();
|
|
}
|
|
|
|
MockPeerConnectionObserver* PeerConnectionWrapper::observer() {
|
|
return observer_.get();
|
|
}
|
|
|
|
PeerConnection* PeerConnectionWrapper::GetInternalPeerConnection() {
|
|
auto* pci =
|
|
static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
|
|
pc());
|
|
return static_cast<PeerConnection*>(pci->internal());
|
|
}
|
|
|
|
std::unique_ptr<SessionDescriptionInterface>
|
|
PeerConnectionWrapper::CreateOffer() {
|
|
return CreateOffer(RTCOfferAnswerOptions());
|
|
}
|
|
|
|
std::unique_ptr<SessionDescriptionInterface> PeerConnectionWrapper::CreateOffer(
|
|
const PeerConnectionInterface::RTCOfferAnswerOptions& options,
|
|
std::string* error_out) {
|
|
return CreateSdp(
|
|
[this, options](CreateSessionDescriptionObserver* observer) {
|
|
pc()->CreateOffer(observer, options);
|
|
},
|
|
error_out);
|
|
}
|
|
|
|
std::unique_ptr<SessionDescriptionInterface>
|
|
PeerConnectionWrapper::CreateOfferAndSetAsLocal() {
|
|
return CreateOfferAndSetAsLocal(RTCOfferAnswerOptions());
|
|
}
|
|
|
|
std::unique_ptr<SessionDescriptionInterface>
|
|
PeerConnectionWrapper::CreateOfferAndSetAsLocal(
|
|
const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
|
|
auto offer = CreateOffer(options);
|
|
if (!offer) {
|
|
return nullptr;
|
|
}
|
|
EXPECT_TRUE(SetLocalDescription(CloneSessionDescription(offer.get())));
|
|
return offer;
|
|
}
|
|
|
|
std::unique_ptr<SessionDescriptionInterface>
|
|
PeerConnectionWrapper::CreateAnswer() {
|
|
return CreateAnswer(RTCOfferAnswerOptions());
|
|
}
|
|
|
|
std::unique_ptr<SessionDescriptionInterface>
|
|
PeerConnectionWrapper::CreateAnswer(
|
|
const PeerConnectionInterface::RTCOfferAnswerOptions& options,
|
|
std::string* error_out) {
|
|
return CreateSdp(
|
|
[this, options](CreateSessionDescriptionObserver* observer) {
|
|
pc()->CreateAnswer(observer, options);
|
|
},
|
|
error_out);
|
|
}
|
|
|
|
std::unique_ptr<SessionDescriptionInterface>
|
|
PeerConnectionWrapper::CreateAnswerAndSetAsLocal() {
|
|
return CreateAnswerAndSetAsLocal(RTCOfferAnswerOptions());
|
|
}
|
|
|
|
std::unique_ptr<SessionDescriptionInterface>
|
|
PeerConnectionWrapper::CreateAnswerAndSetAsLocal(
|
|
const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
|
|
auto answer = CreateAnswer(options);
|
|
if (!answer) {
|
|
return nullptr;
|
|
}
|
|
EXPECT_TRUE(SetLocalDescription(CloneSessionDescription(answer.get())));
|
|
return answer;
|
|
}
|
|
|
|
std::unique_ptr<SessionDescriptionInterface>
|
|
PeerConnectionWrapper::CreateRollback() {
|
|
return CreateSessionDescription(SdpType::kRollback, "");
|
|
}
|
|
|
|
std::unique_ptr<SessionDescriptionInterface> PeerConnectionWrapper::CreateSdp(
|
|
rtc::FunctionView<void(CreateSessionDescriptionObserver*)> fn,
|
|
std::string* error_out) {
|
|
auto observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
|
|
fn(observer.get());
|
|
EXPECT_THAT(
|
|
WaitUntil([&] { return observer->called(); }, ::testing::IsTrue()),
|
|
IsRtcOk());
|
|
if (error_out && !observer->result()) {
|
|
*error_out = observer->error();
|
|
}
|
|
return observer->MoveDescription();
|
|
}
|
|
|
|
bool PeerConnectionWrapper::SetLocalDescription(
|
|
std::unique_ptr<SessionDescriptionInterface> desc,
|
|
std::string* error_out) {
|
|
return SetSdp(
|
|
[this, &desc](SetSessionDescriptionObserver* observer) {
|
|
pc()->SetLocalDescription(observer, desc.release());
|
|
},
|
|
error_out);
|
|
}
|
|
|
|
bool PeerConnectionWrapper::SetLocalDescription(
|
|
std::unique_ptr<SessionDescriptionInterface> desc,
|
|
RTCError* error_out) {
|
|
auto observer = rtc::make_ref_counted<FakeSetLocalDescriptionObserver>();
|
|
pc()->SetLocalDescription(std::move(desc), observer);
|
|
EXPECT_THAT(
|
|
WaitUntil([&] { return observer->called(); }, ::testing::IsTrue()),
|
|
IsRtcOk());
|
|
bool ok = observer->error().ok();
|
|
if (error_out)
|
|
*error_out = std::move(observer->error());
|
|
return ok;
|
|
}
|
|
|
|
bool PeerConnectionWrapper::SetRemoteDescription(
|
|
std::unique_ptr<SessionDescriptionInterface> desc,
|
|
std::string* error_out) {
|
|
return SetSdp(
|
|
[this, &desc](SetSessionDescriptionObserver* observer) {
|
|
pc()->SetRemoteDescription(observer, desc.release());
|
|
},
|
|
error_out);
|
|
}
|
|
|
|
bool PeerConnectionWrapper::SetRemoteDescription(
|
|
std::unique_ptr<SessionDescriptionInterface> desc,
|
|
RTCError* error_out) {
|
|
auto observer = rtc::make_ref_counted<FakeSetRemoteDescriptionObserver>();
|
|
pc()->SetRemoteDescription(std::move(desc), observer);
|
|
EXPECT_THAT(
|
|
WaitUntil([&] { return observer->called(); }, ::testing::IsTrue()),
|
|
IsRtcOk());
|
|
bool ok = observer->error().ok();
|
|
if (error_out)
|
|
*error_out = std::move(observer->error());
|
|
return ok;
|
|
}
|
|
|
|
bool PeerConnectionWrapper::SetSdp(
|
|
rtc::FunctionView<void(SetSessionDescriptionObserver*)> fn,
|
|
std::string* error_out) {
|
|
auto observer = rtc::make_ref_counted<MockSetSessionDescriptionObserver>();
|
|
fn(observer.get());
|
|
EXPECT_THAT(
|
|
WaitUntil([&] { return observer->called(); }, ::testing::IsTrue()),
|
|
IsRtcOk());
|
|
if (error_out && !observer->result()) {
|
|
*error_out = observer->error();
|
|
}
|
|
return observer->result();
|
|
}
|
|
|
|
bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
|
|
PeerConnectionWrapper* answerer) {
|
|
return ExchangeOfferAnswerWith(answerer, RTCOfferAnswerOptions(),
|
|
RTCOfferAnswerOptions());
|
|
}
|
|
|
|
bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
|
|
PeerConnectionWrapper* answerer,
|
|
const PeerConnectionInterface::RTCOfferAnswerOptions& offer_options,
|
|
const PeerConnectionInterface::RTCOfferAnswerOptions& answer_options) {
|
|
RTC_DCHECK(answerer);
|
|
if (answerer == this) {
|
|
RTC_LOG(LS_ERROR) << "Cannot exchange offer/answer with ourself!";
|
|
return false;
|
|
}
|
|
auto offer = CreateOffer(offer_options);
|
|
EXPECT_TRUE(offer);
|
|
if (!offer) {
|
|
return false;
|
|
}
|
|
bool set_local_offer =
|
|
SetLocalDescription(CloneSessionDescription(offer.get()));
|
|
EXPECT_TRUE(set_local_offer);
|
|
if (!set_local_offer) {
|
|
return false;
|
|
}
|
|
bool set_remote_offer = answerer->SetRemoteDescription(std::move(offer));
|
|
EXPECT_TRUE(set_remote_offer);
|
|
if (!set_remote_offer) {
|
|
return false;
|
|
}
|
|
auto answer = answerer->CreateAnswer(answer_options);
|
|
EXPECT_TRUE(answer);
|
|
if (!answer) {
|
|
return false;
|
|
}
|
|
bool set_local_answer =
|
|
answerer->SetLocalDescription(CloneSessionDescription(answer.get()));
|
|
EXPECT_TRUE(set_local_answer);
|
|
if (!set_local_answer) {
|
|
return false;
|
|
}
|
|
bool set_remote_answer = SetRemoteDescription(std::move(answer));
|
|
EXPECT_TRUE(set_remote_answer);
|
|
return set_remote_answer;
|
|
}
|
|
|
|
rtc::scoped_refptr<RtpTransceiverInterface>
|
|
PeerConnectionWrapper::AddTransceiver(cricket::MediaType media_type) {
|
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
|
|
pc()->AddTransceiver(media_type);
|
|
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
|
return result.MoveValue();
|
|
}
|
|
|
|
rtc::scoped_refptr<RtpTransceiverInterface>
|
|
PeerConnectionWrapper::AddTransceiver(cricket::MediaType media_type,
|
|
const RtpTransceiverInit& init) {
|
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
|
|
pc()->AddTransceiver(media_type, init);
|
|
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
|
return result.MoveValue();
|
|
}
|
|
|
|
rtc::scoped_refptr<RtpTransceiverInterface>
|
|
PeerConnectionWrapper::AddTransceiver(
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track) {
|
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
|
|
pc()->AddTransceiver(track);
|
|
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
|
return result.MoveValue();
|
|
}
|
|
|
|
rtc::scoped_refptr<RtpTransceiverInterface>
|
|
PeerConnectionWrapper::AddTransceiver(
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
|
const RtpTransceiverInit& init) {
|
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
|
|
pc()->AddTransceiver(track, init);
|
|
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
|
return result.MoveValue();
|
|
}
|
|
|
|
rtc::scoped_refptr<AudioTrackInterface> PeerConnectionWrapper::CreateAudioTrack(
|
|
const std::string& label) {
|
|
return pc_factory()->CreateAudioTrack(label, nullptr);
|
|
}
|
|
|
|
rtc::scoped_refptr<VideoTrackInterface> PeerConnectionWrapper::CreateVideoTrack(
|
|
const std::string& label) {
|
|
return pc_factory()->CreateVideoTrack(FakeVideoTrackSource::Create(), label);
|
|
}
|
|
|
|
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddTrack(
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
|
const std::vector<std::string>& stream_ids) {
|
|
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> result =
|
|
pc()->AddTrack(track, stream_ids);
|
|
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
|
return result.MoveValue();
|
|
}
|
|
|
|
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddTrack(
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
|
const std::vector<std::string>& stream_ids,
|
|
const std::vector<RtpEncodingParameters>& init_send_encodings) {
|
|
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> result =
|
|
pc()->AddTrack(track, stream_ids, init_send_encodings);
|
|
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
|
return result.MoveValue();
|
|
}
|
|
|
|
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddAudioTrack(
|
|
const std::string& track_label,
|
|
const std::vector<std::string>& stream_ids) {
|
|
return AddTrack(CreateAudioTrack(track_label), stream_ids);
|
|
}
|
|
|
|
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddVideoTrack(
|
|
const std::string& track_label,
|
|
const std::vector<std::string>& stream_ids) {
|
|
return AddTrack(CreateVideoTrack(track_label), stream_ids);
|
|
}
|
|
|
|
rtc::scoped_refptr<DataChannelInterface>
|
|
PeerConnectionWrapper::CreateDataChannel(
|
|
const std::string& label,
|
|
const std::optional<DataChannelInit>& config) {
|
|
const DataChannelInit* config_ptr = config.has_value() ? &(*config) : nullptr;
|
|
auto result = pc()->CreateDataChannelOrError(label, config_ptr);
|
|
if (!result.ok()) {
|
|
RTC_LOG(LS_ERROR) << "CreateDataChannel failed: "
|
|
<< ToString(result.error().type()) << " "
|
|
<< result.error().message();
|
|
return nullptr;
|
|
}
|
|
return result.MoveValue();
|
|
}
|
|
|
|
PeerConnectionInterface::SignalingState
|
|
PeerConnectionWrapper::signaling_state() {
|
|
return pc()->signaling_state();
|
|
}
|
|
|
|
bool PeerConnectionWrapper::IsIceGatheringDone() {
|
|
return observer()->ice_gathering_complete_;
|
|
}
|
|
|
|
bool PeerConnectionWrapper::IsIceConnected() {
|
|
return observer()->ice_connected_;
|
|
}
|
|
|
|
rtc::scoped_refptr<const RTCStatsReport> PeerConnectionWrapper::GetStats() {
|
|
auto callback = rtc::make_ref_counted<MockRTCStatsCollectorCallback>();
|
|
pc()->GetStats(callback.get());
|
|
EXPECT_THAT(
|
|
WaitUntil([&] { return callback->called(); }, ::testing::IsTrue()),
|
|
IsRtcOk());
|
|
return callback->report();
|
|
}
|
|
|
|
} // namespace webrtc
|