Reland of TransportController refactoring. (patchset #1 id:1 of https://codereview.webrtc.org/1358413003/ )
Reason for revert: This CL just landed: https://codereview.chromium.org/1323243006/ Which fixes the FYI bots for the original CL, and breaks them for this revert. Original issue's description: > Revert of TransportController refactoring. (patchset #6 id:100001 of https://codereview.webrtc.org/1350523003/ ) > > Reason for revert: > This CL causes problems with the WebRTC-in-Chromium FYI bots. Presumably it needs to be done in several steps, where removed files are emptied instead of removed in the first step. > > Original issue's description: > > TransportController refactoring. > > > > Getting rid of TransportProxy, and in its place adding a > > TransportController class which will facilitate access to and manage > > the lifetimes of Transports. These Transports will now be accessed > > solely from the worker thread, simplifying their implementation. > > > > This refactoring also pulls Transport-related code out of BaseSession. > > Which means that BaseChannels will now rely on the TransportController > > interface to create channels, rather than BaseSession. > > > > Committed: https://crrev.com/47ee2f3b9f33e8938948c482c921d4e13a3acd83 > > Cr-Commit-Position: refs/heads/master@{#10022} > > TBR=pthatcher@webrtc.org,deadbeef@webrtc.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > > Committed: https://crrev.com/a81a42f584baa0d93a4b93da9632415e8922450c > Cr-Commit-Position: refs/heads/master@{#10024} TBR=pthatcher@webrtc.org,torbjorng@webrtc.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Review URL: https://codereview.webrtc.org/1361773005 Cr-Commit-Position: refs/heads/master@{#10036}
This commit is contained in:
@ -196,8 +196,11 @@
|
||||
if (newState == RTCICEGatheringGathering) {
|
||||
return;
|
||||
}
|
||||
NSAssert([_expectedICEGatheringChanges count] > 0,
|
||||
@"Unexpected ICE gathering state change");
|
||||
int expectedState = [self popFirstElementAsInt:_expectedICEGatheringChanges];
|
||||
NSAssert(expectedState == (int)newState, @"Empty expectation array");
|
||||
NSAssert(expectedState == (int)newState,
|
||||
@"ICE gathering state should match expectation");
|
||||
}
|
||||
|
||||
- (void)peerConnection:(RTCPeerConnection*)peerConnection
|
||||
@ -205,8 +208,11 @@
|
||||
// See TODO(fischman) in RTCPeerConnectionTest.mm about Completed.
|
||||
if (newState == RTCICEConnectionCompleted)
|
||||
return;
|
||||
NSAssert([_expectedICEConnectionChanges count] > 0,
|
||||
@"Unexpected ICE connection state change");
|
||||
int expectedState = [self popFirstElementAsInt:_expectedICEConnectionChanges];
|
||||
NSAssert(expectedState == (int)newState, @"Empty expectation array");
|
||||
NSAssert(expectedState == (int)newState,
|
||||
@"ICE connection state should match expectation");
|
||||
}
|
||||
|
||||
- (void)peerConnection:(RTCPeerConnection*)peerConnection
|
||||
|
||||
@ -182,7 +182,10 @@
|
||||
EXPECT_GT([answerSDP.description length], 0);
|
||||
|
||||
[offeringExpectations expectICECandidates:2];
|
||||
[answeringExpectations expectICECandidates:2];
|
||||
// It's possible to only have 1 ICE candidate for the answerer, since we use
|
||||
// BUNDLE and rtcp-mux by default, and don't provide any ICE servers in this
|
||||
// test.
|
||||
[answeringExpectations expectICECandidates:1];
|
||||
|
||||
sdpObserver = [[RTCSessionDescriptionSyncObserver alloc] init];
|
||||
[answeringExpectations expectSignalingChange:RTCSignalingStable];
|
||||
|
||||
@ -616,6 +616,10 @@ void PeerConnection::SetLocalDescription(
|
||||
}
|
||||
SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
|
||||
signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
|
||||
// MaybeStartGathering needs to be called after posting
|
||||
// MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates
|
||||
// before signaling that SetLocalDescription completed.
|
||||
session_->MaybeStartGathering();
|
||||
}
|
||||
|
||||
void PeerConnection::SetRemoteDescription(
|
||||
@ -868,6 +872,11 @@ void PeerConnection::OnRemoveLocalStream(MediaStreamInterface* stream) {
|
||||
void PeerConnection::OnIceConnectionChange(
|
||||
PeerConnectionInterface::IceConnectionState new_state) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
// After transitioning to "closed", ignore any additional states from
|
||||
// WebRtcSession (such as "disconnected").
|
||||
if (ice_connection_state_ == kIceConnectionClosed) {
|
||||
return;
|
||||
}
|
||||
ice_connection_state_ = new_state;
|
||||
observer_->OnIceConnectionChange(ice_connection_state_);
|
||||
}
|
||||
|
||||
@ -697,24 +697,18 @@ void StatsCollector::ExtractSessionInfo() {
|
||||
// expose them in stats reports. All channels in a transport share the
|
||||
// same local and remote certificates.
|
||||
//
|
||||
// Note that Transport::GetCertificate and Transport::GetRemoteCertificate
|
||||
// invoke method calls on the worker thread and block this thread, but
|
||||
// messages are still processed on this thread, which may blow way the
|
||||
// existing transports. So we cannot reuse |transport| after these calls.
|
||||
StatsReport::Id local_cert_report_id, remote_cert_report_id;
|
||||
|
||||
cricket::Transport* transport =
|
||||
session_->GetTransport(transport_iter.second.content_name);
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> certificate;
|
||||
if (transport && transport->GetCertificate(&certificate)) {
|
||||
if (session_->GetLocalCertificate(transport_iter.second.transport_name,
|
||||
&certificate)) {
|
||||
StatsReport* r = AddCertificateReports(&(certificate->ssl_certificate()));
|
||||
if (r)
|
||||
local_cert_report_id = r->id();
|
||||
}
|
||||
|
||||
transport = session_->GetTransport(transport_iter.second.content_name);
|
||||
rtc::scoped_ptr<rtc::SSLCertificate> cert;
|
||||
if (transport && transport->GetRemoteSSLCertificate(cert.accept())) {
|
||||
if (session_->GetRemoteSSLCertificate(transport_iter.second.transport_name,
|
||||
cert.accept())) {
|
||||
StatsReport* r = AddCertificateReports(cert.get());
|
||||
if (r)
|
||||
remote_cert_report_id = r->id();
|
||||
@ -722,7 +716,7 @@ void StatsCollector::ExtractSessionInfo() {
|
||||
|
||||
for (const auto& channel_iter : transport_iter.second.channel_stats) {
|
||||
StatsReport::Id id(StatsReport::NewComponentId(
|
||||
transport_iter.second.content_name, channel_iter.component));
|
||||
transport_iter.second.transport_name, channel_iter.component));
|
||||
StatsReport* channel_report = reports_.ReplaceOrAddNew(id);
|
||||
channel_report->set_timestamp(stats_gathering_started_);
|
||||
channel_report->AddInt(StatsReport::kStatsValueNameComponent,
|
||||
@ -939,7 +933,6 @@ void StatsCollector::UpdateTrackReports() {
|
||||
StatsReport* report = entry.second;
|
||||
report->set_timestamp(stats_gathering_started_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void StatsCollector::ClearUpdateStatsCacheForTest() {
|
||||
|
||||
@ -27,6 +27,8 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "talk/app/webrtc/statscollector.h"
|
||||
|
||||
#include "talk/app/webrtc/mediastream.h"
|
||||
@ -45,7 +47,7 @@
|
||||
#include "webrtc/base/fakesslidentity.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
#include "webrtc/base/network.h"
|
||||
#include "webrtc/p2p/base/fakesession.h"
|
||||
#include "webrtc/p2p/base/faketransportcontroller.h"
|
||||
|
||||
using rtc::scoped_ptr;
|
||||
using testing::_;
|
||||
@ -89,7 +91,12 @@ class MockWebRtcSession : public webrtc::WebRtcSession {
|
||||
MOCK_METHOD2(GetLocalTrackIdBySsrc, bool(uint32, std::string*));
|
||||
MOCK_METHOD2(GetRemoteTrackIdBySsrc, bool(uint32, std::string*));
|
||||
MOCK_METHOD1(GetTransportStats, bool(cricket::SessionStats*));
|
||||
MOCK_METHOD1(GetTransport, cricket::Transport*(const std::string&));
|
||||
MOCK_METHOD2(GetLocalCertificate,
|
||||
bool(const std::string& transport_name,
|
||||
rtc::scoped_refptr<rtc::RTCCertificate>* certificate));
|
||||
MOCK_METHOD2(GetRemoteSSLCertificate,
|
||||
bool(const std::string& transport_name,
|
||||
rtc::SSLCertificate** cert));
|
||||
};
|
||||
|
||||
class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel {
|
||||
@ -500,7 +507,7 @@ class StatsCollectorTest : public testing::Test {
|
||||
cricket::TransportStats transport_stats;
|
||||
cricket::TransportChannelStats channel_stats;
|
||||
channel_stats.component = 1;
|
||||
transport_stats.content_name = kTransportName;
|
||||
transport_stats.transport_name = kTransportName;
|
||||
transport_stats.channel_stats.push_back(channel_stats);
|
||||
|
||||
session_stats_.transport_stats[kTransportName] = transport_stats;
|
||||
@ -647,36 +654,27 @@ class StatsCollectorTest : public testing::Test {
|
||||
channel_stats.ssl_cipher = "the-ssl-cipher";
|
||||
|
||||
cricket::TransportStats transport_stats;
|
||||
transport_stats.content_name = "audio";
|
||||
transport_stats.transport_name = "audio";
|
||||
transport_stats.channel_stats.push_back(channel_stats);
|
||||
|
||||
cricket::SessionStats session_stats;
|
||||
session_stats.transport_stats[transport_stats.content_name] =
|
||||
session_stats.transport_stats[transport_stats.transport_name] =
|
||||
transport_stats;
|
||||
|
||||
// Fake certificates to report.
|
||||
// Fake certificate to report
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> local_certificate(
|
||||
rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::FakeSSLIdentity>(
|
||||
new rtc::FakeSSLIdentity(local_cert)).Pass()));
|
||||
rtc::scoped_ptr<rtc::FakeSSLCertificate> remote_cert_copy(
|
||||
remote_cert.GetReference());
|
||||
|
||||
// Fake transport object.
|
||||
rtc::scoped_ptr<cricket::FakeTransport> transport(
|
||||
new cricket::FakeTransport(
|
||||
session_.signaling_thread(),
|
||||
session_.worker_thread(),
|
||||
transport_stats.content_name));
|
||||
transport->SetCertificate(local_certificate);
|
||||
cricket::FakeTransportChannel* channel =
|
||||
static_cast<cricket::FakeTransportChannel*>(
|
||||
transport->CreateChannel(channel_stats.component));
|
||||
EXPECT_FALSE(channel == NULL);
|
||||
channel->SetRemoteSSLCertificate(remote_cert_copy.get());
|
||||
new rtc::FakeSSLIdentity(local_cert))
|
||||
.Pass()));
|
||||
|
||||
// Configure MockWebRtcSession
|
||||
EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
|
||||
.WillRepeatedly(Return(transport.get()));
|
||||
EXPECT_CALL(session_,
|
||||
GetLocalCertificate(transport_stats.transport_name, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(local_certificate), Return(true)));
|
||||
EXPECT_CALL(session_,
|
||||
GetRemoteSSLCertificate(transport_stats.transport_name, _))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<1>(remote_cert.GetReference()), Return(true)));
|
||||
EXPECT_CALL(session_, GetTransportStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
|
||||
Return(true)));
|
||||
@ -790,14 +788,17 @@ TEST_F(StatsCollectorTest, ExtractDataInfo) {
|
||||
TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
const char kVideoChannelName[] = "video";
|
||||
|
||||
InitSessionStats(kVideoChannelName);
|
||||
EXPECT_CALL(session_, GetTransportStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||
Return(true)));
|
||||
EXPECT_CALL(session_, GetTransport(_))
|
||||
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
|
||||
|
||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
|
||||
cricket::VideoChannel video_channel(rtc::Thread::Current(),
|
||||
@ -833,14 +834,17 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
|
||||
TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
const char kVideoChannelName[] = "video";
|
||||
|
||||
InitSessionStats(kVideoChannelName);
|
||||
EXPECT_CALL(session_, GetTransportStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||
Return(true)));
|
||||
EXPECT_CALL(session_, GetTransport(_))
|
||||
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
|
||||
|
||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
|
||||
cricket::VideoChannel video_channel(rtc::Thread::Current(),
|
||||
@ -946,13 +950,16 @@ TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
|
||||
TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
const char kVideoChannelName[] = "video";
|
||||
InitSessionStats(kVideoChannelName);
|
||||
EXPECT_CALL(session_, GetTransportStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||
Return(true)));
|
||||
EXPECT_CALL(session_, GetTransport(_))
|
||||
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
|
||||
|
||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
|
||||
cricket::VideoChannel video_channel(rtc::Thread::Current(),
|
||||
@ -1011,11 +1018,13 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
|
||||
TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
// Ignore unused callback (logspam).
|
||||
EXPECT_CALL(session_, GetTransport(_))
|
||||
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
|
||||
// The content_name known by the video channel.
|
||||
// The transport_name known by the video channel.
|
||||
const std::string kVcName("vcname");
|
||||
cricket::VideoChannel video_channel(rtc::Thread::Current(),
|
||||
media_channel, NULL, kVcName, false);
|
||||
@ -1073,7 +1082,7 @@ TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
|
||||
// The content_name known by the video channel.
|
||||
// The transport_name known by the video channel.
|
||||
const std::string kVcName("vcname");
|
||||
cricket::VideoChannel video_channel(rtc::Thread::Current(),
|
||||
media_channel, NULL, kVcName, false);
|
||||
@ -1096,11 +1105,13 @@ TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
|
||||
TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
// Ignore unused callback (logspam).
|
||||
EXPECT_CALL(session_, GetTransport(_))
|
||||
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
|
||||
// The content_name known by the video channel.
|
||||
// The transport_name known by the video channel.
|
||||
const std::string kVcName("vcname");
|
||||
cricket::VideoChannel video_channel(rtc::Thread::Current(),
|
||||
media_channel, NULL, kVcName, false);
|
||||
@ -1145,13 +1156,16 @@ TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
|
||||
TEST_F(StatsCollectorTest, ReportsFromRemoteTrack) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
const char kVideoChannelName[] = "video";
|
||||
InitSessionStats(kVideoChannelName);
|
||||
EXPECT_CALL(session_, GetTransportStats(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
|
||||
Return(true)));
|
||||
EXPECT_CALL(session_, GetTransport(_))
|
||||
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
|
||||
|
||||
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
|
||||
cricket::VideoChannel video_channel(rtc::Thread::Current(),
|
||||
@ -1330,6 +1344,11 @@ TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) {
|
||||
TEST_F(StatsCollectorTest, NoTransport) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
StatsReports reports; // returned values.
|
||||
|
||||
// Fake stats to process.
|
||||
@ -1337,16 +1356,14 @@ TEST_F(StatsCollectorTest, NoTransport) {
|
||||
channel_stats.component = 1;
|
||||
|
||||
cricket::TransportStats transport_stats;
|
||||
transport_stats.content_name = "audio";
|
||||
transport_stats.transport_name = "audio";
|
||||
transport_stats.channel_stats.push_back(channel_stats);
|
||||
|
||||
cricket::SessionStats session_stats;
|
||||
session_stats.transport_stats[transport_stats.content_name] =
|
||||
session_stats.transport_stats[transport_stats.transport_name] =
|
||||
transport_stats;
|
||||
|
||||
// Configure MockWebRtcSession
|
||||
EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
|
||||
.WillRepeatedly(ReturnNull());
|
||||
EXPECT_CALL(session_, GetTransportStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
|
||||
Return(true)));
|
||||
@ -1389,6 +1406,11 @@ TEST_F(StatsCollectorTest, NoTransport) {
|
||||
TEST_F(StatsCollectorTest, NoCertificates) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
StatsReports reports; // returned values.
|
||||
|
||||
// Fake stats to process.
|
||||
@ -1396,23 +1418,18 @@ TEST_F(StatsCollectorTest, NoCertificates) {
|
||||
channel_stats.component = 1;
|
||||
|
||||
cricket::TransportStats transport_stats;
|
||||
transport_stats.content_name = "audio";
|
||||
transport_stats.transport_name = "audio";
|
||||
transport_stats.channel_stats.push_back(channel_stats);
|
||||
|
||||
cricket::SessionStats session_stats;
|
||||
session_stats.transport_stats[transport_stats.content_name] =
|
||||
session_stats.transport_stats[transport_stats.transport_name] =
|
||||
transport_stats;
|
||||
|
||||
// Fake transport object.
|
||||
rtc::scoped_ptr<cricket::FakeTransport> transport(
|
||||
new cricket::FakeTransport(
|
||||
session_.signaling_thread(),
|
||||
session_.worker_thread(),
|
||||
transport_stats.content_name));
|
||||
new cricket::FakeTransport(transport_stats.transport_name));
|
||||
|
||||
// Configure MockWebRtcSession
|
||||
EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
|
||||
.WillRepeatedly(Return(transport.get()));
|
||||
EXPECT_CALL(session_, GetTransportStats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
|
||||
Return(true)));
|
||||
@ -1458,12 +1475,13 @@ TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) {
|
||||
TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
// Ignore unused callback (logspam).
|
||||
EXPECT_CALL(session_, GetTransport(_))
|
||||
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
|
||||
// The content_name known by the voice channel.
|
||||
// The transport_name known by the voice channel.
|
||||
const std::string kVcName("vcname");
|
||||
cricket::VoiceChannel voice_channel(rtc::Thread::Current(),
|
||||
media_engine_, media_channel, NULL, kVcName, false);
|
||||
@ -1492,11 +1510,13 @@ TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) {
|
||||
TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
// Ignore unused callback (logspam).
|
||||
EXPECT_CALL(session_, GetTransport(_))
|
||||
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
|
||||
// The content_name known by the voice channel.
|
||||
// The transport_name known by the voice channel.
|
||||
const std::string kVcName("vcname");
|
||||
cricket::VoiceChannel voice_channel(rtc::Thread::Current(),
|
||||
media_engine_, media_channel, NULL, kVcName, false);
|
||||
@ -1519,11 +1539,13 @@ TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) {
|
||||
TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
// Ignore unused callback (logspam).
|
||||
EXPECT_CALL(session_, GetTransport(_))
|
||||
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
|
||||
// The content_name known by the voice channel.
|
||||
// The transport_name known by the voice channel.
|
||||
const std::string kVcName("vcname");
|
||||
cricket::VoiceChannel voice_channel(rtc::Thread::Current(),
|
||||
media_engine_, media_channel, NULL, kVcName, false);
|
||||
@ -1578,11 +1600,13 @@ TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) {
|
||||
TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
// Ignore unused callback (logspam).
|
||||
EXPECT_CALL(session_, GetTransport(_))
|
||||
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
|
||||
// The content_name known by the voice channel.
|
||||
// The transport_name known by the voice channel.
|
||||
const std::string kVcName("vcname");
|
||||
cricket::VoiceChannel voice_channel(rtc::Thread::Current(),
|
||||
media_engine_, media_channel, NULL, kVcName, false);
|
||||
@ -1663,11 +1687,13 @@ TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) {
|
||||
TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) {
|
||||
StatsCollectorForTest stats(&session_);
|
||||
|
||||
// Ignore unused callback (logspam).
|
||||
EXPECT_CALL(session_, GetTransport(_))
|
||||
.WillRepeatedly(Return(static_cast<cricket::Transport*>(NULL)));
|
||||
EXPECT_CALL(session_, GetLocalCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _))
|
||||
.WillRepeatedly(Return(false));
|
||||
|
||||
MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
|
||||
// The content_name known by the voice channel.
|
||||
// The transport_name known by the voice channel.
|
||||
const std::string kVcName("vcname");
|
||||
cricket::VoiceChannel voice_channel(rtc::Thread::Current(),
|
||||
media_engine_, media_channel, NULL, kVcName, false);
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include "talk/app/webrtc/jsepicecandidate.h"
|
||||
#include "talk/app/webrtc/jsepsessiondescription.h"
|
||||
@ -86,6 +87,7 @@ const char kDtlsSetupFailureRtp[] =
|
||||
"Couldn't set up DTLS-SRTP on RTP channel.";
|
||||
const char kDtlsSetupFailureRtcp[] =
|
||||
"Couldn't set up DTLS-SRTP on RTCP channel.";
|
||||
const char kEnableBundleFailed[] = "Failed to enable BUNDLE.";
|
||||
const int kMaxUnsignalledRecvStreams = 20;
|
||||
|
||||
IceCandidatePairType GetIceCandidatePairCounter(
|
||||
@ -543,7 +545,6 @@ WebRtcSession::WebRtcSession(
|
||||
worker_thread,
|
||||
port_allocator,
|
||||
rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX),
|
||||
cricket::NS_JINGLE_RTP,
|
||||
false),
|
||||
// RFC 3264: The numeric value of the session id and version in the
|
||||
// o line MUST be representable with a "64 bit signed integer".
|
||||
@ -558,6 +559,14 @@ WebRtcSession::WebRtcSession(
|
||||
data_channel_type_(cricket::DCT_NONE),
|
||||
ice_restart_latch_(new IceRestartAnswerLatch),
|
||||
metrics_observer_(NULL) {
|
||||
transport_controller()->SignalConnectionState.connect(
|
||||
this, &WebRtcSession::OnTransportControllerConnectionState);
|
||||
transport_controller()->SignalReceiving.connect(
|
||||
this, &WebRtcSession::OnTransportControllerReceiving);
|
||||
transport_controller()->SignalGatheringState.connect(
|
||||
this, &WebRtcSession::OnTransportControllerGatheringState);
|
||||
transport_controller()->SignalCandidatesGathered.connect(
|
||||
this, &WebRtcSession::OnTransportControllerCandidatesGathered);
|
||||
}
|
||||
|
||||
WebRtcSession::~WebRtcSession() {
|
||||
@ -583,12 +592,12 @@ WebRtcSession::~WebRtcSession() {
|
||||
|
||||
bool WebRtcSession::Initialize(
|
||||
const PeerConnectionFactoryInterface::Options& options,
|
||||
const MediaConstraintsInterface* constraints,
|
||||
const MediaConstraintsInterface* constraints,
|
||||
rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
|
||||
const PeerConnectionInterface::RTCConfiguration& rtc_configuration) {
|
||||
bundle_policy_ = rtc_configuration.bundle_policy;
|
||||
rtcp_mux_policy_ = rtc_configuration.rtcp_mux_policy;
|
||||
SetSslMaxProtocolVersion(options.ssl_max_version);
|
||||
transport_controller()->SetSslMaxProtocolVersion(options.ssl_max_version);
|
||||
|
||||
// Obtain a certificate from RTCConfiguration if any were provided (optional).
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> certificate;
|
||||
@ -613,10 +622,8 @@ bool WebRtcSession::Initialize(
|
||||
// Enable DTLS by default if we have an identity store or a certificate.
|
||||
dtls_enabled_ = (dtls_identity_store || certificate);
|
||||
// |constraints| can override the default |dtls_enabled_| value.
|
||||
if (FindConstraint(
|
||||
constraints,
|
||||
MediaConstraintsInterface::kEnableDtlsSrtp,
|
||||
&value, nullptr)) {
|
||||
if (FindConstraint(constraints, MediaConstraintsInterface::kEnableDtlsSrtp,
|
||||
&value, nullptr)) {
|
||||
dtls_enabled_ = value;
|
||||
}
|
||||
}
|
||||
@ -736,35 +743,21 @@ bool WebRtcSession::Initialize(
|
||||
if (!dtls_enabled_) {
|
||||
// Construct with DTLS disabled.
|
||||
webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
|
||||
signaling_thread(),
|
||||
channel_manager_,
|
||||
mediastream_signaling_,
|
||||
this,
|
||||
id(),
|
||||
data_channel_type_));
|
||||
signaling_thread(), channel_manager_, mediastream_signaling_, this,
|
||||
id(), data_channel_type_));
|
||||
} else {
|
||||
// Construct with DTLS enabled.
|
||||
if (!certificate) {
|
||||
// Use the |dtls_identity_store| to generate a certificate.
|
||||
RTC_DCHECK(dtls_identity_store);
|
||||
webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
|
||||
signaling_thread(),
|
||||
channel_manager_,
|
||||
mediastream_signaling_,
|
||||
dtls_identity_store.Pass(),
|
||||
this,
|
||||
id(),
|
||||
data_channel_type_));
|
||||
signaling_thread(), channel_manager_, mediastream_signaling_,
|
||||
dtls_identity_store.Pass(), this, id(), data_channel_type_));
|
||||
} else {
|
||||
// Use the already generated certificate.
|
||||
webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
|
||||
signaling_thread(),
|
||||
channel_manager_,
|
||||
mediastream_signaling_,
|
||||
certificate,
|
||||
this,
|
||||
id(),
|
||||
data_channel_type_));
|
||||
signaling_thread(), channel_manager_, mediastream_signaling_,
|
||||
certificate, this, id(), data_channel_type_));
|
||||
}
|
||||
}
|
||||
|
||||
@ -791,26 +784,12 @@ bool WebRtcSession::Initialize(
|
||||
|
||||
void WebRtcSession::Terminate() {
|
||||
SetState(STATE_RECEIVEDTERMINATE);
|
||||
RemoveUnusedChannelsAndTransports(NULL);
|
||||
RemoveUnusedChannels(NULL);
|
||||
ASSERT(!voice_channel_);
|
||||
ASSERT(!video_channel_);
|
||||
ASSERT(!data_channel_);
|
||||
}
|
||||
|
||||
bool WebRtcSession::StartCandidatesAllocation() {
|
||||
// SpeculativelyConnectTransportChannels, will call ConnectChannels method
|
||||
// from TransportProxy to start gathering ice candidates.
|
||||
SpeculativelyConnectAllTransportChannels();
|
||||
if (!saved_candidates_.empty()) {
|
||||
// If there are saved candidates which arrived before local description is
|
||||
// set, copy those to remote description.
|
||||
CopySavedCandidates(remote_desc_.get());
|
||||
}
|
||||
// Push remote candidates present in remote description to transport channels.
|
||||
UseCandidatesInSessionDescription(remote_desc_.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebRtcSession::SetSdesPolicy(cricket::SecurePolicy secure_policy) {
|
||||
webrtc_session_desc_factory_->SetSdesPolicy(secure_policy);
|
||||
}
|
||||
@ -826,17 +805,7 @@ bool WebRtcSession::GetSslRole(rtc::SSLRole* role) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(mallinath) - Return role of each transport, as role may differ from
|
||||
// one another.
|
||||
// In current implementaion we just return the role of first transport in the
|
||||
// transport map.
|
||||
for (cricket::TransportMap::const_iterator iter = transport_proxies().begin();
|
||||
iter != transport_proxies().end(); ++iter) {
|
||||
if (iter->second->impl()) {
|
||||
return iter->second->impl()->GetSslRole(role);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return transport_controller()->GetSslRole(role);
|
||||
}
|
||||
|
||||
void WebRtcSession::CreateOffer(
|
||||
@ -852,6 +821,8 @@ void WebRtcSession::CreateAnswer(CreateSessionDescriptionObserver* observer,
|
||||
|
||||
bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
|
||||
std::string* err_desc) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
|
||||
// Takes the ownership of |desc| regardless of the result.
|
||||
rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc);
|
||||
|
||||
@ -884,16 +855,24 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
|
||||
return BadLocalSdp(desc->type(), kCreateChannelFailed, err_desc);
|
||||
}
|
||||
|
||||
// Remove channel and transport proxies, if MediaContentDescription is
|
||||
// rejected.
|
||||
RemoveUnusedChannelsAndTransports(local_desc_->description());
|
||||
// Remove unused channels if MediaContentDescription is rejected.
|
||||
RemoveUnusedChannels(local_desc_->description());
|
||||
|
||||
if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Kick starting the ice candidates allocation.
|
||||
StartCandidatesAllocation();
|
||||
if (remote_description()) {
|
||||
// Now that we have a local description, we can push down remote candidates
|
||||
// that we stored, and those from the remote description.
|
||||
if (!saved_candidates_.empty()) {
|
||||
// If there are saved candidates which arrived before the local
|
||||
// description was set, copy those to the remote description.
|
||||
CopySavedCandidates(remote_desc_.get());
|
||||
}
|
||||
// Push remote candidates in remote description to transport channels.
|
||||
UseCandidatesInSessionDescription(remote_desc_.get());
|
||||
}
|
||||
|
||||
// Update state and SSRC of local MediaStreams and DataChannels based on the
|
||||
// local session description.
|
||||
@ -911,6 +890,8 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
|
||||
|
||||
bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
|
||||
std::string* err_desc) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
|
||||
// Takes the ownership of |desc| regardless of the result.
|
||||
rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc);
|
||||
|
||||
@ -927,9 +908,8 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
|
||||
return BadRemoteSdp(desc->type(), kCreateChannelFailed, err_desc);
|
||||
}
|
||||
|
||||
// Remove channel and transport proxies, if MediaContentDescription is
|
||||
// rejected.
|
||||
RemoveUnusedChannelsAndTransports(desc->description());
|
||||
// Remove unused channels if MediaContentDescription is rejected.
|
||||
RemoveUnusedChannels(desc->description());
|
||||
|
||||
// NOTE: Candidates allocation will be initiated only when SetLocalDescription
|
||||
// is called.
|
||||
@ -988,6 +968,8 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
|
||||
bool WebRtcSession::UpdateSessionState(
|
||||
Action action, cricket::ContentSource source,
|
||||
std::string* err_desc) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
|
||||
// If there's already a pending error then no state transition should happen.
|
||||
// But all call-sites should be verifying this before calling us!
|
||||
ASSERT(error() == cricket::BaseSession::ERROR_NONE);
|
||||
@ -1021,7 +1003,21 @@ bool WebRtcSession::UpdateSessionState(
|
||||
if (!PushdownTransportDescription(source, cricket::CA_ANSWER, &td_err)) {
|
||||
return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc);
|
||||
}
|
||||
MaybeEnableMuxingSupport();
|
||||
const cricket::ContentGroup* local_bundle =
|
||||
BaseSession::local_description()->GetGroupByName(
|
||||
cricket::GROUP_TYPE_BUNDLE);
|
||||
const cricket::ContentGroup* remote_bundle =
|
||||
BaseSession::remote_description()->GetGroupByName(
|
||||
cricket::GROUP_TYPE_BUNDLE);
|
||||
if (local_bundle && remote_bundle) {
|
||||
// The answerer decides the transport to bundle on
|
||||
const cricket::ContentGroup* answer_bundle =
|
||||
(source == cricket::CS_LOCAL ? local_bundle : remote_bundle);
|
||||
if (!EnableBundle(*answer_bundle)) {
|
||||
LOG(LS_WARNING) << "Failed to enable BUNDLE.";
|
||||
return BadAnswerSdp(source, kEnableBundleFailed, err_desc);
|
||||
}
|
||||
}
|
||||
EnableChannels();
|
||||
SetState(source == cricket::CS_LOCAL ?
|
||||
STATE_SENTACCEPT : STATE_RECEIVEDACCEPT);
|
||||
@ -1070,32 +1066,101 @@ WebRtcSession::Action WebRtcSession::GetAction(const std::string& type) {
|
||||
|
||||
bool WebRtcSession::GetTransportStats(cricket::SessionStats* stats) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
return (GetChannelTransportStats(voice_channel(), stats) &&
|
||||
GetChannelTransportStats(video_channel(), stats) &&
|
||||
GetChannelTransportStats(data_channel(), stats));
|
||||
}
|
||||
|
||||
const auto get_transport_stats = [stats](const std::string& content_name,
|
||||
cricket::Transport* transport) {
|
||||
const std::string& transport_id = transport->content_name();
|
||||
stats->proxy_to_transport[content_name] = transport_id;
|
||||
if (stats->transport_stats.find(transport_id)
|
||||
!= stats->transport_stats.end()) {
|
||||
// Transport stats already done for this transport.
|
||||
bool WebRtcSession::GetChannelTransportStats(cricket::BaseChannel* ch,
|
||||
cricket::SessionStats* stats) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
if (!ch) {
|
||||
// Not using this channel.
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string& content_name = ch->content_name();
|
||||
const std::string& transport_name = ch->transport_name();
|
||||
stats->proxy_to_transport[content_name] = transport_name;
|
||||
if (stats->transport_stats.find(transport_name) !=
|
||||
stats->transport_stats.end()) {
|
||||
// Transport stats already done for this transport.
|
||||
return true;
|
||||
}
|
||||
|
||||
cricket::TransportStats tstats;
|
||||
if (!transport_controller()->GetStats(transport_name, &tstats)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
stats->transport_stats[transport_name] = tstats;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRtcSession::GetLocalCertificate(
|
||||
const std::string& transport_name,
|
||||
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
return transport_controller()->GetLocalCertificate(transport_name,
|
||||
certificate);
|
||||
}
|
||||
|
||||
bool WebRtcSession::GetRemoteSSLCertificate(const std::string& transport_name,
|
||||
rtc::SSLCertificate** cert) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
return transport_controller()->GetRemoteSSLCertificate(transport_name, cert);
|
||||
}
|
||||
|
||||
cricket::BaseChannel* WebRtcSession::GetChannel(
|
||||
const std::string& content_name) {
|
||||
if (voice_channel() && voice_channel()->content_name() == content_name) {
|
||||
return voice_channel();
|
||||
}
|
||||
if (video_channel() && video_channel()->content_name() == content_name) {
|
||||
return video_channel();
|
||||
}
|
||||
if (data_channel() && data_channel()->content_name() == content_name) {
|
||||
return data_channel();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) {
|
||||
const std::string* first_content_name = bundle.FirstContentName();
|
||||
if (!first_content_name) {
|
||||
LOG(LS_WARNING) << "Tried to BUNDLE with no contents.";
|
||||
return false;
|
||||
}
|
||||
const std::string& transport_name = *first_content_name;
|
||||
cricket::BaseChannel* first_channel = GetChannel(transport_name);
|
||||
|
||||
auto maybe_set_transport = [this, bundle, transport_name,
|
||||
first_channel](cricket::BaseChannel* ch) {
|
||||
if (!ch || !bundle.HasContentName(ch->content_name())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cricket::TransportStats tstats;
|
||||
if (!transport->GetStats(&tstats)) {
|
||||
return false;
|
||||
if (ch->transport_name() == transport_name) {
|
||||
LOG(LS_INFO) << "BUNDLE already enabled for " << ch->content_name()
|
||||
<< " on " << transport_name << ".";
|
||||
return true;
|
||||
}
|
||||
|
||||
stats->transport_stats[transport_id] = tstats;
|
||||
if (!ch->SetTransport(transport_name)) {
|
||||
LOG(LS_WARNING) << "Failed to enable BUNDLE for " << ch->content_name();
|
||||
return false;
|
||||
}
|
||||
LOG(LS_INFO) << "Enabled BUNDLE for " << ch->content_name() << " on "
|
||||
<< transport_name << ".";
|
||||
return true;
|
||||
};
|
||||
|
||||
for (const auto& kv : transport_proxies()) {
|
||||
cricket::Transport* transport = kv.second->impl();
|
||||
if (transport && !get_transport_stats(kv.first, transport)) {
|
||||
return false;
|
||||
}
|
||||
if (!maybe_set_transport(voice_channel()) ||
|
||||
!maybe_set_transport(video_channel()) ||
|
||||
!maybe_set_transport(data_channel())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1401,13 +1466,18 @@ void WebRtcSession::ResetIceRestartLatch() {
|
||||
|
||||
void WebRtcSession::OnCertificateReady(
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
|
||||
SetCertificate(certificate);
|
||||
transport_controller()->SetLocalCertificate(certificate);
|
||||
}
|
||||
|
||||
bool WebRtcSession::waiting_for_certificate_for_testing() const {
|
||||
return webrtc_session_desc_factory_->waiting_for_certificate_for_testing();
|
||||
}
|
||||
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>&
|
||||
WebRtcSession::certificate_for_testing() {
|
||||
return transport_controller()->certificate_for_testing();
|
||||
}
|
||||
|
||||
void WebRtcSession::SetIceConnectionState(
|
||||
PeerConnectionInterface::IceConnectionState state) {
|
||||
if (ice_connection_state_ == state) {
|
||||
@ -1418,6 +1488,8 @@ void WebRtcSession::SetIceConnectionState(
|
||||
// WebRtcSession does not implement "kIceConnectionClosed" (that is handled
|
||||
// within PeerConnection). This switch statement should compile away when
|
||||
// ASSERTs are disabled.
|
||||
LOG(LS_INFO) << "Changing IceConnectionState " << ice_connection_state_
|
||||
<< " => " << state;
|
||||
switch (ice_connection_state_) {
|
||||
case PeerConnectionInterface::kIceConnectionNew:
|
||||
ASSERT(state == PeerConnectionInterface::kIceConnectionChecking);
|
||||
@ -1458,70 +1530,52 @@ void WebRtcSession::SetIceConnectionState(
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSession::OnTransportRequestSignaling(
|
||||
cricket::Transport* transport) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
transport->OnSignalingReady();
|
||||
if (ice_observer_) {
|
||||
ice_observer_->OnIceGatheringChange(
|
||||
PeerConnectionInterface::kIceGatheringGathering);
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSession::OnTransportConnecting(cricket::Transport* transport) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
// start monitoring for the write state of the transport.
|
||||
OnTransportWritable(transport);
|
||||
}
|
||||
|
||||
void WebRtcSession::OnTransportWritable(cricket::Transport* transport) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
if (transport->all_channels_writable()) {
|
||||
SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
|
||||
} else if (transport->HasChannels()) {
|
||||
// If the current state is Connected or Completed, then there were writable
|
||||
// channels but now there are not, so the next state must be Disconnected.
|
||||
if (ice_connection_state_ ==
|
||||
PeerConnectionInterface::kIceConnectionConnected ||
|
||||
ice_connection_state_ ==
|
||||
PeerConnectionInterface::kIceConnectionCompleted) {
|
||||
SetIceConnectionState(
|
||||
PeerConnectionInterface::kIceConnectionDisconnected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSession::OnTransportCompleted(cricket::Transport* transport) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
PeerConnectionInterface::IceConnectionState old_state = ice_connection_state_;
|
||||
SetIceConnectionState(PeerConnectionInterface::kIceConnectionCompleted);
|
||||
// Only report once when Ice connection is completed.
|
||||
if (old_state != PeerConnectionInterface::kIceConnectionCompleted) {
|
||||
cricket::TransportStats stats;
|
||||
if (metrics_observer_ && transport->GetStats(&stats)) {
|
||||
ReportBestConnectionState(stats);
|
||||
ReportNegotiatedCiphers(stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSession::OnTransportFailed(cricket::Transport* transport) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed);
|
||||
}
|
||||
|
||||
void WebRtcSession::OnTransportReceiving(cricket::Transport* transport) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
// The ice connection is considered receiving if at least one transport is
|
||||
// receiving on any channels.
|
||||
bool receiving = false;
|
||||
for (const auto& kv : transport_proxies()) {
|
||||
cricket::Transport* transport = kv.second->impl();
|
||||
if (transport && transport->any_channel_receiving()) {
|
||||
receiving = true;
|
||||
void WebRtcSession::OnTransportControllerConnectionState(
|
||||
cricket::IceConnectionState state) {
|
||||
switch (state) {
|
||||
case cricket::kIceConnectionConnecting:
|
||||
// If the current state is Connected or Completed, then there were
|
||||
// writable channels but now there are not, so the next state must
|
||||
// be Disconnected.
|
||||
// kIceConnectionConnecting is currently used as the default,
|
||||
// un-connected state by the TransportController, so its only use is
|
||||
// detecting disconnections.
|
||||
if (ice_connection_state_ ==
|
||||
PeerConnectionInterface::kIceConnectionConnected ||
|
||||
ice_connection_state_ ==
|
||||
PeerConnectionInterface::kIceConnectionCompleted) {
|
||||
SetIceConnectionState(
|
||||
PeerConnectionInterface::kIceConnectionDisconnected);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cricket::kIceConnectionFailed:
|
||||
SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed);
|
||||
break;
|
||||
case cricket::kIceConnectionConnected:
|
||||
LOG(LS_INFO) << "Changing to ICE connected state because "
|
||||
<< "all transports are writable.";
|
||||
SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
|
||||
break;
|
||||
case cricket::kIceConnectionCompleted:
|
||||
LOG(LS_INFO) << "Changing to ICE completed state because "
|
||||
<< "all transports are complete.";
|
||||
if (ice_connection_state_ !=
|
||||
PeerConnectionInterface::kIceConnectionConnected) {
|
||||
// If jumping directly from "checking" to "connected",
|
||||
// signal "connected" first.
|
||||
SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
|
||||
}
|
||||
SetIceConnectionState(PeerConnectionInterface::kIceConnectionCompleted);
|
||||
if (metrics_observer_) {
|
||||
ReportTransportStats();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSession::OnTransportControllerReceiving(bool receiving) {
|
||||
SetIceConnectionReceiving(receiving);
|
||||
}
|
||||
|
||||
@ -1535,18 +1589,27 @@ void WebRtcSession::SetIceConnectionReceiving(bool receiving) {
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSession::OnTransportProxyCandidatesReady(
|
||||
cricket::TransportProxy* proxy, const cricket::Candidates& candidates) {
|
||||
void WebRtcSession::OnTransportControllerCandidatesGathered(
|
||||
const std::string& transport_name,
|
||||
const cricket::Candidates& candidates) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
ProcessNewLocalCandidate(proxy->content_name(), candidates);
|
||||
}
|
||||
int sdp_mline_index;
|
||||
if (!GetLocalCandidateMediaIndex(transport_name, &sdp_mline_index)) {
|
||||
LOG(LS_ERROR) << "OnTransportControllerCandidatesGathered: content name "
|
||||
<< transport_name << " not found";
|
||||
return;
|
||||
}
|
||||
|
||||
void WebRtcSession::OnCandidatesAllocationDone() {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
if (ice_observer_) {
|
||||
ice_observer_->OnIceGatheringChange(
|
||||
PeerConnectionInterface::kIceGatheringComplete);
|
||||
ice_observer_->OnIceComplete();
|
||||
for (cricket::Candidates::const_iterator citer = candidates.begin();
|
||||
citer != candidates.end(); ++citer) {
|
||||
// Use transport_name as the candidate media id.
|
||||
JsepIceCandidate candidate(transport_name, sdp_mline_index, *citer);
|
||||
if (ice_observer_) {
|
||||
ice_observer_->OnIceCandidate(&candidate);
|
||||
}
|
||||
if (local_desc_) {
|
||||
local_desc_->AddCandidate(&candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1562,29 +1625,6 @@ void WebRtcSession::EnableChannels() {
|
||||
data_channel_->Enable(true);
|
||||
}
|
||||
|
||||
void WebRtcSession::ProcessNewLocalCandidate(
|
||||
const std::string& content_name,
|
||||
const cricket::Candidates& candidates) {
|
||||
int sdp_mline_index;
|
||||
if (!GetLocalCandidateMediaIndex(content_name, &sdp_mline_index)) {
|
||||
LOG(LS_ERROR) << "ProcessNewLocalCandidate: content name "
|
||||
<< content_name << " not found";
|
||||
return;
|
||||
}
|
||||
|
||||
for (cricket::Candidates::const_iterator citer = candidates.begin();
|
||||
citer != candidates.end(); ++citer) {
|
||||
// Use content_name as the candidate media id.
|
||||
JsepIceCandidate candidate(content_name, sdp_mline_index, *citer);
|
||||
if (ice_observer_) {
|
||||
ice_observer_->OnIceCandidate(&candidate);
|
||||
}
|
||||
if (local_desc_) {
|
||||
local_desc_->AddCandidate(&candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the media index for a local ice candidate given the content name.
|
||||
bool WebRtcSession::GetLocalCandidateMediaIndex(const std::string& content_name,
|
||||
int* sdp_mline_index) {
|
||||
@ -1649,7 +1689,8 @@ bool WebRtcSession::UseCandidate(
|
||||
candidates.push_back(candidate->candidate());
|
||||
// Invoking BaseSession method to handle remote candidates.
|
||||
std::string error;
|
||||
if (OnRemoteCandidates(content.name, candidates, &error)) {
|
||||
if (transport_controller()->AddRemoteCandidates(content.name, candidates,
|
||||
&error)) {
|
||||
// Candidates successfully submitted for checking.
|
||||
if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew ||
|
||||
ice_connection_state_ ==
|
||||
@ -1673,8 +1714,7 @@ bool WebRtcSession::UseCandidate(
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebRtcSession::RemoveUnusedChannelsAndTransports(
|
||||
const SessionDescription* desc) {
|
||||
void WebRtcSession::RemoveUnusedChannels(const SessionDescription* desc) {
|
||||
// Destroy video_channel_ first since it may have a pointer to the
|
||||
// voice_channel_.
|
||||
const cricket::ContentInfo* video_info =
|
||||
@ -1684,7 +1724,6 @@ void WebRtcSession::RemoveUnusedChannelsAndTransports(
|
||||
SignalVideoChannelDestroyed();
|
||||
const std::string content_name = video_channel_->content_name();
|
||||
channel_manager_->DestroyVideoChannel(video_channel_.release());
|
||||
DestroyTransportProxy(content_name);
|
||||
}
|
||||
|
||||
const cricket::ContentInfo* voice_info =
|
||||
@ -1694,7 +1733,6 @@ void WebRtcSession::RemoveUnusedChannelsAndTransports(
|
||||
SignalVoiceChannelDestroyed();
|
||||
const std::string content_name = voice_channel_->content_name();
|
||||
channel_manager_->DestroyVoiceChannel(voice_channel_.release());
|
||||
DestroyTransportProxy(content_name);
|
||||
}
|
||||
|
||||
const cricket::ContentInfo* data_info =
|
||||
@ -1704,7 +1742,6 @@ void WebRtcSession::RemoveUnusedChannelsAndTransports(
|
||||
SignalDataChannelDestroyed();
|
||||
const std::string content_name = data_channel_->content_name();
|
||||
channel_manager_->DestroyDataChannel(data_channel_.release());
|
||||
DestroyTransportProxy(content_name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1749,7 +1786,7 @@ bool WebRtcSession::CreateChannels(const SessionDescription* desc) {
|
||||
}
|
||||
}
|
||||
|
||||
// Enable bundle before when kMaxBundle policy is in effect.
|
||||
// Enable BUNDLE immediately when kBundlePolicyMaxBundle is in effect.
|
||||
if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) {
|
||||
const cricket::ContentGroup* bundle_group = desc->GetGroupByName(
|
||||
cricket::GROUP_TYPE_BUNDLE);
|
||||
@ -1757,7 +1794,7 @@ bool WebRtcSession::CreateChannels(const SessionDescription* desc) {
|
||||
LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified";
|
||||
return false;
|
||||
}
|
||||
if (!BaseSession::BundleContentGroup(bundle_group)) {
|
||||
if (!EnableBundle(*bundle_group)) {
|
||||
LOG(LS_WARNING) << "max-bundle failed to enable bundling.";
|
||||
return false;
|
||||
}
|
||||
@ -1768,7 +1805,8 @@ bool WebRtcSession::CreateChannels(const SessionDescription* desc) {
|
||||
|
||||
bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) {
|
||||
voice_channel_.reset(channel_manager_->CreateVoiceChannel(
|
||||
media_controller_.get(), this, content->name, true, audio_options_));
|
||||
media_controller_.get(), transport_controller(), content->name, true,
|
||||
audio_options_));
|
||||
if (!voice_channel_) {
|
||||
return false;
|
||||
}
|
||||
@ -1780,7 +1818,8 @@ bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) {
|
||||
|
||||
bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) {
|
||||
video_channel_.reset(channel_manager_->CreateVideoChannel(
|
||||
media_controller_.get(), this, content->name, true, video_options_));
|
||||
media_controller_.get(), transport_controller(), content->name, true,
|
||||
video_options_));
|
||||
if (!video_channel_) {
|
||||
return false;
|
||||
}
|
||||
@ -1793,7 +1832,7 @@ bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) {
|
||||
bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) {
|
||||
bool sctp = (data_channel_type_ == cricket::DCT_SCTP);
|
||||
data_channel_.reset(channel_manager_->CreateDataChannel(
|
||||
this, content->name, !sctp, data_channel_type_));
|
||||
transport_controller(), content->name, !sctp, data_channel_type_));
|
||||
if (!data_channel_) {
|
||||
return false;
|
||||
}
|
||||
@ -1974,7 +2013,6 @@ bool WebRtcSession::ReadyToUseRemoteCandidate(
|
||||
const SessionDescriptionInterface* remote_desc,
|
||||
bool* valid) {
|
||||
*valid = true;;
|
||||
cricket::TransportProxy* transport_proxy = NULL;
|
||||
|
||||
const SessionDescriptionInterface* current_remote_desc =
|
||||
remote_desc ? remote_desc : remote_description();
|
||||
@ -1996,12 +2034,53 @@ bool WebRtcSession::ReadyToUseRemoteCandidate(
|
||||
|
||||
cricket::ContentInfo content =
|
||||
current_remote_desc->description()->contents()[mediacontent_index];
|
||||
transport_proxy = GetTransportProxy(content.name);
|
||||
cricket::BaseChannel* channel = GetChannel(content.name);
|
||||
if (!channel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return transport_proxy && transport_proxy->local_description_set() &&
|
||||
transport_proxy->remote_description_set();
|
||||
return transport_controller()->ReadyForRemoteCandidates(
|
||||
channel->transport_name());
|
||||
}
|
||||
|
||||
void WebRtcSession::OnTransportControllerGatheringState(
|
||||
cricket::IceGatheringState state) {
|
||||
ASSERT(signaling_thread()->IsCurrent());
|
||||
if (state == cricket::kIceGatheringGathering) {
|
||||
if (ice_observer_) {
|
||||
ice_observer_->OnIceGatheringChange(
|
||||
PeerConnectionInterface::kIceGatheringGathering);
|
||||
}
|
||||
} else if (state == cricket::kIceGatheringComplete) {
|
||||
if (ice_observer_) {
|
||||
ice_observer_->OnIceGatheringChange(
|
||||
PeerConnectionInterface::kIceGatheringComplete);
|
||||
ice_observer_->OnIceComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSession::ReportTransportStats() {
|
||||
// Use a set so we don't report the same stats twice if two channels share
|
||||
// a transport.
|
||||
std::set<std::string> transport_names;
|
||||
if (voice_channel()) {
|
||||
transport_names.insert(voice_channel()->transport_name());
|
||||
}
|
||||
if (video_channel()) {
|
||||
transport_names.insert(video_channel()->transport_name());
|
||||
}
|
||||
if (data_channel()) {
|
||||
transport_names.insert(data_channel()->transport_name());
|
||||
}
|
||||
for (const auto& name : transport_names) {
|
||||
cricket::TransportStats stats;
|
||||
if (transport_controller()->GetStats(name, &stats)) {
|
||||
ReportBestConnectionState(stats);
|
||||
ReportNegotiatedCiphers(stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Walk through the ConnectionInfos to gather best connection usage
|
||||
// for IPv4 and IPv6.
|
||||
void WebRtcSession::ReportBestConnectionState(
|
||||
@ -2069,13 +2148,13 @@ void WebRtcSession::ReportNegotiatedCiphers(
|
||||
|
||||
PeerConnectionMetricsName srtp_name;
|
||||
PeerConnectionMetricsName ssl_name;
|
||||
if (stats.content_name == cricket::CN_AUDIO) {
|
||||
if (stats.transport_name == cricket::CN_AUDIO) {
|
||||
srtp_name = kAudioSrtpCipher;
|
||||
ssl_name = kAudioSslCipher;
|
||||
} else if (stats.content_name == cricket::CN_VIDEO) {
|
||||
} else if (stats.transport_name == cricket::CN_VIDEO) {
|
||||
srtp_name = kVideoSrtpCipher;
|
||||
ssl_name = kVideoSslCipher;
|
||||
} else if (stats.content_name == cricket::CN_DATA) {
|
||||
} else if (stats.transport_name == cricket::CN_DATA) {
|
||||
srtp_name = kDataSrtpCipher;
|
||||
ssl_name = kDataSslCipher;
|
||||
} else {
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#define TALK_APP_WEBRTC_WEBRTCSESSION_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "talk/app/webrtc/datachannel.h"
|
||||
#include "talk/app/webrtc/dtmfsender.h"
|
||||
@ -49,7 +50,6 @@ class BaseChannel;
|
||||
class ChannelManager;
|
||||
class DataChannel;
|
||||
class StatsReport;
|
||||
class Transport;
|
||||
class VideoCapturer;
|
||||
class VideoChannel;
|
||||
class VoiceChannel;
|
||||
@ -77,6 +77,8 @@ extern const char kSessionError[];
|
||||
extern const char kSessionErrorDesc[];
|
||||
extern const char kDtlsSetupFailureRtp[];
|
||||
extern const char kDtlsSetupFailureRtcp[];
|
||||
extern const char kEnableBundleFailed[];
|
||||
|
||||
// Maximum number of received video streams that will be processed by webrtc
|
||||
// even if they are not signalled beforehand.
|
||||
extern const int kMaxUnsignalledRecvStreams;
|
||||
@ -235,6 +237,19 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
// This avoids exposing the internal structures used to track them.
|
||||
virtual bool GetTransportStats(cricket::SessionStats* stats);
|
||||
|
||||
// Get stats for a specific channel
|
||||
bool GetChannelTransportStats(cricket::BaseChannel* ch,
|
||||
cricket::SessionStats* stats);
|
||||
|
||||
// virtual so it can be mocked in unit tests
|
||||
virtual bool GetLocalCertificate(
|
||||
const std::string& transport_name,
|
||||
rtc::scoped_refptr<rtc::RTCCertificate>* certificate);
|
||||
|
||||
// Caller owns returned certificate
|
||||
virtual bool GetRemoteSSLCertificate(const std::string& transport_name,
|
||||
rtc::SSLCertificate** cert);
|
||||
|
||||
// Implements DataChannelFactory.
|
||||
rtc::scoped_refptr<DataChannel> CreateDataChannel(
|
||||
const std::string& label,
|
||||
@ -254,6 +269,7 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
|
||||
// For unit test.
|
||||
bool waiting_for_certificate_for_testing() const;
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate_for_testing();
|
||||
|
||||
void set_metrics_observer(
|
||||
webrtc::MetricsObserverInterface* metrics_observer) {
|
||||
@ -269,9 +285,6 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
kAnswer,
|
||||
};
|
||||
|
||||
// Invokes ConnectChannels() on transport proxies, which initiates ice
|
||||
// candidates allocation.
|
||||
bool StartCandidatesAllocation();
|
||||
bool UpdateSessionState(Action action, cricket::ContentSource source,
|
||||
std::string* err_desc);
|
||||
static Action GetAction(const std::string& type);
|
||||
@ -281,25 +294,13 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
cricket::ContentSource source,
|
||||
std::string* error_desc);
|
||||
|
||||
|
||||
// Transport related callbacks, override from cricket::BaseSession.
|
||||
virtual void OnTransportRequestSignaling(cricket::Transport* transport);
|
||||
virtual void OnTransportConnecting(cricket::Transport* transport);
|
||||
virtual void OnTransportWritable(cricket::Transport* transport);
|
||||
virtual void OnTransportCompleted(cricket::Transport* transport);
|
||||
virtual void OnTransportFailed(cricket::Transport* transport);
|
||||
virtual void OnTransportProxyCandidatesReady(
|
||||
cricket::TransportProxy* proxy,
|
||||
const cricket::Candidates& candidates);
|
||||
virtual void OnCandidatesAllocationDone();
|
||||
void OnTransportReceiving(cricket::Transport* transport) override;
|
||||
cricket::BaseChannel* GetChannel(const std::string& content_name);
|
||||
// Cause all the BaseChannels in the bundle group to have the same
|
||||
// transport channel.
|
||||
bool EnableBundle(const cricket::ContentGroup& bundle);
|
||||
|
||||
// Enables media channels to allow sending of media.
|
||||
void EnableChannels();
|
||||
// Creates a JsepIceCandidate and adds it to the local session description
|
||||
// and notify observers. Called when a new local candidate have been found.
|
||||
void ProcessNewLocalCandidate(const std::string& content_name,
|
||||
const cricket::Candidates& candidates);
|
||||
// Returns the media index for a local ice candidate given the content name.
|
||||
// Returns false if the local session description does not have a media
|
||||
// content called |content_name|.
|
||||
@ -312,8 +313,7 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
bool UseCandidate(const IceCandidateInterface* candidate);
|
||||
// Deletes the corresponding channel of contents that don't exist in |desc|.
|
||||
// |desc| can be null. This means that all channels are deleted.
|
||||
void RemoveUnusedChannelsAndTransports(
|
||||
const cricket::SessionDescription* desc);
|
||||
void RemoveUnusedChannels(const cricket::SessionDescription* desc);
|
||||
|
||||
// Allocates media channels based on the |desc|. If |desc| doesn't have
|
||||
// the BUNDLE option, this method will disable BUNDLE in PortAllocator.
|
||||
@ -362,10 +362,20 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
const SessionDescriptionInterface* remote_desc,
|
||||
bool* valid);
|
||||
|
||||
void OnTransportControllerConnectionState(cricket::IceConnectionState state);
|
||||
void OnTransportControllerReceiving(bool receiving);
|
||||
void OnTransportControllerGatheringState(cricket::IceGatheringState state);
|
||||
void OnTransportControllerCandidatesGathered(
|
||||
const std::string& transport_name,
|
||||
const cricket::Candidates& candidates);
|
||||
|
||||
std::string GetSessionErrorMsg();
|
||||
|
||||
// Invoked when OnTransportCompleted is signaled to gather the usage
|
||||
// of IPv4/IPv6 as best connection.
|
||||
// Invoked when TransportController connection completion is signaled.
|
||||
// Reports stats for all transports in use.
|
||||
void ReportTransportStats();
|
||||
|
||||
// Gather the usage of IPv4/IPv6 as best connection.
|
||||
void ReportBestConnectionState(const cricket::TransportStats& stats);
|
||||
|
||||
void ReportNegotiatedCiphers(const cricket::TransportStats& stats);
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "talk/app/webrtc/audiotrack.h"
|
||||
#include "talk/app/webrtc/fakemetricsobserver.h"
|
||||
#include "talk/app/webrtc/jsepicecandidate.h"
|
||||
@ -163,8 +165,8 @@ static void InjectAfter(const std::string& line,
|
||||
const std::string& newlines,
|
||||
std::string* message) {
|
||||
const std::string tmp = line + newlines;
|
||||
rtc::replace_substrs(line.c_str(), line.length(),
|
||||
tmp.c_str(), tmp.length(), message);
|
||||
rtc::replace_substrs(line.c_str(), line.length(), tmp.c_str(), tmp.length(),
|
||||
message);
|
||||
}
|
||||
|
||||
class MockIceObserver : public webrtc::IceObserver {
|
||||
@ -244,12 +246,52 @@ class WebRtcSessionForTest : public webrtc::WebRtcSession {
|
||||
}
|
||||
virtual ~WebRtcSessionForTest() {}
|
||||
|
||||
using cricket::BaseSession::GetTransportProxy;
|
||||
// Note that these methods are only safe to use if the signaling thread
|
||||
// is the same as the worker thread
|
||||
cricket::TransportChannel* voice_rtp_transport_channel() {
|
||||
return rtp_transport_channel(voice_channel());
|
||||
}
|
||||
|
||||
cricket::TransportChannel* voice_rtcp_transport_channel() {
|
||||
return rtcp_transport_channel(voice_channel());
|
||||
}
|
||||
|
||||
cricket::TransportChannel* video_rtp_transport_channel() {
|
||||
return rtp_transport_channel(video_channel());
|
||||
}
|
||||
|
||||
cricket::TransportChannel* video_rtcp_transport_channel() {
|
||||
return rtcp_transport_channel(video_channel());
|
||||
}
|
||||
|
||||
cricket::TransportChannel* data_rtp_transport_channel() {
|
||||
return rtp_transport_channel(data_channel());
|
||||
}
|
||||
|
||||
cricket::TransportChannel* data_rtcp_transport_channel() {
|
||||
return rtcp_transport_channel(data_channel());
|
||||
}
|
||||
|
||||
using webrtc::WebRtcSession::SetAudioPlayout;
|
||||
using webrtc::WebRtcSession::SetAudioSend;
|
||||
using webrtc::WebRtcSession::SetCaptureDevice;
|
||||
using webrtc::WebRtcSession::SetVideoPlayout;
|
||||
using webrtc::WebRtcSession::SetVideoSend;
|
||||
|
||||
private:
|
||||
cricket::TransportChannel* rtp_transport_channel(cricket::BaseChannel* ch) {
|
||||
if (!ch) {
|
||||
return nullptr;
|
||||
}
|
||||
return ch->transport_channel();
|
||||
}
|
||||
|
||||
cricket::TransportChannel* rtcp_transport_channel(cricket::BaseChannel* ch) {
|
||||
if (!ch) {
|
||||
return nullptr;
|
||||
}
|
||||
return ch->rtcp_transport_channel();
|
||||
}
|
||||
};
|
||||
|
||||
class WebRtcSessionCreateSDPObserverForTest
|
||||
@ -375,9 +417,9 @@ class WebRtcSessionTest
|
||||
EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
|
||||
observer_.ice_gathering_state_);
|
||||
|
||||
EXPECT_TRUE(session_->Initialize(
|
||||
options_, constraints_.get(), dtls_identity_store.Pass(),
|
||||
rtc_configuration));
|
||||
EXPECT_TRUE(session_->Initialize(options_, constraints_.get(),
|
||||
dtls_identity_store.Pass(),
|
||||
rtc_configuration));
|
||||
session_->set_metrics_observer(metrics_observer_);
|
||||
}
|
||||
|
||||
@ -490,13 +532,6 @@ class WebRtcSessionTest
|
||||
session_->video_channel() != NULL);
|
||||
}
|
||||
|
||||
void CheckTransportChannels() const {
|
||||
EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
|
||||
EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
|
||||
EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
|
||||
EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
|
||||
}
|
||||
|
||||
void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
|
||||
ASSERT_TRUE(session_.get() != NULL);
|
||||
const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
|
||||
@ -722,6 +757,7 @@ class WebRtcSessionTest
|
||||
}
|
||||
void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
|
||||
EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
|
||||
session_->MaybeStartGathering();
|
||||
}
|
||||
void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
|
||||
BaseSession::State expected_state) {
|
||||
@ -968,15 +1004,10 @@ class WebRtcSessionTest
|
||||
SetRemoteDescriptionWithoutError(new_answer);
|
||||
EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
|
||||
EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
|
||||
EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
|
||||
for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
|
||||
cricket::Candidate c0 = observer_.mline_0_candidates_[i];
|
||||
cricket::Candidate c1 = observer_.mline_1_candidates_[i];
|
||||
if (bundle) {
|
||||
EXPECT_TRUE(c0.IsEquivalent(c1));
|
||||
} else {
|
||||
EXPECT_FALSE(c0.IsEquivalent(c1));
|
||||
}
|
||||
if (bundle) {
|
||||
EXPECT_EQ(0, observer_.mline_1_candidates_.size());
|
||||
} else {
|
||||
EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
|
||||
}
|
||||
}
|
||||
// Tests that we can only send DTMF when the dtmf codec is supported.
|
||||
@ -1001,7 +1032,7 @@ class WebRtcSessionTest
|
||||
// initial ICE convergences.
|
||||
|
||||
class LoopbackNetworkConfiguration {
|
||||
public:
|
||||
public:
|
||||
LoopbackNetworkConfiguration()
|
||||
: test_ipv6_network_(false),
|
||||
test_extra_ipv4_network_(false),
|
||||
@ -1150,11 +1181,8 @@ class WebRtcSessionTest
|
||||
|
||||
// Clearing the rules, session should move back to completed state.
|
||||
loopback_network_manager.ClearRules(fss_.get());
|
||||
// Session is automatically calling OnSignalingReady after creation of
|
||||
// new portallocator session which will allocate new set of candidates.
|
||||
|
||||
LOG(LS_INFO) << "Firewall Rules cleared";
|
||||
|
||||
EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
|
||||
observer_.ice_connection_state_,
|
||||
kIceCandidatesTimeout);
|
||||
@ -1707,15 +1735,14 @@ TEST_P(WebRtcSessionTest, TestSetLocalNonDtlsAnswerWhenDtlsOn) {
|
||||
// a DTLS fingerprint when DTLS is required.
|
||||
TEST_P(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) {
|
||||
MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
|
||||
// Enable both SDES and DTLS, so that offer won't be outright rejected as a
|
||||
// result of using the "UDP/TLS/RTP/SAVPF" profile.
|
||||
InitWithDtls(GetParam());
|
||||
session_->SetSdesPolicy(cricket::SEC_ENABLED);
|
||||
SessionDescriptionInterface* offer = CreateOffer();
|
||||
cricket::MediaSessionOptions options;
|
||||
options.recv_video = true;
|
||||
rtc::scoped_ptr<SessionDescriptionInterface> temp_offer(
|
||||
CreateRemoteOffer(options, cricket::SEC_ENABLED));
|
||||
JsepSessionDescription* answer =
|
||||
CreateRemoteAnswer(offer, options, cricket::SEC_ENABLED);
|
||||
CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
|
||||
|
||||
// SetRemoteDescription and SetLocalDescription will take the ownership of
|
||||
// the offer and answer.
|
||||
@ -2017,7 +2044,7 @@ TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
|
||||
EXPECT_LT(0u, candidates->count());
|
||||
candidates = local_desc->candidates(1);
|
||||
ASSERT_TRUE(candidates != NULL);
|
||||
EXPECT_LT(0u, candidates->count());
|
||||
EXPECT_EQ(0u, candidates->count());
|
||||
|
||||
// Update the session descriptions.
|
||||
mediastream_signaling_.SendAudioVideoStream1();
|
||||
@ -2029,7 +2056,7 @@ TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
|
||||
EXPECT_LT(0u, candidates->count());
|
||||
candidates = local_desc->candidates(1);
|
||||
ASSERT_TRUE(candidates != NULL);
|
||||
EXPECT_LT(0u, candidates->count());
|
||||
EXPECT_EQ(0u, candidates->count());
|
||||
}
|
||||
|
||||
// Test that we can set a remote session description with remote candidates.
|
||||
@ -2073,23 +2100,17 @@ TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
|
||||
// Wait until at least one local candidate has been collected.
|
||||
EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
|
||||
kIceCandidatesTimeout);
|
||||
EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
|
||||
kIceCandidatesTimeout);
|
||||
|
||||
rtc::scoped_ptr<SessionDescriptionInterface> local_offer(CreateOffer());
|
||||
|
||||
ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
|
||||
EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
|
||||
ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
|
||||
EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count());
|
||||
|
||||
SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
|
||||
SetRemoteDescriptionWithoutError(remote_offer);
|
||||
SessionDescriptionInterface* answer = CreateAnswer(NULL);
|
||||
ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
|
||||
EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
|
||||
ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL);
|
||||
EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count());
|
||||
SetLocalDescriptionWithoutError(answer);
|
||||
}
|
||||
|
||||
@ -2131,8 +2152,14 @@ TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
|
||||
CreateAnswer(NULL);
|
||||
SetLocalDescriptionWithoutError(answer);
|
||||
|
||||
EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL);
|
||||
EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL);
|
||||
cricket::TransportChannel* voice_transport_channel =
|
||||
session_->voice_rtp_transport_channel();
|
||||
EXPECT_TRUE(voice_transport_channel != NULL);
|
||||
EXPECT_EQ(voice_transport_channel->transport_name(), "audio_content_name");
|
||||
cricket::TransportChannel* video_transport_channel =
|
||||
session_->video_rtp_transport_channel();
|
||||
EXPECT_TRUE(video_transport_channel != NULL);
|
||||
EXPECT_EQ(video_transport_channel->transport_name(), "video_content_name");
|
||||
EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
|
||||
EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
|
||||
}
|
||||
@ -2692,20 +2719,23 @@ TEST_F(WebRtcSessionTest, TestIgnoreCandidatesForUnusedTransportWhenBundling) {
|
||||
SessionDescriptionInterface* answer = CreateAnswer(NULL);
|
||||
SetLocalDescriptionWithoutError(answer);
|
||||
|
||||
EXPECT_EQ(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_EQ(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
|
||||
cricket::Transport* t = session_->GetTransport("audio");
|
||||
cricket::BaseChannel* voice_channel = session_->voice_channel();
|
||||
ASSERT(voice_channel != NULL);
|
||||
|
||||
// Checks if one of the transport channels contains a connection using a given
|
||||
// port.
|
||||
auto connection_with_remote_port = [t](int port) {
|
||||
cricket::TransportStats stats;
|
||||
t->GetStats(&stats);
|
||||
for (auto& chan_stat : stats.channel_stats) {
|
||||
for (auto& conn_info : chan_stat.connection_infos) {
|
||||
if (conn_info.remote_candidate.address().port() == port) {
|
||||
return true;
|
||||
auto connection_with_remote_port = [this, voice_channel](int port) {
|
||||
cricket::SessionStats stats;
|
||||
session_->GetChannelTransportStats(voice_channel, &stats);
|
||||
for (auto& kv : stats.transport_stats) {
|
||||
for (auto& chan_stat : kv.second.channel_stats) {
|
||||
for (auto& conn_info : chan_stat.connection_infos) {
|
||||
if (conn_info.remote_candidate.address().port() == port) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2758,7 +2788,7 @@ TEST_F(WebRtcSessionTest, TestIgnoreCandidatesForUnusedTransportWhenBundling) {
|
||||
EXPECT_FALSE(connection_with_remote_port(6000));
|
||||
}
|
||||
|
||||
// kBundlePolicyBalanced bundle policy and answer contains BUNDLE.
|
||||
// kBundlePolicyBalanced BUNDLE policy and answer contains BUNDLE.
|
||||
TEST_F(WebRtcSessionTest, TestBalancedBundleInAnswer) {
|
||||
InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
|
||||
mediastream_signaling_.SendAudioVideoStream1();
|
||||
@ -2769,19 +2799,19 @@ TEST_F(WebRtcSessionTest, TestBalancedBundleInAnswer) {
|
||||
SessionDescriptionInterface* offer = CreateOffer(options);
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
|
||||
EXPECT_NE(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_NE(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
|
||||
mediastream_signaling_.SendAudioVideoStream2();
|
||||
SessionDescriptionInterface* answer =
|
||||
CreateRemoteAnswer(session_->local_description());
|
||||
SetRemoteDescriptionWithoutError(answer);
|
||||
|
||||
EXPECT_EQ(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_EQ(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
}
|
||||
|
||||
// kBundlePolicyBalanced bundle policy but no BUNDLE in the answer.
|
||||
// kBundlePolicyBalanced BUNDLE policy but no BUNDLE in the answer.
|
||||
TEST_F(WebRtcSessionTest, TestBalancedNoBundleInAnswer) {
|
||||
InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
|
||||
mediastream_signaling_.SendAudioVideoStream1();
|
||||
@ -2792,8 +2822,8 @@ TEST_F(WebRtcSessionTest, TestBalancedNoBundleInAnswer) {
|
||||
SessionDescriptionInterface* offer = CreateOffer(options);
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
|
||||
EXPECT_NE(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_NE(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
|
||||
mediastream_signaling_.SendAudioVideoStream2();
|
||||
|
||||
@ -2807,8 +2837,8 @@ TEST_F(WebRtcSessionTest, TestBalancedNoBundleInAnswer) {
|
||||
modified_answer->Initialize(answer_copy, "1", "1");
|
||||
SetRemoteDescriptionWithoutError(modified_answer); //
|
||||
|
||||
EXPECT_NE(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_NE(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
}
|
||||
|
||||
// kBundlePolicyMaxBundle policy with BUNDLE in the answer.
|
||||
@ -2822,16 +2852,49 @@ TEST_F(WebRtcSessionTest, TestMaxBundleBundleInAnswer) {
|
||||
SessionDescriptionInterface* offer = CreateOffer(options);
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
|
||||
EXPECT_EQ(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_EQ(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
|
||||
mediastream_signaling_.SendAudioVideoStream2();
|
||||
SessionDescriptionInterface* answer =
|
||||
CreateRemoteAnswer(session_->local_description());
|
||||
SetRemoteDescriptionWithoutError(answer);
|
||||
|
||||
EXPECT_EQ(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_EQ(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
}
|
||||
|
||||
// kBundlePolicyMaxBundle policy with BUNDLE in the answer, but no
|
||||
// audio content in the answer.
|
||||
TEST_F(WebRtcSessionTest, TestMaxBundleRejectAudio) {
|
||||
InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
|
||||
mediastream_signaling_.SendAudioVideoStream1();
|
||||
|
||||
PeerConnectionInterface::RTCOfferAnswerOptions options;
|
||||
options.use_rtp_mux = true;
|
||||
|
||||
SessionDescriptionInterface* offer = CreateOffer(options);
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
|
||||
EXPECT_EQ(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
|
||||
mediastream_signaling_.SendAudioVideoStream2();
|
||||
cricket::MediaSessionOptions recv_options;
|
||||
recv_options.recv_audio = false;
|
||||
recv_options.recv_video = true;
|
||||
SessionDescriptionInterface* answer =
|
||||
CreateRemoteAnswer(session_->local_description(), recv_options);
|
||||
SetRemoteDescriptionWithoutError(answer);
|
||||
|
||||
EXPECT_TRUE(NULL == session_->voice_channel());
|
||||
EXPECT_TRUE(NULL != session_->video_rtp_transport_channel());
|
||||
|
||||
session_->Terminate();
|
||||
EXPECT_TRUE(NULL == session_->voice_rtp_transport_channel());
|
||||
EXPECT_TRUE(NULL == session_->voice_rtcp_transport_channel());
|
||||
EXPECT_TRUE(NULL == session_->video_rtp_transport_channel());
|
||||
EXPECT_TRUE(NULL == session_->video_rtcp_transport_channel());
|
||||
}
|
||||
|
||||
// kBundlePolicyMaxBundle policy but no BUNDLE in the answer.
|
||||
@ -2845,8 +2908,8 @@ TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInAnswer) {
|
||||
SessionDescriptionInterface* offer = CreateOffer(options);
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
|
||||
EXPECT_EQ(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_EQ(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
|
||||
mediastream_signaling_.SendAudioVideoStream2();
|
||||
|
||||
@ -2860,8 +2923,45 @@ TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInAnswer) {
|
||||
modified_answer->Initialize(answer_copy, "1", "1");
|
||||
SetRemoteDescriptionWithoutError(modified_answer);
|
||||
|
||||
EXPECT_EQ(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_EQ(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
}
|
||||
|
||||
// kBundlePolicyMaxBundle policy with BUNDLE in the remote offer.
|
||||
TEST_F(WebRtcSessionTest, TestMaxBundleBundleInRemoteOffer) {
|
||||
InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
|
||||
mediastream_signaling_.SendAudioVideoStream1();
|
||||
|
||||
SessionDescriptionInterface* offer = CreateRemoteOffer();
|
||||
SetRemoteDescriptionWithoutError(offer);
|
||||
|
||||
EXPECT_EQ(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
|
||||
mediastream_signaling_.SendAudioVideoStream2();
|
||||
SessionDescriptionInterface* answer = CreateAnswer(nullptr);
|
||||
SetLocalDescriptionWithoutError(answer);
|
||||
|
||||
EXPECT_EQ(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
}
|
||||
|
||||
// kBundlePolicyMaxBundle policy but no BUNDLE in the remote offer.
|
||||
TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInRemoteOffer) {
|
||||
InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
|
||||
mediastream_signaling_.SendAudioVideoStream1();
|
||||
|
||||
// Remove BUNDLE from the offer.
|
||||
rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
|
||||
cricket::SessionDescription* offer_copy = offer->description()->Copy();
|
||||
offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
|
||||
JsepSessionDescription* modified_offer =
|
||||
new JsepSessionDescription(JsepSessionDescription::kOffer);
|
||||
modified_offer->Initialize(offer_copy, "1", "1");
|
||||
|
||||
// Expect an error when applying the remote description
|
||||
SetRemoteDescriptionExpectError(JsepSessionDescription::kOffer,
|
||||
kCreateChannelFailed, modified_offer);
|
||||
}
|
||||
|
||||
// kBundlePolicyMaxCompat bundle policy and answer contains BUNDLE.
|
||||
@ -2875,8 +2975,8 @@ TEST_F(WebRtcSessionTest, TestMaxCompatBundleInAnswer) {
|
||||
SessionDescriptionInterface* offer = CreateOffer(options);
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
|
||||
EXPECT_NE(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_NE(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
|
||||
mediastream_signaling_.SendAudioVideoStream2();
|
||||
SessionDescriptionInterface* answer =
|
||||
@ -2885,11 +2985,11 @@ TEST_F(WebRtcSessionTest, TestMaxCompatBundleInAnswer) {
|
||||
|
||||
// This should lead to an audio-only call but isn't implemented
|
||||
// correctly yet.
|
||||
EXPECT_EQ(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_EQ(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
}
|
||||
|
||||
// kBundlePolicyMaxCompat bundle policy but no BUNDLE in the answer.
|
||||
// kBundlePolicyMaxCompat BUNDLE policy but no BUNDLE in the answer.
|
||||
TEST_F(WebRtcSessionTest, TestMaxCompatNoBundleInAnswer) {
|
||||
InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat);
|
||||
mediastream_signaling_.SendAudioVideoStream1();
|
||||
@ -2899,8 +2999,8 @@ TEST_F(WebRtcSessionTest, TestMaxCompatNoBundleInAnswer) {
|
||||
SessionDescriptionInterface* offer = CreateOffer(options);
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
|
||||
EXPECT_NE(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_NE(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
|
||||
mediastream_signaling_.SendAudioVideoStream2();
|
||||
|
||||
@ -2914,8 +3014,8 @@ TEST_F(WebRtcSessionTest, TestMaxCompatNoBundleInAnswer) {
|
||||
modified_answer->Initialize(answer_copy, "1", "1");
|
||||
SetRemoteDescriptionWithoutError(modified_answer); //
|
||||
|
||||
EXPECT_NE(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_NE(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
}
|
||||
|
||||
// kBundlePolicyMaxbundle and then we call SetRemoteDescription first.
|
||||
@ -2929,8 +3029,8 @@ TEST_F(WebRtcSessionTest, TestMaxBundleWithSetRemoteDescriptionFirst) {
|
||||
SessionDescriptionInterface* offer = CreateOffer(options);
|
||||
SetRemoteDescriptionWithoutError(offer);
|
||||
|
||||
EXPECT_EQ(session_->GetTransportProxy("audio")->impl(),
|
||||
session_->GetTransportProxy("video")->impl());
|
||||
EXPECT_EQ(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
}
|
||||
|
||||
TEST_F(WebRtcSessionTest, TestRequireRtcpMux) {
|
||||
@ -2941,16 +3041,16 @@ TEST_F(WebRtcSessionTest, TestRequireRtcpMux) {
|
||||
SessionDescriptionInterface* offer = CreateOffer(options);
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
|
||||
EXPECT_FALSE(session_->GetTransportProxy("audio")->impl()->HasChannel(2));
|
||||
EXPECT_FALSE(session_->GetTransportProxy("video")->impl()->HasChannel(2));
|
||||
EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
|
||||
EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
|
||||
|
||||
mediastream_signaling_.SendAudioVideoStream2();
|
||||
SessionDescriptionInterface* answer =
|
||||
CreateRemoteAnswer(session_->local_description());
|
||||
SetRemoteDescriptionWithoutError(answer);
|
||||
|
||||
EXPECT_FALSE(session_->GetTransportProxy("audio")->impl()->HasChannel(2));
|
||||
EXPECT_FALSE(session_->GetTransportProxy("video")->impl()->HasChannel(2));
|
||||
EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
|
||||
EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcSessionTest, TestNegotiateRtcpMux) {
|
||||
@ -2961,16 +3061,16 @@ TEST_F(WebRtcSessionTest, TestNegotiateRtcpMux) {
|
||||
SessionDescriptionInterface* offer = CreateOffer(options);
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
|
||||
EXPECT_TRUE(session_->GetTransportProxy("audio")->impl()->HasChannel(2));
|
||||
EXPECT_TRUE(session_->GetTransportProxy("video")->impl()->HasChannel(2));
|
||||
EXPECT_TRUE(session_->voice_rtcp_transport_channel() != NULL);
|
||||
EXPECT_TRUE(session_->video_rtcp_transport_channel() != NULL);
|
||||
|
||||
mediastream_signaling_.SendAudioVideoStream2();
|
||||
SessionDescriptionInterface* answer =
|
||||
CreateRemoteAnswer(session_->local_description());
|
||||
SetRemoteDescriptionWithoutError(answer);
|
||||
|
||||
EXPECT_FALSE(session_->GetTransportProxy("audio")->impl()->HasChannel(2));
|
||||
EXPECT_FALSE(session_->GetTransportProxy("video")->impl()->HasChannel(2));
|
||||
EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
|
||||
EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
|
||||
}
|
||||
|
||||
// This test verifies that SetLocalDescription and SetRemoteDescription fails
|
||||
@ -2991,11 +3091,11 @@ TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
|
||||
rtc::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
|
||||
xrtcp_mux.c_str(), xrtcp_mux.length(),
|
||||
&offer_str);
|
||||
JsepSessionDescription *local_offer =
|
||||
JsepSessionDescription* local_offer =
|
||||
new JsepSessionDescription(JsepSessionDescription::kOffer);
|
||||
EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
|
||||
SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
|
||||
JsepSessionDescription *remote_offer =
|
||||
JsepSessionDescription* remote_offer =
|
||||
new JsepSessionDescription(JsepSessionDescription::kOffer);
|
||||
EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
|
||||
SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
|
||||
@ -3258,8 +3358,8 @@ TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
|
||||
candidate1);
|
||||
EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
|
||||
SetRemoteDescriptionWithoutError(offer);
|
||||
ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL);
|
||||
ASSERT_TRUE(session_->GetTransportProxy("video") != NULL);
|
||||
ASSERT_TRUE(session_->voice_rtp_transport_channel() != NULL);
|
||||
ASSERT_TRUE(session_->video_rtp_transport_channel() != NULL);
|
||||
|
||||
// Pump for 1 second and verify that no candidates are generated.
|
||||
rtc::Thread::Current()->ProcessMessages(1000);
|
||||
@ -3268,8 +3368,6 @@ TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
|
||||
|
||||
SessionDescriptionInterface* answer = CreateAnswer(NULL);
|
||||
SetLocalDescriptionWithoutError(answer);
|
||||
EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated());
|
||||
EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated());
|
||||
EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
|
||||
}
|
||||
|
||||
@ -3304,7 +3402,7 @@ TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
|
||||
// will be set as per MediaSessionDescriptionFactory.
|
||||
std::string offer_str;
|
||||
offer->ToString(&offer_str);
|
||||
SessionDescriptionInterface *jsep_offer_str =
|
||||
SessionDescriptionInterface* jsep_offer_str =
|
||||
CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
|
||||
SetLocalDescriptionWithoutError(jsep_offer_str);
|
||||
EXPECT_FALSE(session_->voice_channel()->secure_required());
|
||||
@ -3657,8 +3755,8 @@ TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
|
||||
TEST_P(WebRtcSessionTest,
|
||||
TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
|
||||
MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
|
||||
VerifyMultipleAsyncCreateDescription(
|
||||
GetParam(), CreateSessionDescriptionRequest::kOffer);
|
||||
VerifyMultipleAsyncCreateDescription(GetParam(),
|
||||
CreateSessionDescriptionRequest::kOffer);
|
||||
}
|
||||
|
||||
// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
|
||||
@ -3881,31 +3979,31 @@ TEST_F(WebRtcSessionTest, TestSetSocketOptionBeforeBundle) {
|
||||
rtc::Socket::Option::OPT_RCVBUF, 8000);
|
||||
|
||||
int option_val;
|
||||
EXPECT_TRUE(session_->video_channel()->transport_channel()->GetOption(
|
||||
EXPECT_TRUE(session_->video_rtp_transport_channel()->GetOption(
|
||||
rtc::Socket::Option::OPT_SNDBUF, &option_val));
|
||||
EXPECT_EQ(4000, option_val);
|
||||
EXPECT_FALSE(session_->voice_channel()->transport_channel()->GetOption(
|
||||
EXPECT_FALSE(session_->voice_rtp_transport_channel()->GetOption(
|
||||
rtc::Socket::Option::OPT_SNDBUF, &option_val));
|
||||
|
||||
EXPECT_TRUE(session_->voice_channel()->transport_channel()->GetOption(
|
||||
EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
|
||||
rtc::Socket::Option::OPT_RCVBUF, &option_val));
|
||||
EXPECT_EQ(8000, option_val);
|
||||
EXPECT_FALSE(session_->video_channel()->transport_channel()->GetOption(
|
||||
EXPECT_FALSE(session_->video_rtp_transport_channel()->GetOption(
|
||||
rtc::Socket::Option::OPT_RCVBUF, &option_val));
|
||||
|
||||
EXPECT_NE(session_->voice_channel()->transport_channel(),
|
||||
session_->video_channel()->transport_channel());
|
||||
EXPECT_NE(session_->voice_rtp_transport_channel(),
|
||||
session_->video_rtp_transport_channel());
|
||||
|
||||
mediastream_signaling_.SendAudioVideoStream2();
|
||||
SessionDescriptionInterface* answer =
|
||||
CreateRemoteAnswer(session_->local_description());
|
||||
SetRemoteDescriptionWithoutError(answer);
|
||||
|
||||
EXPECT_TRUE(session_->voice_channel()->transport_channel()->GetOption(
|
||||
EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
|
||||
rtc::Socket::Option::OPT_SNDBUF, &option_val));
|
||||
EXPECT_EQ(4000, option_val);
|
||||
|
||||
EXPECT_TRUE(session_->voice_channel()->transport_channel()->GetOption(
|
||||
EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
|
||||
rtc::Socket::Option::OPT_RCVBUF, &option_val));
|
||||
EXPECT_EQ(8000, option_val);
|
||||
}
|
||||
@ -3941,6 +4039,7 @@ TEST_F(WebRtcSessionTest, CreateOffersAndShutdown) {
|
||||
// currently fails because upon disconnection and reconnection OnIceComplete is
|
||||
// called more than once without returning to IceGatheringGathering.
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
WebRtcSessionTests, WebRtcSessionTest,
|
||||
testing::Values(ALREADY_GENERATED, DTLS_IDENTITY_STORE));
|
||||
INSTANTIATE_TEST_CASE_P(WebRtcSessionTests,
|
||||
WebRtcSessionTest,
|
||||
testing::Values(ALREADY_GENERATED,
|
||||
DTLS_IDENTITY_STORE));
|
||||
|
||||
@ -165,9 +165,15 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
|
||||
WebRtcSession* session,
|
||||
const std::string& session_id,
|
||||
cricket::DataChannelType dct)
|
||||
: WebRtcSessionDescriptionFactory(
|
||||
signaling_thread, channel_manager, mediastream_signaling, nullptr,
|
||||
nullptr, session, session_id, dct, false) {
|
||||
: WebRtcSessionDescriptionFactory(signaling_thread,
|
||||
channel_manager,
|
||||
mediastream_signaling,
|
||||
nullptr,
|
||||
nullptr,
|
||||
session,
|
||||
session_id,
|
||||
dct,
|
||||
false) {
|
||||
LOG(LS_VERBOSE) << "DTLS-SRTP disabled.";
|
||||
}
|
||||
|
||||
@ -226,9 +232,9 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
|
||||
// We already have a certificate but we wait to do SetIdentity; if we do
|
||||
// it in the constructor then the caller has not had a chance to connect to
|
||||
// SignalIdentityReady.
|
||||
signaling_thread_->Post(this, MSG_USE_CONSTRUCTOR_CERTIFICATE,
|
||||
new rtc::ScopedRefMessageData<rtc::RTCCertificate>(
|
||||
certificate));
|
||||
signaling_thread_->Post(
|
||||
this, MSG_USE_CONSTRUCTOR_CERTIFICATE,
|
||||
new rtc::ScopedRefMessageData<rtc::RTCCertificate>(certificate));
|
||||
}
|
||||
|
||||
WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() {
|
||||
@ -254,8 +260,6 @@ WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() {
|
||||
delete msg.pdata;
|
||||
}
|
||||
}
|
||||
|
||||
transport_desc_factory_.set_certificate(nullptr);
|
||||
}
|
||||
|
||||
void WebRtcSessionDescriptionFactory::CreateOffer(
|
||||
|
||||
@ -90,13 +90,12 @@ class WebRtcSessionDescriptionFactory : public rtc::MessageHandler,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
// Construct with DTLS disabled.
|
||||
WebRtcSessionDescriptionFactory(
|
||||
rtc::Thread* signaling_thread,
|
||||
cricket::ChannelManager* channel_manager,
|
||||
MediaStreamSignaling* mediastream_signaling,
|
||||
WebRtcSession* session,
|
||||
const std::string& session_id,
|
||||
cricket::DataChannelType dct);
|
||||
WebRtcSessionDescriptionFactory(rtc::Thread* signaling_thread,
|
||||
cricket::ChannelManager* channel_manager,
|
||||
MediaStreamSignaling* mediastream_signaling,
|
||||
WebRtcSession* session,
|
||||
const std::string& session_id,
|
||||
cricket::DataChannelType dct);
|
||||
|
||||
// Construct with DTLS enabled using the specified |dtls_identity_store| to
|
||||
// generate a certificate.
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
#include "talk/media/webrtc/fakewebrtccall.h"
|
||||
#include "talk/media/webrtc/fakewebrtcvoiceengine.h"
|
||||
#include "talk/media/webrtc/webrtcvoiceengine.h"
|
||||
#include "webrtc/p2p/base/fakesession.h"
|
||||
#include "webrtc/p2p/base/faketransportcontroller.h"
|
||||
#include "talk/session/media/channel.h"
|
||||
|
||||
// Tests for the WebRtcVoiceEngine/VoiceChannel code.
|
||||
|
||||
@ -170,15 +170,17 @@ void RtpSendParametersFromMediaDescription(
|
||||
}
|
||||
|
||||
BaseChannel::BaseChannel(rtc::Thread* thread,
|
||||
MediaChannel* media_channel, BaseSession* session,
|
||||
const std::string& content_name, bool rtcp)
|
||||
MediaChannel* media_channel,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp)
|
||||
: worker_thread_(thread),
|
||||
session_(session),
|
||||
transport_controller_(transport_controller),
|
||||
media_channel_(media_channel),
|
||||
content_name_(content_name),
|
||||
rtcp_(rtcp),
|
||||
transport_channel_(NULL),
|
||||
rtcp_transport_channel_(NULL),
|
||||
rtcp_transport_enabled_(rtcp),
|
||||
transport_channel_(nullptr),
|
||||
rtcp_transport_channel_(nullptr),
|
||||
enabled_(false),
|
||||
writable_(false),
|
||||
rtp_ready_to_send_(false),
|
||||
@ -204,20 +206,31 @@ BaseChannel::~BaseChannel() {
|
||||
// the media channel may try to send on the dead transport channel. NULLing
|
||||
// is not an effective strategy since the sends will come on another thread.
|
||||
delete media_channel_;
|
||||
set_transport_channel(nullptr);
|
||||
set_rtcp_transport_channel(nullptr);
|
||||
// Note that we don't just call set_transport_channel(nullptr) because that
|
||||
// would call a pure virtual method which we can't do from a destructor.
|
||||
if (transport_channel_) {
|
||||
DisconnectFromTransportChannel(transport_channel_);
|
||||
transport_controller_->DestroyTransportChannel_w(
|
||||
transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
||||
}
|
||||
if (rtcp_transport_channel_) {
|
||||
DisconnectFromTransportChannel(rtcp_transport_channel_);
|
||||
transport_controller_->DestroyTransportChannel_w(
|
||||
transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
|
||||
}
|
||||
LOG(LS_INFO) << "Destroyed channel";
|
||||
}
|
||||
|
||||
bool BaseChannel::Init() {
|
||||
if (!SetTransportChannels(session(), rtcp())) {
|
||||
if (!SetTransport(content_name())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetDtlsSrtpCiphers(transport_channel(), false)) {
|
||||
return false;
|
||||
}
|
||||
if (rtcp() && !SetDtlsSrtpCiphers(rtcp_transport_channel(), true)) {
|
||||
if (rtcp_transport_enabled() &&
|
||||
!SetDtlsSrtpCiphers(rtcp_transport_channel(), true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -231,29 +244,35 @@ void BaseChannel::Deinit() {
|
||||
media_channel_->SetInterface(NULL);
|
||||
}
|
||||
|
||||
bool BaseChannel::SetTransportChannels(BaseSession* session, bool rtcp) {
|
||||
return worker_thread_->Invoke<bool>(Bind(
|
||||
&BaseChannel::SetTransportChannels_w, this, session, rtcp));
|
||||
bool BaseChannel::SetTransport(const std::string& transport_name) {
|
||||
return worker_thread_->Invoke<bool>(
|
||||
Bind(&BaseChannel::SetTransport_w, this, transport_name));
|
||||
}
|
||||
|
||||
bool BaseChannel::SetTransportChannels_w(BaseSession* session, bool rtcp) {
|
||||
bool BaseChannel::SetTransport_w(const std::string& transport_name) {
|
||||
ASSERT(worker_thread_ == rtc::Thread::Current());
|
||||
|
||||
set_transport_channel(session->CreateChannel(
|
||||
content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTP));
|
||||
if (transport_name == transport_name_) {
|
||||
// Nothing to do if transport name isn't changing
|
||||
return true;
|
||||
}
|
||||
|
||||
set_transport_channel(transport_controller_->CreateTransportChannel_w(
|
||||
transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP));
|
||||
if (!transport_channel()) {
|
||||
return false;
|
||||
}
|
||||
if (rtcp) {
|
||||
set_rtcp_transport_channel(session->CreateChannel(
|
||||
content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTCP));
|
||||
if (rtcp_transport_enabled()) {
|
||||
LOG(LS_INFO) << "Create RTCP TransportChannel for " << content_name()
|
||||
<< " on " << transport_name << " transport ";
|
||||
set_rtcp_transport_channel(transport_controller_->CreateTransportChannel_w(
|
||||
transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP));
|
||||
if (!rtcp_transport_channel()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
set_rtcp_transport_channel(nullptr);
|
||||
}
|
||||
|
||||
transport_name_ = transport_name;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -261,42 +280,62 @@ void BaseChannel::set_transport_channel(TransportChannel* new_tc) {
|
||||
ASSERT(worker_thread_ == rtc::Thread::Current());
|
||||
|
||||
TransportChannel* old_tc = transport_channel_;
|
||||
|
||||
if (old_tc == new_tc) {
|
||||
if (!old_tc && !new_tc) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
ASSERT(old_tc != new_tc);
|
||||
|
||||
if (old_tc) {
|
||||
DisconnectFromTransportChannel(old_tc);
|
||||
session()->DestroyChannel(
|
||||
content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
||||
transport_controller_->DestroyTransportChannel_w(
|
||||
transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
||||
}
|
||||
|
||||
transport_channel_ = new_tc;
|
||||
|
||||
if (new_tc) {
|
||||
ConnectToTransportChannel(new_tc);
|
||||
for (const auto& pair : socket_options_) {
|
||||
new_tc->SetOption(pair.first, pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Update aggregate writable/ready-to-send state between RTP and RTCP upon
|
||||
// setting new channel
|
||||
UpdateWritableState_w();
|
||||
SetReadyToSend(false, new_tc && new_tc->writable());
|
||||
}
|
||||
|
||||
void BaseChannel::set_rtcp_transport_channel(TransportChannel* new_tc) {
|
||||
ASSERT(worker_thread_ == rtc::Thread::Current());
|
||||
|
||||
TransportChannel* old_tc = rtcp_transport_channel_;
|
||||
|
||||
if (old_tc == new_tc) {
|
||||
if (!old_tc && !new_tc) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
ASSERT(old_tc != new_tc);
|
||||
|
||||
if (old_tc) {
|
||||
DisconnectFromTransportChannel(old_tc);
|
||||
session()->DestroyChannel(
|
||||
content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTCP);
|
||||
transport_controller_->DestroyTransportChannel_w(
|
||||
transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
|
||||
}
|
||||
|
||||
rtcp_transport_channel_ = new_tc;
|
||||
|
||||
if (new_tc) {
|
||||
ConnectToTransportChannel(new_tc);
|
||||
for (const auto& pair : rtcp_socket_options_) {
|
||||
new_tc->SetOption(pair.first, pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Update aggregate writable/ready-to-send state between RTP and RTCP upon
|
||||
// setting new channel
|
||||
UpdateWritableState_w();
|
||||
SetReadyToSend(true, new_tc && new_tc->writable());
|
||||
}
|
||||
|
||||
void BaseChannel::ConnectToTransportChannel(TransportChannel* tc) {
|
||||
@ -407,9 +446,13 @@ int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
|
||||
switch (type) {
|
||||
case ST_RTP:
|
||||
channel = transport_channel_;
|
||||
socket_options_.push_back(
|
||||
std::pair<rtc::Socket::Option, int>(opt, value));
|
||||
break;
|
||||
case ST_RTCP:
|
||||
channel = rtcp_transport_channel_;
|
||||
rtcp_socket_options_.push_back(
|
||||
std::pair<rtc::Socket::Option, int>(opt, value));
|
||||
break;
|
||||
}
|
||||
return channel ? channel->SetOption(opt, value) : -1;
|
||||
@ -417,12 +460,7 @@ int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
|
||||
|
||||
void BaseChannel::OnWritableState(TransportChannel* channel) {
|
||||
ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
|
||||
if (transport_channel_->writable()
|
||||
&& (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
|
||||
ChannelWritable_w();
|
||||
} else {
|
||||
ChannelNotWritable_w();
|
||||
}
|
||||
UpdateWritableState_w();
|
||||
}
|
||||
|
||||
void BaseChannel::OnChannelRead(TransportChannel* channel,
|
||||
@ -440,26 +478,25 @@ void BaseChannel::OnChannelRead(TransportChannel* channel,
|
||||
}
|
||||
|
||||
void BaseChannel::OnReadyToSend(TransportChannel* channel) {
|
||||
SetReadyToSend(channel, true);
|
||||
ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
|
||||
SetReadyToSend(channel == rtcp_transport_channel_, true);
|
||||
}
|
||||
|
||||
void BaseChannel::SetReadyToSend(TransportChannel* channel, bool ready) {
|
||||
ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
|
||||
if (channel == transport_channel_) {
|
||||
void BaseChannel::SetReadyToSend(bool rtcp, bool ready) {
|
||||
if (rtcp) {
|
||||
rtcp_ready_to_send_ = ready;
|
||||
} else {
|
||||
rtp_ready_to_send_ = ready;
|
||||
}
|
||||
if (channel == rtcp_transport_channel_) {
|
||||
rtcp_ready_to_send_ = ready;
|
||||
}
|
||||
|
||||
if (!ready) {
|
||||
// Notify the MediaChannel when either rtp or rtcp channel can't send.
|
||||
media_channel_->OnReadyToSend(false);
|
||||
} else if (rtp_ready_to_send_ &&
|
||||
// In the case of rtcp mux |rtcp_transport_channel_| will be null.
|
||||
(rtcp_ready_to_send_ || !rtcp_transport_channel_)) {
|
||||
if (rtp_ready_to_send_ &&
|
||||
// In the case of rtcp mux |rtcp_transport_channel_| will be null.
|
||||
(rtcp_ready_to_send_ || !rtcp_transport_channel_)) {
|
||||
// Notify the MediaChannel when both rtp and rtcp channel can send.
|
||||
media_channel_->OnReadyToSend(true);
|
||||
} else {
|
||||
// Notify the MediaChannel when either rtp or rtcp channel can't send.
|
||||
media_channel_->OnReadyToSend(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -581,7 +618,7 @@ bool BaseChannel::SendPacket(bool rtcp, rtc::Buffer* packet,
|
||||
if (ret != static_cast<int>(packet->size())) {
|
||||
if (channel->GetError() == EWOULDBLOCK) {
|
||||
LOG(LS_WARNING) << "Got EWOULDBLOCK from socket.";
|
||||
SetReadyToSend(channel, false);
|
||||
SetReadyToSend(rtcp, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -715,14 +752,21 @@ void BaseChannel::DisableMedia_w() {
|
||||
ChangeState();
|
||||
}
|
||||
|
||||
void BaseChannel::UpdateWritableState_w() {
|
||||
if (transport_channel_ && transport_channel_->writable() &&
|
||||
(!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
|
||||
ChannelWritable_w();
|
||||
} else {
|
||||
ChannelNotWritable_w();
|
||||
}
|
||||
}
|
||||
|
||||
void BaseChannel::ChannelWritable_w() {
|
||||
ASSERT(worker_thread_ == rtc::Thread::Current());
|
||||
if (writable_)
|
||||
return;
|
||||
|
||||
LOG(LS_INFO) << "Channel socket writable ("
|
||||
<< transport_channel_->content_name() << ", "
|
||||
<< transport_channel_->component() << ")"
|
||||
LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
|
||||
<< (was_ever_writable_ ? "" : " for the first time");
|
||||
|
||||
std::vector<ConnectionInfo> infos;
|
||||
@ -739,13 +783,13 @@ void BaseChannel::ChannelWritable_w() {
|
||||
// If we're doing DTLS-SRTP, now is the time.
|
||||
if (!was_ever_writable_ && ShouldSetupDtlsSrtp()) {
|
||||
if (!SetupDtlsSrtp(false)) {
|
||||
SignalDtlsSetupFailure(this, false);
|
||||
SignalDtlsSetupFailure_w(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rtcp_transport_channel_) {
|
||||
if (!SetupDtlsSrtp(true)) {
|
||||
SignalDtlsSetupFailure(this, true);
|
||||
SignalDtlsSetupFailure_w(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -788,8 +832,8 @@ bool BaseChannel::ShouldSetupDtlsSrtp() const {
|
||||
bool BaseChannel::SetupDtlsSrtp(bool rtcp_channel) {
|
||||
bool ret = false;
|
||||
|
||||
TransportChannel *channel = rtcp_channel ?
|
||||
rtcp_transport_channel_ : transport_channel_;
|
||||
TransportChannel* channel =
|
||||
rtcp_channel ? rtcp_transport_channel_ : transport_channel_;
|
||||
|
||||
// No DTLS
|
||||
if (!channel->IsDtlsActive())
|
||||
@ -884,9 +928,7 @@ void BaseChannel::ChannelNotWritable_w() {
|
||||
if (!writable_)
|
||||
return;
|
||||
|
||||
LOG(LS_INFO) << "Channel socket not writable ("
|
||||
<< transport_channel_->content_name() << ", "
|
||||
<< transport_channel_->component() << ")";
|
||||
LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
|
||||
writable_ = false;
|
||||
ChangeState();
|
||||
}
|
||||
@ -985,7 +1027,8 @@ void BaseChannel::ActivateRtcpMux() {
|
||||
void BaseChannel::ActivateRtcpMux_w() {
|
||||
if (!rtcp_mux_filter_.IsActive()) {
|
||||
rtcp_mux_filter_.SetActive();
|
||||
set_rtcp_transport_channel(NULL);
|
||||
set_rtcp_transport_channel(nullptr);
|
||||
rtcp_transport_enabled_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1004,7 +1047,11 @@ bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action,
|
||||
ret = rtcp_mux_filter_.SetAnswer(enable, src);
|
||||
if (ret && rtcp_mux_filter_.IsActive()) {
|
||||
// We activated RTCP mux, close down the RTCP transport.
|
||||
set_rtcp_transport_channel(NULL);
|
||||
LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
|
||||
<< " by destroying RTCP transport channel for "
|
||||
<< transport_name();
|
||||
set_rtcp_transport_channel(nullptr);
|
||||
rtcp_transport_enabled_ = false;
|
||||
}
|
||||
break;
|
||||
case CA_UPDATE:
|
||||
@ -1231,14 +1278,16 @@ void BaseChannel::FlushRtcpMessages() {
|
||||
VoiceChannel::VoiceChannel(rtc::Thread* thread,
|
||||
MediaEngineInterface* media_engine,
|
||||
VoiceMediaChannel* media_channel,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp)
|
||||
: BaseChannel(thread, media_channel, session, content_name,
|
||||
: BaseChannel(thread,
|
||||
media_channel,
|
||||
transport_controller,
|
||||
content_name,
|
||||
rtcp),
|
||||
media_engine_(media_engine),
|
||||
received_media_(false) {
|
||||
}
|
||||
received_media_(false) {}
|
||||
|
||||
VoiceChannel::~VoiceChannel() {
|
||||
StopAudioMonitor();
|
||||
@ -1264,11 +1313,12 @@ bool VoiceChannel::SetRemoteRenderer(uint32 ssrc, AudioRenderer* renderer) {
|
||||
media_channel(), ssrc, renderer));
|
||||
}
|
||||
|
||||
bool VoiceChannel::SetAudioSend(uint32 ssrc, bool mute,
|
||||
bool VoiceChannel::SetAudioSend(uint32 ssrc,
|
||||
bool mute,
|
||||
const AudioOptions* options,
|
||||
AudioRenderer* renderer) {
|
||||
return InvokeOnWorker(Bind(&VoiceMediaChannel::SetAudioSend,
|
||||
media_channel(), ssrc, mute, options, renderer));
|
||||
return InvokeOnWorker(Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
|
||||
ssrc, mute, options, renderer));
|
||||
}
|
||||
|
||||
// TODO(juberti): Handle early media the right way. We should get an explicit
|
||||
@ -1583,14 +1633,16 @@ void VoiceChannel::GetSrtpCiphers(std::vector<std::string>* ciphers) const {
|
||||
|
||||
VideoChannel::VideoChannel(rtc::Thread* thread,
|
||||
VideoMediaChannel* media_channel,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp)
|
||||
: BaseChannel(thread, media_channel, session, content_name,
|
||||
: BaseChannel(thread,
|
||||
media_channel,
|
||||
transport_controller,
|
||||
content_name,
|
||||
rtcp),
|
||||
renderer_(NULL),
|
||||
previous_we_(rtc::WE_CLOSE) {
|
||||
}
|
||||
previous_we_(rtc::WE_CLOSE) {}
|
||||
|
||||
bool VideoChannel::Init() {
|
||||
if (!BaseChannel::Init()) {
|
||||
@ -1683,10 +1735,11 @@ bool VideoChannel::RequestIntraFrame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VideoChannel::SetVideoSend(uint32 ssrc, bool mute,
|
||||
bool VideoChannel::SetVideoSend(uint32 ssrc,
|
||||
bool mute,
|
||||
const VideoOptions* options) {
|
||||
return InvokeOnWorker(Bind(&VideoMediaChannel::SetVideoSend,
|
||||
media_channel(), ssrc, mute, options));
|
||||
return InvokeOnWorker(Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
|
||||
ssrc, mute, options));
|
||||
}
|
||||
|
||||
void VideoChannel::ChangeState() {
|
||||
@ -2021,13 +2074,16 @@ void VideoChannel::GetSrtpCiphers(std::vector<std::string>* ciphers) const {
|
||||
|
||||
DataChannel::DataChannel(rtc::Thread* thread,
|
||||
DataMediaChannel* media_channel,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp)
|
||||
: BaseChannel(thread, media_channel, session, content_name, rtcp),
|
||||
: BaseChannel(thread,
|
||||
media_channel,
|
||||
transport_controller,
|
||||
content_name,
|
||||
rtcp),
|
||||
data_channel_type_(cricket::DCT_NONE),
|
||||
ready_to_send_data_(false) {
|
||||
}
|
||||
ready_to_send_data_(false) {}
|
||||
|
||||
DataChannel::~DataChannel() {
|
||||
StopMediaMonitor();
|
||||
|
||||
@ -30,12 +30,15 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include "talk/media/base/mediachannel.h"
|
||||
#include "talk/media/base/mediaengine.h"
|
||||
#include "talk/media/base/streamparams.h"
|
||||
#include "talk/media/base/videocapturer.h"
|
||||
#include "webrtc/p2p/base/session.h"
|
||||
#include "webrtc/p2p/base/transportcontroller.h"
|
||||
#include "webrtc/p2p/client/socketmonitor.h"
|
||||
#include "talk/session/media/audiomonitor.h"
|
||||
#include "talk/session/media/bundlefilter.h"
|
||||
@ -74,8 +77,11 @@ class BaseChannel
|
||||
public MediaChannel::NetworkInterface,
|
||||
public ConnectionStatsGetter {
|
||||
public:
|
||||
BaseChannel(rtc::Thread* thread, MediaChannel* channel, BaseSession* session,
|
||||
const std::string& content_name, bool rtcp);
|
||||
BaseChannel(rtc::Thread* thread,
|
||||
MediaChannel* channel,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp);
|
||||
virtual ~BaseChannel();
|
||||
bool Init();
|
||||
// Deinit may be called multiple times and is simply ignored if it's alreay
|
||||
@ -83,8 +89,8 @@ class BaseChannel
|
||||
void Deinit();
|
||||
|
||||
rtc::Thread* worker_thread() const { return worker_thread_; }
|
||||
BaseSession* session() const { return session_; }
|
||||
const std::string& content_name() { return content_name_; }
|
||||
const std::string& content_name() const { return content_name_; }
|
||||
const std::string& transport_name() const { return transport_name_; }
|
||||
TransportChannel* transport_channel() const {
|
||||
return transport_channel_;
|
||||
}
|
||||
@ -109,6 +115,7 @@ class BaseChannel
|
||||
// description doesn't support RTCP mux, setting the remote
|
||||
// description will fail.
|
||||
void ActivateRtcpMux();
|
||||
bool SetTransport(const std::string& transport_name);
|
||||
bool PushdownLocalDescription(const SessionDescription* local_desc,
|
||||
ContentAction action,
|
||||
std::string* error_desc);
|
||||
@ -135,7 +142,7 @@ class BaseChannel
|
||||
void StartConnectionMonitor(int cms);
|
||||
void StopConnectionMonitor();
|
||||
// For ConnectionStatsGetter, used by ConnectionMonitor
|
||||
virtual bool GetConnectionStats(ConnectionInfos* infos) override;
|
||||
bool GetConnectionStats(ConnectionInfos* infos) override;
|
||||
|
||||
void set_srtp_signal_silent_time(uint32 silent_time) {
|
||||
srtp_filter_.set_signal_silent_time(silent_time);
|
||||
@ -158,19 +165,16 @@ class BaseChannel
|
||||
sigslot::signal1<BaseChannel*> SignalFirstPacketReceived;
|
||||
|
||||
// Made public for easier testing.
|
||||
void SetReadyToSend(TransportChannel* channel, bool ready);
|
||||
void SetReadyToSend(bool rtcp, bool ready);
|
||||
|
||||
// Only public for unit tests. Otherwise, consider protected.
|
||||
virtual int SetOption(SocketType type, rtc::Socket::Option o, int val);
|
||||
|
||||
protected:
|
||||
virtual MediaChannel* media_channel() const { return media_channel_; }
|
||||
// Sets the transport_channel_ and rtcp_transport_channel_. If
|
||||
// |rtcp| is false, set rtcp_transport_channel_ is set to NULL. Get
|
||||
// the transport channels from |session|.
|
||||
// TODO(pthatcher): Pass in a Transport instead of a BaseSession.
|
||||
bool SetTransportChannels(BaseSession* session, bool rtcp);
|
||||
bool SetTransportChannels_w(BaseSession* session, bool rtcp);
|
||||
// Sets the |transport_channel_| (and |rtcp_transport_channel_|, if |rtcp_| is
|
||||
// true). Gets the transport channels from |transport_controller_|.
|
||||
bool SetTransport_w(const std::string& transport_name);
|
||||
void set_transport_channel(TransportChannel* transport);
|
||||
void set_rtcp_transport_channel(TransportChannel* transport);
|
||||
bool was_ever_writable() const { return was_ever_writable_; }
|
||||
@ -185,9 +189,11 @@ class BaseChannel
|
||||
}
|
||||
bool IsReadyToReceive() const;
|
||||
bool IsReadyToSend() const;
|
||||
rtc::Thread* signaling_thread() { return session_->signaling_thread(); }
|
||||
rtc::Thread* signaling_thread() {
|
||||
return transport_controller_->signaling_thread();
|
||||
}
|
||||
SrtpFilter* srtp_filter() { return &srtp_filter_; }
|
||||
bool rtcp() const { return rtcp_; }
|
||||
bool rtcp_transport_enabled() const { return rtcp_transport_enabled_; }
|
||||
|
||||
void ConnectToTransportChannel(TransportChannel* tc);
|
||||
void DisconnectFromTransportChannel(TransportChannel* tc);
|
||||
@ -217,12 +223,9 @@ class BaseChannel
|
||||
void HandlePacket(bool rtcp, rtc::Buffer* packet,
|
||||
const rtc::PacketTime& packet_time);
|
||||
|
||||
// Apply the new local/remote session description.
|
||||
void OnNewLocalDescription(BaseSession* session, ContentAction action);
|
||||
void OnNewRemoteDescription(BaseSession* session, ContentAction action);
|
||||
|
||||
void EnableMedia_w();
|
||||
void DisableMedia_w();
|
||||
void UpdateWritableState_w();
|
||||
void ChannelWritable_w();
|
||||
void ChannelNotWritable_w();
|
||||
bool AddRecvStream_w(const StreamParams& sp);
|
||||
@ -293,15 +296,18 @@ class BaseChannel
|
||||
|
||||
private:
|
||||
rtc::Thread* worker_thread_;
|
||||
BaseSession* session_;
|
||||
TransportController* transport_controller_;
|
||||
MediaChannel* media_channel_;
|
||||
std::vector<StreamParams> local_streams_;
|
||||
std::vector<StreamParams> remote_streams_;
|
||||
|
||||
const std::string content_name_;
|
||||
bool rtcp_;
|
||||
std::string transport_name_;
|
||||
bool rtcp_transport_enabled_;
|
||||
TransportChannel* transport_channel_;
|
||||
std::vector<std::pair<rtc::Socket::Option, int> > socket_options_;
|
||||
TransportChannel* rtcp_transport_channel_;
|
||||
std::vector<std::pair<rtc::Socket::Option, int> > rtcp_socket_options_;
|
||||
SrtpFilter srtp_filter_;
|
||||
RtcpMuxFilter rtcp_mux_filter_;
|
||||
BundleFilter bundle_filter_;
|
||||
@ -323,16 +329,21 @@ class BaseChannel
|
||||
// and input/output level monitoring.
|
||||
class VoiceChannel : public BaseChannel {
|
||||
public:
|
||||
VoiceChannel(rtc::Thread* thread, MediaEngineInterface* media_engine,
|
||||
VoiceMediaChannel* channel, BaseSession* session,
|
||||
const std::string& content_name, bool rtcp);
|
||||
VoiceChannel(rtc::Thread* thread,
|
||||
MediaEngineInterface* media_engine,
|
||||
VoiceMediaChannel* channel,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp);
|
||||
~VoiceChannel();
|
||||
bool Init();
|
||||
bool SetRemoteRenderer(uint32 ssrc, AudioRenderer* renderer);
|
||||
|
||||
// Configure sending media on the stream with SSRC |ssrc|
|
||||
// If there is only one sending stream SSRC 0 can be used.
|
||||
bool SetAudioSend(uint32 ssrc, bool mute, const AudioOptions* options,
|
||||
bool SetAudioSend(uint32 ssrc,
|
||||
bool mute,
|
||||
const AudioOptions* options,
|
||||
AudioRenderer* renderer);
|
||||
|
||||
// downcasts a MediaChannel
|
||||
@ -429,8 +440,10 @@ class VoiceChannel : public BaseChannel {
|
||||
// VideoChannel is a specialization for video.
|
||||
class VideoChannel : public BaseChannel {
|
||||
public:
|
||||
VideoChannel(rtc::Thread* thread, VideoMediaChannel* channel,
|
||||
BaseSession* session, const std::string& content_name,
|
||||
VideoChannel(rtc::Thread* thread,
|
||||
VideoMediaChannel* channel,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp);
|
||||
~VideoChannel();
|
||||
bool Init();
|
||||
@ -529,7 +542,7 @@ class DataChannel : public BaseChannel {
|
||||
public:
|
||||
DataChannel(rtc::Thread* thread,
|
||||
DataMediaChannel* media_channel,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp);
|
||||
~DataChannel();
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
#include "talk/media/base/rtpdump.h"
|
||||
#include "talk/media/base/screencastid.h"
|
||||
#include "talk/media/base/testutils.h"
|
||||
#include "webrtc/p2p/base/fakesession.h"
|
||||
#include "webrtc/p2p/base/faketransportcontroller.h"
|
||||
#include "talk/session/media/channel.h"
|
||||
#include "webrtc/base/fileutils.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
@ -73,12 +73,12 @@ static const uint32 kSsrc3 = 0x3333;
|
||||
static const int kAudioPts[] = {0, 8};
|
||||
static const int kVideoPts[] = {97, 99};
|
||||
|
||||
template<class ChannelT,
|
||||
class MediaChannelT,
|
||||
class ContentT,
|
||||
class CodecT,
|
||||
class MediaInfoT,
|
||||
class OptionsT>
|
||||
template <class ChannelT,
|
||||
class MediaChannelT,
|
||||
class ContentT,
|
||||
class CodecT,
|
||||
class MediaInfoT,
|
||||
class OptionsT>
|
||||
class Traits {
|
||||
public:
|
||||
typedef ChannelT Channel;
|
||||
@ -98,25 +98,21 @@ class VoiceTraits : public Traits<cricket::VoiceChannel,
|
||||
cricket::AudioContentDescription,
|
||||
cricket::AudioCodec,
|
||||
cricket::VoiceMediaInfo,
|
||||
cricket::AudioOptions> {
|
||||
};
|
||||
cricket::AudioOptions> {};
|
||||
|
||||
class VideoTraits : public Traits<cricket::VideoChannel,
|
||||
cricket::FakeVideoMediaChannel,
|
||||
cricket::VideoContentDescription,
|
||||
cricket::VideoCodec,
|
||||
cricket::VideoMediaInfo,
|
||||
cricket::VideoOptions> {
|
||||
};
|
||||
cricket::VideoOptions> {};
|
||||
|
||||
class DataTraits : public Traits<cricket::DataChannel,
|
||||
cricket::FakeDataMediaChannel,
|
||||
cricket::DataContentDescription,
|
||||
cricket::DataCodec,
|
||||
cricket::DataMediaInfo,
|
||||
cricket::DataOptions> {
|
||||
};
|
||||
|
||||
cricket::DataOptions> {};
|
||||
|
||||
rtc::StreamInterface* Open(const std::string& path) {
|
||||
return rtc::Filesystem::OpenFile(
|
||||
@ -130,10 +126,12 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
enum Flags { RTCP = 0x1, RTCP_MUX = 0x2, SECURE = 0x4, SSRC_MUX = 0x8,
|
||||
DTLS = 0x10 };
|
||||
|
||||
ChannelTest(const uint8* rtp_data, int rtp_len,
|
||||
const uint8* rtcp_data, int rtcp_len)
|
||||
: session1_(true),
|
||||
session2_(false),
|
||||
ChannelTest(const uint8* rtp_data,
|
||||
int rtp_len,
|
||||
const uint8* rtcp_data,
|
||||
int rtcp_len)
|
||||
: transport_controller1_(cricket::ICEROLE_CONTROLLING),
|
||||
transport_controller2_(cricket::ICEROLE_CONTROLLED),
|
||||
media_channel1_(NULL),
|
||||
media_channel2_(NULL),
|
||||
rtp_packet_(reinterpret_cast<const char*>(rtp_data), rtp_len),
|
||||
@ -141,8 +139,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
media_info_callbacks1_(),
|
||||
media_info_callbacks2_(),
|
||||
ssrc_(0),
|
||||
error_(T::MediaChannel::ERROR_NONE) {
|
||||
}
|
||||
error_(T::MediaChannel::ERROR_NONE) {}
|
||||
|
||||
void CreateChannels(int flags1, int flags2) {
|
||||
CreateChannels(new typename T::MediaChannel(NULL, typename T::Options()),
|
||||
@ -154,9 +151,11 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
int flags1, int flags2, rtc::Thread* thread) {
|
||||
media_channel1_ = ch1;
|
||||
media_channel2_ = ch2;
|
||||
channel1_.reset(CreateChannel(thread, &media_engine_, ch1, &session1_,
|
||||
channel1_.reset(CreateChannel(thread, &media_engine_, ch1,
|
||||
&transport_controller1_,
|
||||
(flags1 & RTCP) != 0));
|
||||
channel2_.reset(CreateChannel(thread, &media_engine_, ch2, &session2_,
|
||||
channel2_.reset(CreateChannel(thread, &media_engine_, ch2,
|
||||
&transport_controller2_,
|
||||
(flags2 & RTCP) != 0));
|
||||
channel1_->SignalMediaMonitor.connect(
|
||||
this, &ChannelTest<T>::OnMediaMonitor);
|
||||
@ -179,15 +178,17 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
|
||||
if (flags1 & DTLS) {
|
||||
// Confirmed to work with KT_RSA and KT_ECDSA.
|
||||
session1_.set_ssl_rtccertificate(rtc::RTCCertificate::Create(
|
||||
rtc::scoped_ptr<rtc::SSLIdentity>(rtc::SSLIdentity::Generate(
|
||||
"session1", rtc::KT_DEFAULT)).Pass()));
|
||||
transport_controller1_.SetLocalCertificate(rtc::RTCCertificate::Create(
|
||||
rtc::scoped_ptr<rtc::SSLIdentity>(
|
||||
rtc::SSLIdentity::Generate("session1", rtc::KT_DEFAULT))
|
||||
.Pass()));
|
||||
}
|
||||
if (flags2 & DTLS) {
|
||||
// Confirmed to work with KT_RSA and KT_ECDSA.
|
||||
session2_.set_ssl_rtccertificate(rtc::RTCCertificate::Create(
|
||||
rtc::scoped_ptr<rtc::SSLIdentity>(rtc::SSLIdentity::Generate(
|
||||
"session2", rtc::KT_DEFAULT)).Pass()));
|
||||
transport_controller2_.SetLocalCertificate(rtc::RTCCertificate::Create(
|
||||
rtc::scoped_ptr<rtc::SSLIdentity>(
|
||||
rtc::SSLIdentity::Generate("session2", rtc::KT_DEFAULT))
|
||||
.Pass()));
|
||||
}
|
||||
|
||||
// Add stream information (SSRC) to the local content but not to the remote
|
||||
@ -204,13 +205,14 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
AddLegacyStreamInContent(kSsrc2, flags2, &remote_media_content2_);
|
||||
}
|
||||
}
|
||||
typename T::Channel* CreateChannel(rtc::Thread* thread,
|
||||
cricket::MediaEngineInterface* engine,
|
||||
typename T::MediaChannel* ch,
|
||||
cricket::BaseSession* session,
|
||||
bool rtcp) {
|
||||
typename T::Channel* CreateChannel(
|
||||
rtc::Thread* thread,
|
||||
cricket::MediaEngineInterface* engine,
|
||||
typename T::MediaChannel* ch,
|
||||
cricket::TransportController* transport_controller,
|
||||
bool rtcp) {
|
||||
typename T::Channel* channel = new typename T::Channel(
|
||||
thread, engine, ch, session, cricket::CN_AUDIO, rtcp);
|
||||
thread, engine, ch, transport_controller, cricket::CN_AUDIO, rtcp);
|
||||
if (!channel->Init()) {
|
||||
delete channel;
|
||||
channel = NULL;
|
||||
@ -226,7 +228,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
result = channel2_->SetRemoteContent(&remote_media_content1_,
|
||||
CA_OFFER, NULL);
|
||||
if (result) {
|
||||
session1_.Connect(&session2_);
|
||||
transport_controller1_.Connect(&transport_controller2_);
|
||||
|
||||
result = channel2_->SetLocalContent(&local_media_content2_,
|
||||
CA_ANSWER, NULL);
|
||||
@ -259,7 +261,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
channel2_->Enable(true);
|
||||
result = channel1_->SetRemoteContent(&remote_media_content2_,
|
||||
CA_PRANSWER, NULL);
|
||||
session1_.Connect(&session2_);
|
||||
transport_controller1_.Connect(&transport_controller2_);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -286,11 +288,12 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
return channel1_->RemoveRecvStream(id);
|
||||
}
|
||||
|
||||
// Calling "_w" method here is ok since we only use one thread for this test
|
||||
cricket::FakeTransport* GetTransport1() {
|
||||
return session1_.GetTransport(channel1_->content_name());
|
||||
return transport_controller1_.GetTransport_w(channel1_->content_name());
|
||||
}
|
||||
cricket::FakeTransport* GetTransport2() {
|
||||
return session2_.GetTransport(channel2_->content_name());
|
||||
return transport_controller2_.GetTransport_w(channel2_->content_name());
|
||||
}
|
||||
|
||||
bool SendRtp1() {
|
||||
@ -769,7 +772,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
|
||||
EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER, NULL));
|
||||
EXPECT_EQ(1u, media_channel2_->recv_streams().size());
|
||||
session1_.Connect(&session2_);
|
||||
transport_controller1_.Connect(&transport_controller2_);
|
||||
|
||||
// Channel 2 do not send anything.
|
||||
typename T::Content content2;
|
||||
@ -832,7 +835,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CA_ANSWER, NULL));
|
||||
EXPECT_FALSE(media_channel2_->playout());
|
||||
EXPECT_FALSE(media_channel2_->sending());
|
||||
session1_.Connect(&session2_);
|
||||
transport_controller1_.Connect(&transport_controller2_);
|
||||
EXPECT_TRUE(media_channel1_->playout());
|
||||
EXPECT_FALSE(media_channel1_->sending());
|
||||
EXPECT_FALSE(media_channel2_->playout());
|
||||
@ -868,7 +871,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
EXPECT_TRUE(channel2_->SetRemoteContent(&content1, CA_OFFER, NULL));
|
||||
EXPECT_TRUE(channel2_->SetLocalContent(&content2, CA_PRANSWER, NULL));
|
||||
EXPECT_TRUE(channel1_->SetRemoteContent(&content2, CA_PRANSWER, NULL));
|
||||
session1_.Connect(&session2_);
|
||||
transport_controller1_.Connect(&transport_controller2_);
|
||||
|
||||
EXPECT_TRUE(media_channel1_->playout());
|
||||
EXPECT_FALSE(media_channel1_->sending()); // remote InActive
|
||||
@ -938,6 +941,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(0, 0);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(1U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(1U, GetTransport2()->channels().size());
|
||||
EXPECT_TRUE(SendRtp1());
|
||||
@ -953,6 +958,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(0, 0);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(1U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(1U, GetTransport2()->channels().size());
|
||||
EXPECT_FALSE(SendRtcp1());
|
||||
@ -966,6 +973,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(0, RTCP);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(1U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(2U, GetTransport2()->channels().size());
|
||||
EXPECT_FALSE(SendRtcp1());
|
||||
@ -979,6 +988,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(RTCP, 0);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(2U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(1U, GetTransport2()->channels().size());
|
||||
EXPECT_FALSE(SendRtcp1());
|
||||
@ -992,6 +1003,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(RTCP, RTCP);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(2U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(2U, GetTransport2()->channels().size());
|
||||
EXPECT_TRUE(SendRtcp1());
|
||||
@ -1007,6 +1020,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(RTCP | RTCP_MUX, RTCP);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(2U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(2U, GetTransport2()->channels().size());
|
||||
EXPECT_TRUE(SendRtcp1());
|
||||
@ -1021,6 +1036,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
void SendRtcpMuxToRtcpMux() {
|
||||
CreateChannels(RTCP | RTCP_MUX, RTCP | RTCP_MUX);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(2U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(1U, GetTransport2()->channels().size());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
@ -1045,6 +1062,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(RTCP | RTCP_MUX, RTCP | RTCP_MUX);
|
||||
channel1_->ActivateRtcpMux();
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(1U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(1U, GetTransport2()->channels().size());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
@ -1068,6 +1087,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(RTCP | RTCP_MUX, RTCP | RTCP_MUX);
|
||||
channel2_->ActivateRtcpMux();
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(2U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(1U, GetTransport2()->channels().size());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
@ -1093,6 +1114,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
channel1_->ActivateRtcpMux();
|
||||
channel2_->ActivateRtcpMux();
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(1U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(1U, GetTransport2()->channels().size());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
@ -1117,6 +1140,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(RTCP | RTCP_MUX, RTCP);
|
||||
channel1_->ActivateRtcpMux();
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(1U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(2U, GetTransport2()->channels().size());
|
||||
EXPECT_FALSE(SendAccept());
|
||||
@ -1126,6 +1151,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
void SendEarlyRtcpMuxToRtcp() {
|
||||
CreateChannels(RTCP | RTCP_MUX, RTCP);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(2U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(2U, GetTransport2()->channels().size());
|
||||
|
||||
@ -1156,6 +1183,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
void SendEarlyRtcpMuxToRtcpMux() {
|
||||
CreateChannels(RTCP | RTCP_MUX, RTCP | RTCP_MUX);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(2U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(1U, GetTransport2()->channels().size());
|
||||
|
||||
@ -1246,6 +1275,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
EXPECT_TRUE(SendProvisionalAnswer());
|
||||
EXPECT_TRUE(channel1_->secure());
|
||||
EXPECT_TRUE(channel2_->secure());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(2U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(2U, GetTransport2()->channels().size());
|
||||
EXPECT_TRUE(SendCustomRtcp1(kSsrc1));
|
||||
@ -1329,6 +1360,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(0, 0);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(1U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(1U, GetTransport2()->channels().size());
|
||||
EXPECT_TRUE(SendRtp1());
|
||||
@ -1393,6 +1426,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
}
|
||||
CreateChannels(flags, flags);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(2U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(expected_channels, GetTransport2()->channels().size());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
@ -1581,6 +1616,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
CreateChannels(RTCP, RTCP);
|
||||
EXPECT_TRUE(SendInitiate());
|
||||
EXPECT_TRUE(SendAccept());
|
||||
ASSERT_TRUE(GetTransport1());
|
||||
ASSERT_TRUE(GetTransport2());
|
||||
EXPECT_EQ(2U, GetTransport1()->channels().size());
|
||||
EXPECT_EQ(2U, GetTransport2()->channels().size());
|
||||
|
||||
@ -1669,15 +1706,15 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
EXPECT_TRUE(media_channel1_->ready_to_send());
|
||||
|
||||
// rtp channel becomes not ready to send will be propagated to mediachannel
|
||||
channel1_->SetReadyToSend(rtp, false);
|
||||
channel1_->SetReadyToSend(false, false);
|
||||
EXPECT_FALSE(media_channel1_->ready_to_send());
|
||||
channel1_->SetReadyToSend(rtp, true);
|
||||
channel1_->SetReadyToSend(false, true);
|
||||
EXPECT_TRUE(media_channel1_->ready_to_send());
|
||||
|
||||
// rtcp channel becomes not ready to send will be propagated to mediachannel
|
||||
channel1_->SetReadyToSend(rtcp, false);
|
||||
channel1_->SetReadyToSend(true, false);
|
||||
EXPECT_FALSE(media_channel1_->ready_to_send());
|
||||
channel1_->SetReadyToSend(rtcp, true);
|
||||
channel1_->SetReadyToSend(true, true);
|
||||
EXPECT_TRUE(media_channel1_->ready_to_send());
|
||||
}
|
||||
|
||||
@ -1696,13 +1733,13 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
|
||||
// should trigger the MediaChannel's OnReadyToSend.
|
||||
rtp->SignalReadyToSend(rtp);
|
||||
EXPECT_TRUE(media_channel1_->ready_to_send());
|
||||
channel1_->SetReadyToSend(rtp, false);
|
||||
channel1_->SetReadyToSend(false, false);
|
||||
EXPECT_FALSE(media_channel1_->ready_to_send());
|
||||
}
|
||||
|
||||
protected:
|
||||
cricket::FakeSession session1_;
|
||||
cricket::FakeSession session2_;
|
||||
cricket::FakeTransportController transport_controller1_;
|
||||
cricket::FakeTransportController transport_controller2_;
|
||||
cricket::FakeMediaEngine media_engine_;
|
||||
// The media channels are owned by the voice channel objects below.
|
||||
typename T::MediaChannel* media_channel1_;
|
||||
@ -1763,18 +1800,21 @@ class VoiceChannelTest
|
||||
: public ChannelTest<VoiceTraits> {
|
||||
public:
|
||||
typedef ChannelTest<VoiceTraits> Base;
|
||||
VoiceChannelTest() : Base(kPcmuFrame, sizeof(kPcmuFrame),
|
||||
kRtcpReport, sizeof(kRtcpReport)) {}
|
||||
VoiceChannelTest()
|
||||
: Base(kPcmuFrame, sizeof(kPcmuFrame), kRtcpReport, sizeof(kRtcpReport)) {
|
||||
}
|
||||
};
|
||||
|
||||
// override to add NULL parameter
|
||||
template<>
|
||||
template <>
|
||||
cricket::VideoChannel* ChannelTest<VideoTraits>::CreateChannel(
|
||||
rtc::Thread* thread, cricket::MediaEngineInterface* engine,
|
||||
cricket::FakeVideoMediaChannel* ch, cricket::BaseSession* session,
|
||||
rtc::Thread* thread,
|
||||
cricket::MediaEngineInterface* engine,
|
||||
cricket::FakeVideoMediaChannel* ch,
|
||||
cricket::TransportController* transport_controller,
|
||||
bool rtcp) {
|
||||
cricket::VideoChannel* channel = new cricket::VideoChannel(
|
||||
thread, ch, session, cricket::CN_VIDEO, rtcp);
|
||||
thread, ch, transport_controller, cricket::CN_VIDEO, rtcp);
|
||||
if (!channel->Init()) {
|
||||
delete channel;
|
||||
channel = NULL;
|
||||
@ -1827,8 +1867,11 @@ class VideoChannelTest
|
||||
: public ChannelTest<VideoTraits> {
|
||||
public:
|
||||
typedef ChannelTest<VideoTraits> Base;
|
||||
VideoChannelTest() : Base(kH264Packet, sizeof(kH264Packet),
|
||||
kRtcpReport, sizeof(kRtcpReport)) {}
|
||||
VideoChannelTest()
|
||||
: Base(kH264Packet,
|
||||
sizeof(kH264Packet),
|
||||
kRtcpReport,
|
||||
sizeof(kRtcpReport)) {}
|
||||
};
|
||||
|
||||
|
||||
@ -2519,13 +2562,15 @@ class DataChannelTest
|
||||
};
|
||||
|
||||
// Override to avoid engine channel parameter.
|
||||
template<>
|
||||
template <>
|
||||
cricket::DataChannel* ChannelTest<DataTraits>::CreateChannel(
|
||||
rtc::Thread* thread, cricket::MediaEngineInterface* engine,
|
||||
cricket::FakeDataMediaChannel* ch, cricket::BaseSession* session,
|
||||
rtc::Thread* thread,
|
||||
cricket::MediaEngineInterface* engine,
|
||||
cricket::FakeDataMediaChannel* ch,
|
||||
cricket::TransportController* transport_controller,
|
||||
bool rtcp) {
|
||||
cricket::DataChannel* channel = new cricket::DataChannel(
|
||||
thread, ch, session, cricket::CN_DATA, rtcp);
|
||||
thread, ch, transport_controller, cricket::CN_DATA, rtcp);
|
||||
if (!channel->Init()) {
|
||||
delete channel;
|
||||
channel = NULL;
|
||||
|
||||
@ -318,23 +318,18 @@ void ChannelManager::Terminate_w() {
|
||||
|
||||
VoiceChannel* ChannelManager::CreateVoiceChannel(
|
||||
webrtc::MediaControllerInterface* media_controller,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
const AudioOptions& options) {
|
||||
return worker_thread_->Invoke<VoiceChannel*>(
|
||||
Bind(&ChannelManager::CreateVoiceChannel_w,
|
||||
this,
|
||||
media_controller,
|
||||
session,
|
||||
content_name,
|
||||
rtcp,
|
||||
options));
|
||||
Bind(&ChannelManager::CreateVoiceChannel_w, this, media_controller,
|
||||
transport_controller, content_name, rtcp, options));
|
||||
}
|
||||
|
||||
VoiceChannel* ChannelManager::CreateVoiceChannel_w(
|
||||
webrtc::MediaControllerInterface* media_controller,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
const AudioOptions& options) {
|
||||
@ -346,9 +341,9 @@ VoiceChannel* ChannelManager::CreateVoiceChannel_w(
|
||||
if (!media_channel)
|
||||
return nullptr;
|
||||
|
||||
VoiceChannel* voice_channel = new VoiceChannel(
|
||||
worker_thread_, media_engine_.get(), media_channel,
|
||||
session, content_name, rtcp);
|
||||
VoiceChannel* voice_channel =
|
||||
new VoiceChannel(worker_thread_, media_engine_.get(), media_channel,
|
||||
transport_controller, content_name, rtcp);
|
||||
if (!voice_channel->Init()) {
|
||||
delete voice_channel;
|
||||
return nullptr;
|
||||
@ -379,23 +374,18 @@ void ChannelManager::DestroyVoiceChannel_w(VoiceChannel* voice_channel) {
|
||||
|
||||
VideoChannel* ChannelManager::CreateVideoChannel(
|
||||
webrtc::MediaControllerInterface* media_controller,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
const VideoOptions& options) {
|
||||
return worker_thread_->Invoke<VideoChannel*>(
|
||||
Bind(&ChannelManager::CreateVideoChannel_w,
|
||||
this,
|
||||
media_controller,
|
||||
session,
|
||||
content_name,
|
||||
rtcp,
|
||||
options));
|
||||
Bind(&ChannelManager::CreateVideoChannel_w, this, media_controller,
|
||||
transport_controller, content_name, rtcp, options));
|
||||
}
|
||||
|
||||
VideoChannel* ChannelManager::CreateVideoChannel_w(
|
||||
webrtc::MediaControllerInterface* media_controller,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
const VideoOptions& options) {
|
||||
@ -404,12 +394,12 @@ VideoChannel* ChannelManager::CreateVideoChannel_w(
|
||||
ASSERT(nullptr != media_controller);
|
||||
VideoMediaChannel* media_channel =
|
||||
media_engine_->CreateVideoChannel(media_controller->call_w(), options);
|
||||
if (media_channel == NULL)
|
||||
if (media_channel == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VideoChannel* video_channel = new VideoChannel(
|
||||
worker_thread_, media_channel,
|
||||
session, content_name, rtcp);
|
||||
worker_thread_, media_channel, transport_controller, content_name, rtcp);
|
||||
if (!video_channel->Init()) {
|
||||
delete video_channel;
|
||||
return NULL;
|
||||
@ -440,16 +430,20 @@ void ChannelManager::DestroyVideoChannel_w(VideoChannel* video_channel) {
|
||||
}
|
||||
|
||||
DataChannel* ChannelManager::CreateDataChannel(
|
||||
BaseSession* session, const std::string& content_name,
|
||||
bool rtcp, DataChannelType channel_type) {
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
DataChannelType channel_type) {
|
||||
return worker_thread_->Invoke<DataChannel*>(
|
||||
Bind(&ChannelManager::CreateDataChannel_w, this, session, content_name,
|
||||
rtcp, channel_type));
|
||||
Bind(&ChannelManager::CreateDataChannel_w, this, transport_controller,
|
||||
content_name, rtcp, channel_type));
|
||||
}
|
||||
|
||||
DataChannel* ChannelManager::CreateDataChannel_w(
|
||||
BaseSession* session, const std::string& content_name,
|
||||
bool rtcp, DataChannelType data_channel_type) {
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
DataChannelType data_channel_type) {
|
||||
// This is ok to alloc from a thread other than the worker thread.
|
||||
ASSERT(initialized_);
|
||||
DataMediaChannel* media_channel = data_media_engine_->CreateChannel(
|
||||
@ -461,8 +455,7 @@ DataChannel* ChannelManager::CreateDataChannel_w(
|
||||
}
|
||||
|
||||
DataChannel* data_channel = new DataChannel(
|
||||
worker_thread_, media_channel,
|
||||
session, content_name, rtcp);
|
||||
worker_thread_, media_channel, transport_controller, content_name, rtcp);
|
||||
if (!data_channel->Init()) {
|
||||
LOG(LS_WARNING) << "Failed to init data channel.";
|
||||
delete data_channel;
|
||||
|
||||
@ -104,11 +104,10 @@ class ChannelManager : public rtc::MessageHandler,
|
||||
void Terminate();
|
||||
|
||||
// The operations below all occur on the worker thread.
|
||||
|
||||
// Creates a voice channel, to be associated with the specified session.
|
||||
VoiceChannel* CreateVoiceChannel(
|
||||
webrtc::MediaControllerInterface* media_controller,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
const AudioOptions& options);
|
||||
@ -118,15 +117,16 @@ class ChannelManager : public rtc::MessageHandler,
|
||||
// associated with the specified session.
|
||||
VideoChannel* CreateVideoChannel(
|
||||
webrtc::MediaControllerInterface* media_controller,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
const VideoOptions& options);
|
||||
// Destroys a video channel created with the Create API.
|
||||
void DestroyVideoChannel(VideoChannel* video_channel);
|
||||
DataChannel* CreateDataChannel(
|
||||
BaseSession* session, const std::string& content_name,
|
||||
bool rtcp, DataChannelType data_channel_type);
|
||||
DataChannel* CreateDataChannel(TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
DataChannelType data_channel_type);
|
||||
// Destroys a data channel created with the Create API.
|
||||
void DestroyDataChannel(DataChannel* data_channel);
|
||||
|
||||
@ -241,21 +241,22 @@ class ChannelManager : public rtc::MessageHandler,
|
||||
void Terminate_w();
|
||||
VoiceChannel* CreateVoiceChannel_w(
|
||||
webrtc::MediaControllerInterface* media_controller,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
const AudioOptions& options);
|
||||
void DestroyVoiceChannel_w(VoiceChannel* voice_channel);
|
||||
VideoChannel* CreateVideoChannel_w(
|
||||
webrtc::MediaControllerInterface* media_controller,
|
||||
BaseSession* session,
|
||||
TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
const VideoOptions& options);
|
||||
void DestroyVideoChannel_w(VideoChannel* video_channel);
|
||||
DataChannel* CreateDataChannel_w(
|
||||
BaseSession* session, const std::string& content_name,
|
||||
bool rtcp, DataChannelType data_channel_type);
|
||||
DataChannel* CreateDataChannel_w(TransportController* transport_controller,
|
||||
const std::string& content_name,
|
||||
bool rtcp,
|
||||
DataChannelType data_channel_type);
|
||||
void DestroyDataChannel_w(DataChannel* data_channel);
|
||||
bool SetAudioOptions_w(const AudioOptions& options, int delay_offset,
|
||||
const Device* in_dev, const Device* out_dev);
|
||||
|
||||
@ -31,11 +31,11 @@
|
||||
#include "talk/media/base/testutils.h"
|
||||
#include "talk/media/devices/fakedevicemanager.h"
|
||||
#include "talk/media/webrtc/fakewebrtccall.h"
|
||||
#include "webrtc/p2p/base/fakesession.h"
|
||||
#include "talk/session/media/channelmanager.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/thread.h"
|
||||
#include "webrtc/p2p/base/faketransportcontroller.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
@ -57,14 +57,20 @@ class FakeMediaController : public webrtc::MediaControllerInterface {
|
||||
}
|
||||
~FakeMediaController() override {}
|
||||
webrtc::Call* call_w() override { return call_; }
|
||||
|
||||
private:
|
||||
webrtc::Call* call_;
|
||||
};
|
||||
|
||||
class ChannelManagerTest : public testing::Test {
|
||||
protected:
|
||||
ChannelManagerTest() : fake_call_(webrtc::Call::Config()),
|
||||
fake_mc_(&fake_call_), fme_(NULL), fdm_(NULL), fcm_(NULL), cm_(NULL) {}
|
||||
ChannelManagerTest()
|
||||
: fake_call_(webrtc::Call::Config()),
|
||||
fake_mc_(&fake_call_),
|
||||
fme_(NULL),
|
||||
fdm_(NULL),
|
||||
fcm_(NULL),
|
||||
cm_(NULL) {}
|
||||
|
||||
virtual void SetUp() {
|
||||
fme_ = new cricket::FakeMediaEngine();
|
||||
@ -75,7 +81,8 @@ class ChannelManagerTest : public testing::Test {
|
||||
fcm_ = new cricket::FakeCaptureManager();
|
||||
cm_ = new cricket::ChannelManager(
|
||||
fme_, fdme_, fdm_, fcm_, rtc::Thread::Current());
|
||||
session_ = new cricket::FakeSession(true);
|
||||
transport_controller_ =
|
||||
new cricket::FakeTransportController(ICEROLE_CONTROLLING);
|
||||
|
||||
std::vector<std::string> in_device_list, out_device_list, vid_device_list;
|
||||
in_device_list.push_back("audio-in1");
|
||||
@ -90,7 +97,7 @@ class ChannelManagerTest : public testing::Test {
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
delete session_;
|
||||
delete transport_controller_;
|
||||
delete cm_;
|
||||
cm_ = NULL;
|
||||
fdm_ = NULL;
|
||||
@ -107,7 +114,7 @@ class ChannelManagerTest : public testing::Test {
|
||||
cricket::FakeDeviceManager* fdm_;
|
||||
cricket::FakeCaptureManager* fcm_;
|
||||
cricket::ChannelManager* cm_;
|
||||
cricket::FakeSession* session_;
|
||||
cricket::FakeTransportController* transport_controller_;
|
||||
};
|
||||
|
||||
// Test that we startup/shutdown properly.
|
||||
@ -138,15 +145,16 @@ TEST_F(ChannelManagerTest, StartupShutdownOnThread) {
|
||||
// Test that we can create and destroy a voice and video channel.
|
||||
TEST_F(ChannelManagerTest, CreateDestroyChannels) {
|
||||
EXPECT_TRUE(cm_->Init());
|
||||
cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel(
|
||||
&fake_mc_, session_, cricket::CN_AUDIO, false, AudioOptions());
|
||||
cricket::VoiceChannel* voice_channel =
|
||||
cm_->CreateVoiceChannel(&fake_mc_, transport_controller_,
|
||||
cricket::CN_AUDIO, false, AudioOptions());
|
||||
EXPECT_TRUE(voice_channel != nullptr);
|
||||
cricket::VideoChannel* video_channel = cm_->CreateVideoChannel(
|
||||
&fake_mc_, session_, cricket::CN_VIDEO, false, VideoOptions());
|
||||
cricket::VideoChannel* video_channel =
|
||||
cm_->CreateVideoChannel(&fake_mc_, transport_controller_,
|
||||
cricket::CN_VIDEO, false, VideoOptions());
|
||||
EXPECT_TRUE(video_channel != nullptr);
|
||||
cricket::DataChannel* data_channel =
|
||||
cm_->CreateDataChannel(session_, cricket::CN_DATA,
|
||||
false, cricket::DCT_RTP);
|
||||
cricket::DataChannel* data_channel = cm_->CreateDataChannel(
|
||||
transport_controller_, cricket::CN_DATA, false, cricket::DCT_RTP);
|
||||
EXPECT_TRUE(data_channel != nullptr);
|
||||
cm_->DestroyVideoChannel(video_channel);
|
||||
cm_->DestroyVoiceChannel(voice_channel);
|
||||
@ -159,17 +167,19 @@ TEST_F(ChannelManagerTest, CreateDestroyChannelsOnThread) {
|
||||
worker_.Start();
|
||||
EXPECT_TRUE(cm_->set_worker_thread(&worker_));
|
||||
EXPECT_TRUE(cm_->Init());
|
||||
delete session_;
|
||||
session_ = new cricket::FakeSession(&worker_, true);
|
||||
cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel(
|
||||
&fake_mc_, session_, cricket::CN_AUDIO, false, AudioOptions());
|
||||
delete transport_controller_;
|
||||
transport_controller_ =
|
||||
new cricket::FakeTransportController(&worker_, ICEROLE_CONTROLLING);
|
||||
cricket::VoiceChannel* voice_channel =
|
||||
cm_->CreateVoiceChannel(&fake_mc_, transport_controller_,
|
||||
cricket::CN_AUDIO, false, AudioOptions());
|
||||
EXPECT_TRUE(voice_channel != nullptr);
|
||||
cricket::VideoChannel* video_channel = cm_->CreateVideoChannel(
|
||||
&fake_mc_, session_, cricket::CN_VIDEO, false, VideoOptions());
|
||||
cricket::VideoChannel* video_channel =
|
||||
cm_->CreateVideoChannel(&fake_mc_, transport_controller_,
|
||||
cricket::CN_VIDEO, false, VideoOptions());
|
||||
EXPECT_TRUE(video_channel != nullptr);
|
||||
cricket::DataChannel* data_channel =
|
||||
cm_->CreateDataChannel(session_, cricket::CN_DATA,
|
||||
false, cricket::DCT_RTP);
|
||||
cricket::DataChannel* data_channel = cm_->CreateDataChannel(
|
||||
transport_controller_, cricket::CN_DATA, false, cricket::DCT_RTP);
|
||||
EXPECT_TRUE(data_channel != nullptr);
|
||||
cm_->DestroyVideoChannel(video_channel);
|
||||
cm_->DestroyVoiceChannel(voice_channel);
|
||||
@ -181,21 +191,22 @@ TEST_F(ChannelManagerTest, CreateDestroyChannelsOnThread) {
|
||||
// to create a cricket::TransportChannel
|
||||
TEST_F(ChannelManagerTest, NoTransportChannelTest) {
|
||||
EXPECT_TRUE(cm_->Init());
|
||||
session_->set_fail_channel_creation(true);
|
||||
transport_controller_->set_fail_channel_creation(true);
|
||||
// The test is useless unless the session does not fail creating
|
||||
// cricket::TransportChannel.
|
||||
ASSERT_TRUE(session_->CreateChannel(
|
||||
ASSERT_TRUE(transport_controller_->CreateTransportChannel_w(
|
||||
"audio", cricket::ICE_CANDIDATE_COMPONENT_RTP) == nullptr);
|
||||
|
||||
cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel(
|
||||
&fake_mc_, session_, cricket::CN_AUDIO, false, AudioOptions());
|
||||
cricket::VoiceChannel* voice_channel =
|
||||
cm_->CreateVoiceChannel(&fake_mc_, transport_controller_,
|
||||
cricket::CN_AUDIO, false, AudioOptions());
|
||||
EXPECT_TRUE(voice_channel == nullptr);
|
||||
cricket::VideoChannel* video_channel = cm_->CreateVideoChannel(
|
||||
&fake_mc_, session_, cricket::CN_VIDEO, false, VideoOptions());
|
||||
cricket::VideoChannel* video_channel =
|
||||
cm_->CreateVideoChannel(&fake_mc_, transport_controller_,
|
||||
cricket::CN_VIDEO, false, VideoOptions());
|
||||
EXPECT_TRUE(video_channel == nullptr);
|
||||
cricket::DataChannel* data_channel =
|
||||
cm_->CreateDataChannel(session_, cricket::CN_DATA,
|
||||
false, cricket::DCT_RTP);
|
||||
cricket::DataChannel* data_channel = cm_->CreateDataChannel(
|
||||
transport_controller_, cricket::CN_DATA, false, cricket::DCT_RTP);
|
||||
EXPECT_TRUE(data_channel == nullptr);
|
||||
cm_->Terminate();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user