Use c=IN IP4 <hostname> to support the presence of hostname candidates.

Bug: chromium:927309
Change-Id: I1b014ee3d194bf2b8fcc47b37e31c7af866a8322
Reviewed-on: https://webrtc-review.googlesource.com/c/121960
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Qingsi Wang <qingsi@google.com>
Cr-Commit-Position: refs/heads/master@{#26619}
This commit is contained in:
Qingsi Wang 2019-02-08 12:53:06 -08:00 committed by Commit Bot
parent 78323436cf
commit 5699142b9a
4 changed files with 80 additions and 7 deletions

View File

@ -56,6 +56,7 @@ void UpdateConnectionAddress(
cricket::MediaContentDescription* media_desc) {
int port = kDummyPort;
std::string ip = kDummyAddress;
std::string hostname;
int current_preference = kPreferenceUnknown;
int current_family = AF_UNSPEC;
for (size_t i = 0; i < candidate_collection.count(); ++i) {
@ -81,12 +82,16 @@ void UpdateConnectionAddress(
}
current_preference = preference;
current_family = family;
port = jsep_candidate->candidate().address().port();
ip = jsep_candidate->candidate().address().ipaddr().ToString();
const rtc::SocketAddress& candidate_addr =
jsep_candidate->candidate().address();
port = candidate_addr.port();
ip = candidate_addr.ipaddr().ToString();
hostname = candidate_addr.hostname();
}
rtc::SocketAddress connection_addr(ip, port);
if (rtc::IPIsUnspec(connection_addr.ipaddr()) && !hostname.empty()) {
connection_addr = rtc::SocketAddress(hostname, port);
}
rtc::SocketAddress connection_addr;
connection_addr.SetIP(ip);
connection_addr.SetPort(port);
media_desc->set_connection_address(connection_addr);
}

View File

@ -212,6 +212,22 @@ TEST_F(JsepSessionDescriptionTest, AddCandidateDuplicates) {
EXPECT_EQ(1u, jsep_desc_->candidates(0)->count());
}
// Test that the connection address is set to a hostname address after adding a
// hostname candidate.
TEST_F(JsepSessionDescriptionTest, AddHostnameCandidate) {
cricket::Candidate c;
c.set_component(cricket::ICE_CANDIDATE_COMPONENT_RTP);
c.set_protocol(cricket::UDP_PROTOCOL_NAME);
c.set_address(rtc::SocketAddress("example.local", 1234));
c.set_type(cricket::LOCAL_PORT_TYPE);
JsepIceCandidate hostname_candidate("audio", 0, c);
EXPECT_TRUE(jsep_desc_->AddCandidate(&hostname_candidate));
ASSERT_NE(nullptr, jsep_desc_->description());
const auto& content = jsep_desc_->description()->contents()[0];
EXPECT_EQ("example.local:1234",
content.media_description()->connection_address().ToString());
}
// Test that we can serialize a JsepSessionDescription and deserialize it again.
TEST_F(JsepSessionDescriptionTest, SerializeDeserialize) {
std::string sdp = Serialize(jsep_desc_.get());

View File

@ -1385,9 +1385,15 @@ void BuildMediaDescription(const ContentInfo* content_info,
} else if (media_desc->connection_address().family() == AF_INET) {
os << " " << kConnectionIpv4Addrtype << " "
<< media_desc->connection_address().ipaddr().ToString();
} else {
} else if (media_desc->connection_address().family() == AF_INET6) {
os << " " << kConnectionIpv6Addrtype << " "
<< media_desc->connection_address().ipaddr().ToString();
} else if (!media_desc->connection_address().hostname().empty()) {
// For hostname candidates, we use c=IN IP4 <hostname>.
os << " " << kConnectionIpv4Addrtype << " "
<< media_desc->connection_address().hostname();
} else {
os << " " << kConnectionIpv4Addrtype << " " << kDummyAddress;
}
AddLine(os.str(), message);

View File

@ -3991,7 +3991,28 @@ TEST_F(WebRtcSdpTest, ParseConnectionDataIPv6) {
content2.media_description()->connection_address().ToString());
}
// Test that the invalid or unsupprted connection data cannot be parsed.
// Test that a c= line that contains a hostname connection address can be
// parsed.
TEST_F(WebRtcSdpTest, ParseConnectionDataWithHostnameConnectionAddress) {
JsepSessionDescription jsep_desc(kDummyType);
std::string sdp = kSdpString;
EXPECT_TRUE(SdpDeserialize(sdp, &jsep_desc));
sdp = kSdpString;
Replace("c=IN IP4 0.0.0.0\r\n", "c=IN IP4 example.local\r\n", &sdp);
Replace("c=IN IP4 0.0.0.0\r\n", "c=IN IP4 example.local\r\n", &sdp);
ASSERT_TRUE(SdpDeserialize(sdp, &jsep_desc));
ASSERT_NE(nullptr, jsep_desc.description());
const auto& content1 = jsep_desc.description()->contents()[0];
EXPECT_EQ("example.local:9",
content1.media_description()->connection_address().ToString());
const auto& content2 = jsep_desc.description()->contents()[1];
EXPECT_EQ("example.local:9",
content2.media_description()->connection_address().ToString());
}
// Test that the invalid or unsupported connection data cannot be parsed.
TEST_F(WebRtcSdpTest, ParseConnectionDataFailure) {
JsepSessionDescription jsep_desc(kDummyType);
std::string sdp = kSdpString;
@ -4038,6 +4059,31 @@ TEST_F(WebRtcSdpTest, SerializeAndDeserializeWithConnectionAddress) {
video_desc->connection_address().ToString());
}
// Test that a media description that contains a hostname connection address can
// be correctly serialized.
TEST_F(WebRtcSdpTest, SerializeAndDeserializeWithHostnameConnectionAddress) {
JsepSessionDescription expected_jsep(kDummyType);
cricket::Candidate c;
const rtc::SocketAddress hostname_addr("example.local", 1234);
audio_desc_->set_connection_address(hostname_addr);
video_desc_->set_connection_address(hostname_addr);
ASSERT_TRUE(
expected_jsep.Initialize(desc_.Copy(), kSessionId, kSessionVersion));
// Serialization.
std::string message = webrtc::SdpSerialize(expected_jsep);
// Deserialization.
JsepSessionDescription jdesc(kDummyType);
ASSERT_TRUE(SdpDeserialize(message, &jdesc));
auto audio_desc = jdesc.description()
->GetContentByName(kAudioContentName)
->media_description();
auto video_desc = jdesc.description()
->GetContentByName(kVideoContentName)
->media_description();
EXPECT_EQ(hostname_addr, audio_desc->connection_address());
EXPECT_EQ(hostname_addr, video_desc->connection_address());
}
// RFC4566 says "If a session has no meaningful name, the value "s= " SHOULD be
// used (i.e., a single space as the session name)." So we should accept that.
TEST_F(WebRtcSdpTest, DeserializeEmptySessionName) {