Only generate one CNAME per PeerConnection.

The CNAME is generated in the PeerConnection constructor and is populated through the MediaSessionOptions.
A default cname will be set in the MediaSessionOptions constructor.

BUG=webrtc:3431

Review-Url: https://codereview.webrtc.org/1871993002
Cr-Commit-Position: refs/heads/master@{#12650}
This commit is contained in:
zhihuang
2016-05-06 18:40:30 -07:00
committed by Commit bot
parent 630d9ba364
commit 8f65cdf22b
6 changed files with 108 additions and 83 deletions

View File

@ -66,6 +66,9 @@ static const char kTransport[] = "transport";
// NOTE: Must be in the same order as the ServiceType enum.
static const char* kValidIceServiceTypes[] = {"stun", "stuns", "turn", "turns"};
// The length of RTCP CNAMEs.
static const int kRtcpCnameLength = 16;
// NOTE: A loop below assumes that the first value of this enum is 0 and all
// other values are incremental.
enum ServiceType {
@ -377,6 +380,16 @@ void AddSendStreams(
namespace webrtc {
// Generate a RTCP CNAME when a PeerConnection is created.
std::string GenerateRtcpCname() {
std::string cname;
if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) {
LOG(LS_ERROR) << "Failed to generate CNAME.";
RTC_DCHECK(false);
}
return cname;
}
bool ExtractMediaSessionOptions(
const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
bool is_offer,
@ -508,6 +521,7 @@ PeerConnection::PeerConnection(PeerConnectionFactory* factory)
ice_state_(kIceNew),
ice_connection_state_(kIceConnectionNew),
ice_gathering_state_(kIceGatheringNew),
rtcp_cname_(GenerateRtcpCname()),
local_streams_(StreamCollection::Create()),
remote_streams_(StreamCollection::Create()) {}
@ -1503,6 +1517,8 @@ bool PeerConnection::GetOptionsForOffer(
if (session_->data_channel_type() == cricket::DCT_SCTP && HasDataChannels()) {
session_options->data_channel_type = cricket::DCT_SCTP;
}
session_options->rtcp_cname = rtcp_cname_;
return true;
}
@ -1540,6 +1556,8 @@ bool PeerConnection::GetOptionsForAnswer(
if (!ParseConstraintsForAnswer(constraints, session_options)) {
return false;
}
session_options->rtcp_cname = rtcp_cname_;
FinishOptionsForAnswer(session_options);
return true;
}
@ -1552,6 +1570,8 @@ bool PeerConnection::GetOptionsForAnswer(
if (!ExtractMediaSessionOptions(options, false, session_options)) {
return false;
}
session_options->rtcp_cname = rtcp_cname_;
FinishOptionsForAnswer(session_options);
return true;
}

View File

@ -369,6 +369,10 @@ class PeerConnection : public PeerConnectionInterface,
std::unique_ptr<cricket::PortAllocator> port_allocator_;
std::unique_ptr<MediaControllerInterface> media_controller_;
// One PeerConnection has only one RTCP CNAME.
// https://tools.ietf.org/html/draft-ietf-rtcweb-rtp-usage-26#section-4.9
std::string rtcp_cname_;
// Streams added via AddStream.
rtc::scoped_refptr<StreamCollection> local_streams_;
// Streams created as a result of SetRemoteDescription.

View File

@ -934,6 +934,34 @@ class PeerConnectionInterfaceTest : public testing::Test {
ASSERT_TRUE(stream->AddTrack(video_track));
}
rtc::scoped_ptr<SessionDescriptionInterface> CreateOfferWithOneAudioStream() {
CreatePeerConnection();
AddVoiceStream(kStreamLabel1);
rtc::scoped_ptr<SessionDescriptionInterface> offer;
EXPECT_TRUE(DoCreateOffer(&offer, nullptr));
return offer;
}
rtc::scoped_ptr<SessionDescriptionInterface>
CreateAnswerWithOneAudioStream() {
rtc::scoped_ptr<SessionDescriptionInterface> offer =
CreateOfferWithOneAudioStream();
EXPECT_TRUE(DoSetRemoteDescription(offer.release()));
rtc::scoped_ptr<SessionDescriptionInterface> answer;
EXPECT_TRUE(DoCreateAnswer(&answer, nullptr));
return answer;
}
const std::string& GetFirstAudioStreamCname(
const SessionDescriptionInterface* desc) {
const cricket::ContentInfo* audio_content =
cricket::GetFirstAudioContent(desc->description());
const cricket::AudioContentDescription* audio_desc =
static_cast<const cricket::AudioContentDescription*>(
audio_content->description);
return audio_desc->streams()[0].cname;
}
cricket::FakePortAllocator* port_allocator_ = nullptr;
scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory_;
scoped_refptr<PeerConnectionInterface> pc_;
@ -941,6 +969,27 @@ class PeerConnectionInterfaceTest : public testing::Test {
rtc::scoped_refptr<StreamCollection> reference_collection_;
};
// Generate different CNAMEs when PeerConnections are created.
// The CNAMEs are expected to be generated randomly. It is possible
// that the test fails, though the possibility is very low.
TEST_F(PeerConnectionInterfaceTest, CnameGenerationInOffer) {
rtc::scoped_ptr<SessionDescriptionInterface> offer1 =
CreateOfferWithOneAudioStream();
rtc::scoped_ptr<SessionDescriptionInterface> offer2 =
CreateOfferWithOneAudioStream();
EXPECT_NE(GetFirstAudioStreamCname(offer1.get()),
GetFirstAudioStreamCname(offer2.get()));
}
TEST_F(PeerConnectionInterfaceTest, CnameGenerationInAnswer) {
rtc::scoped_ptr<SessionDescriptionInterface> answer1 =
CreateAnswerWithOneAudioStream();
rtc::scoped_ptr<SessionDescriptionInterface> answer2 =
CreateAnswerWithOneAudioStream();
EXPECT_NE(GetFirstAudioStreamCname(answer1.get()),
GetFirstAudioStreamCname(answer2.get()));
}
TEST_F(PeerConnectionInterfaceTest,
CreatePeerConnectionWithDifferentConfigurations) {
CreatePeerConnectionWithDifferentConfigurations();