blob: ee446cbbdad2627e986d51f4093371e748e581f1 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "api/jsep_session_description.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <stddef.h>
14#include <stdint.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020015
Yves Gerey3e707812018-11-28 16:47:49 +010016#include <utility>
17#include <vector>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000018
Patrik Höglunde2d6a062017-10-05 14:53:33 +020019#include "api/candidate.h"
Yves Gerey3e707812018-11-28 16:47:49 +010020#include "api/jsep.h"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "api/jsep_ice_candidate.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "media/base/codec.h"
Steve Anton10542f22019-01-11 09:11:00 -080023#include "p2p/base/p2p_constants.h"
Steve Antona3a92c22017-12-07 10:27:41 -080024#include "p2p/base/port.h"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "p2p/base/transport_description.h"
26#include "p2p/base/transport_info.h"
27#include "pc/session_description.h"
28#include "pc/webrtc_sdp.h"
Yves Gerey3e707812018-11-28 16:47:49 +010029#include "rtc_base/helpers.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000030#include "rtc_base/net_helper.h"
Steve Anton10542f22019-01-11 09:11:00 -080031#include "rtc_base/socket_address.h"
32#include "rtc_base/string_encode.h"
Yves Gerey3e707812018-11-28 16:47:49 +010033#include "test/gtest.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000034
Steve Anton5adfafd2017-12-20 16:34:00 -080035using cricket::MediaProtocolType;
Steve Anton88f2cb92017-12-05 12:47:32 -080036using ::testing::Values;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037using webrtc::IceCandidateCollection;
38using webrtc::IceCandidateInterface;
39using webrtc::JsepIceCandidate;
40using webrtc::JsepSessionDescription;
Steve Anton88f2cb92017-12-05 12:47:32 -080041using webrtc::SdpType;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042using webrtc::SessionDescriptionInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000043
44static const char kCandidateUfrag[] = "ufrag";
45static const char kCandidatePwd[] = "pwd";
46static const char kCandidateUfragVoice[] = "ufrag_voice";
47static const char kCandidatePwdVoice[] = "pwd_voice";
48static const char kCandidateUfragVideo[] = "ufrag_video";
49static const char kCandidatePwdVideo[] = "pwd_video";
zhihuang38989e52017-03-21 11:04:53 -070050static const char kCandidateFoundation[] = "a0+B/1";
51static const uint32_t kCandidatePriority = 2130706432U; // pref = 1.0
52static const uint32_t kCandidateGeneration = 2;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000053
54// This creates a session description with both audio and video media contents.
55// In SDP this is described by two m lines, one audio and one video.
Harald Alvestrand4d7160e2019-04-12 07:01:29 +020056static std::unique_ptr<cricket::SessionDescription>
57CreateCricketSessionDescription() {
Mirko Bonadei317a1f02019-09-17 17:06:18 +020058 auto desc = std::make_unique<cricket::SessionDescription>();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000059
Harald Alvestrand4d7160e2019-04-12 07:01:29 +020060 // AudioContentDescription
Mirko Bonadei317a1f02019-09-17 17:06:18 +020061 auto audio = std::make_unique<cricket::AudioContentDescription>();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062 // VideoContentDescription
Mirko Bonadei317a1f02019-09-17 17:06:18 +020063 auto video = std::make_unique<cricket::VideoContentDescription>();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064
deadbeef67cf2c12016-04-13 10:07:16 -070065 audio->AddCodec(cricket::AudioCodec(103, "ISAC", 16000, 0, 0));
Harald Alvestrand1716d392019-06-03 20:35:45 +020066 desc->AddContent(cricket::CN_AUDIO, MediaProtocolType::kRtp,
67 std::move(audio));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068
perkj26752742016-10-24 01:21:16 -070069 video->AddCodec(cricket::VideoCodec(120, "VP8"));
Harald Alvestrand1716d392019-06-03 20:35:45 +020070 desc->AddContent(cricket::CN_VIDEO, MediaProtocolType::kRtp,
71 std::move(video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000072
Steve Anton06817cd2018-12-18 15:55:30 -080073 desc->AddTransportInfo(cricket::TransportInfo(
deadbeef46eed762016-01-28 13:24:37 -080074 cricket::CN_AUDIO,
75 cricket::TransportDescription(
76 std::vector<std::string>(), kCandidateUfragVoice, kCandidatePwdVoice,
Steve Anton06817cd2018-12-18 15:55:30 -080077 cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_NONE, NULL)));
78 desc->AddTransportInfo(cricket::TransportInfo(
deadbeef46eed762016-01-28 13:24:37 -080079 cricket::CN_VIDEO,
80 cricket::TransportDescription(
81 std::vector<std::string>(), kCandidateUfragVideo, kCandidatePwdVideo,
Steve Anton06817cd2018-12-18 15:55:30 -080082 cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_NONE, NULL)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000083 return desc;
84}
85
Mirko Bonadei6a489f22019-04-09 15:11:12 +020086class JsepSessionDescriptionTest : public ::testing::Test {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087 protected:
henrike@webrtc.org28e20752013-07-10 00:45:36 +000088 virtual void SetUp() {
89 int port = 1234;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000090 rtc::SocketAddress address("127.0.0.1", port++);
guoweis@webrtc.org61c12472015-01-15 06:53:07 +000091 cricket::Candidate candidate(cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
92 address, 1, "", "", "local", 0, "1");
henrike@webrtc.org28e20752013-07-10 00:45:36 +000093 candidate_ = candidate;
Yves Gerey665174f2018-06-19 15:03:05 +020094 const std::string session_id = rtc::ToString(rtc::CreateRandomId64());
95 const std::string session_version = rtc::ToString(rtc::CreateRandomId());
Mirko Bonadei317a1f02019-09-17 17:06:18 +020096 jsep_desc_ = std::make_unique<JsepSessionDescription>(SdpType::kOffer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097 ASSERT_TRUE(jsep_desc_->Initialize(CreateCricketSessionDescription(),
Yves Gerey665174f2018-06-19 15:03:05 +020098 session_id, session_version));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099 }
100
101 std::string Serialize(const SessionDescriptionInterface* desc) {
102 std::string sdp;
103 EXPECT_TRUE(desc->ToString(&sdp));
104 EXPECT_FALSE(sdp.empty());
105 return sdp;
106 }
107
Steve Antona3a92c22017-12-07 10:27:41 -0800108 std::unique_ptr<SessionDescriptionInterface> DeSerialize(
109 const std::string& sdp) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200110 auto jsep_desc = std::make_unique<JsepSessionDescription>(SdpType::kOffer);
Steve Antona3a92c22017-12-07 10:27:41 -0800111 EXPECT_TRUE(webrtc::SdpDeserialize(sdp, jsep_desc.get(), nullptr));
112 return std::move(jsep_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113 }
114
115 cricket::Candidate candidate_;
kwibergd1fe2812016-04-27 06:47:29 -0700116 std::unique_ptr<JsepSessionDescription> jsep_desc_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000117};
118
Harald Alvestrand0e7b3a92020-12-15 15:18:28 +0000119TEST_F(JsepSessionDescriptionTest, CloneDefault) {
120 auto new_desc = jsep_desc_->Clone();
121 EXPECT_EQ(jsep_desc_->type(), new_desc->type());
122 std::string old_desc_string;
123 std::string new_desc_string;
124 EXPECT_TRUE(jsep_desc_->ToString(&old_desc_string));
125 EXPECT_TRUE(new_desc->ToString(&new_desc_string));
126 EXPECT_EQ(old_desc_string, new_desc_string);
127 EXPECT_EQ(jsep_desc_->session_id(), new_desc->session_id());
128 EXPECT_EQ(jsep_desc_->session_version(), new_desc->session_version());
129}
130
Byoungchan Leecb42e102021-07-15 14:09:40 +0900131TEST_F(JsepSessionDescriptionTest, CloneRollback) {
132 auto jsep_desc = std::make_unique<JsepSessionDescription>(SdpType::kRollback);
133 auto new_desc = jsep_desc->Clone();
134 EXPECT_EQ(jsep_desc->type(), new_desc->type());
135}
136
Harald Alvestrandfc6b8712021-01-05 10:51:08 +0000137TEST_F(JsepSessionDescriptionTest, CloneWithCandidates) {
138 cricket::Candidate candidate_v4(
139 cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
140 rtc::SocketAddress("192.168.1.5", 1234), kCandidatePriority, "", "",
141 cricket::STUN_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
142 cricket::Candidate candidate_v6(
143 cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
144 rtc::SocketAddress("::1", 1234), kCandidatePriority, "", "",
145 cricket::LOCAL_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
146
147 JsepIceCandidate jice_v4("audio", 0, candidate_v4);
148 JsepIceCandidate jice_v6("audio", 0, candidate_v6);
149 JsepIceCandidate jice_v4_video("video", 0, candidate_v4);
150 JsepIceCandidate jice_v6_video("video", 0, candidate_v6);
151 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v4));
152 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v6));
153 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v4_video));
154 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v6_video));
155 auto new_desc = jsep_desc_->Clone();
156 EXPECT_EQ(jsep_desc_->type(), new_desc->type());
157 std::string old_desc_string;
158 std::string new_desc_string;
159 EXPECT_TRUE(jsep_desc_->ToString(&old_desc_string));
160 EXPECT_TRUE(new_desc->ToString(&new_desc_string));
161 EXPECT_EQ(old_desc_string, new_desc_string);
162}
163
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000164// Test that number_of_mediasections() returns the number of media contents in
165// a session description.
166TEST_F(JsepSessionDescriptionTest, CheckSessionDescription) {
167 EXPECT_EQ(2u, jsep_desc_->number_of_mediasections());
168}
169
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700170// Test that we can add a candidate to a session description without MID.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000171TEST_F(JsepSessionDescriptionTest, AddCandidateWithoutMid) {
172 JsepIceCandidate jsep_candidate("", 0, candidate_);
173 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
174 const IceCandidateCollection* ice_candidates = jsep_desc_->candidates(0);
175 ASSERT_TRUE(ice_candidates != NULL);
176 EXPECT_EQ(1u, ice_candidates->count());
177 const IceCandidateInterface* ice_candidate = ice_candidates->at(0);
178 ASSERT_TRUE(ice_candidate != NULL);
179 candidate_.set_username(kCandidateUfragVoice);
180 candidate_.set_password(kCandidatePwdVoice);
181 EXPECT_TRUE(ice_candidate->candidate().IsEquivalent(candidate_));
182 EXPECT_EQ(0, ice_candidate->sdp_mline_index());
183 EXPECT_EQ(0u, jsep_desc_->candidates(1)->count());
184}
185
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700186// Test that we can add and remove candidates to a session description with
187// MID. Removing candidates requires MID (transport_name).
188TEST_F(JsepSessionDescriptionTest, AddAndRemoveCandidatesWithMid) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000189 // mid and m-line index don't match, in this case mid is preferred.
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700190 std::string mid = "video";
191 JsepIceCandidate jsep_candidate(mid, 0, candidate_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000192 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
193 EXPECT_EQ(0u, jsep_desc_->candidates(0)->count());
194 const IceCandidateCollection* ice_candidates = jsep_desc_->candidates(1);
195 ASSERT_TRUE(ice_candidates != NULL);
196 EXPECT_EQ(1u, ice_candidates->count());
197 const IceCandidateInterface* ice_candidate = ice_candidates->at(0);
198 ASSERT_TRUE(ice_candidate != NULL);
199 candidate_.set_username(kCandidateUfragVideo);
200 candidate_.set_password(kCandidatePwdVideo);
201 EXPECT_TRUE(ice_candidate->candidate().IsEquivalent(candidate_));
202 // The mline index should have been updated according to mid.
203 EXPECT_EQ(1, ice_candidate->sdp_mline_index());
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700204
205 std::vector<cricket::Candidate> candidates(1, candidate_);
206 candidates[0].set_transport_name(mid);
207 EXPECT_EQ(1u, jsep_desc_->RemoveCandidates(candidates));
208 EXPECT_EQ(0u, jsep_desc_->candidates(0)->count());
209 EXPECT_EQ(0u, jsep_desc_->candidates(1)->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000210}
211
212TEST_F(JsepSessionDescriptionTest, AddCandidateAlreadyHasUfrag) {
213 candidate_.set_username(kCandidateUfrag);
214 candidate_.set_password(kCandidatePwd);
215 JsepIceCandidate jsep_candidate("audio", 0, candidate_);
216 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
217 const IceCandidateCollection* ice_candidates = jsep_desc_->candidates(0);
218 ASSERT_TRUE(ice_candidates != NULL);
219 EXPECT_EQ(1u, ice_candidates->count());
220 const IceCandidateInterface* ice_candidate = ice_candidates->at(0);
221 ASSERT_TRUE(ice_candidate != NULL);
222 candidate_.set_username(kCandidateUfrag);
223 candidate_.set_password(kCandidatePwd);
224 EXPECT_TRUE(ice_candidate->candidate().IsEquivalent(candidate_));
225
226 EXPECT_EQ(0u, jsep_desc_->candidates(1)->count());
227}
228
229// Test that we can not add a candidate if there is no corresponding media
230// content in the session description.
231TEST_F(JsepSessionDescriptionTest, AddBadCandidate) {
232 JsepIceCandidate bad_candidate1("", 55, candidate_);
233 EXPECT_FALSE(jsep_desc_->AddCandidate(&bad_candidate1));
234
235 JsepIceCandidate bad_candidate2("some weird mid", 0, candidate_);
236 EXPECT_FALSE(jsep_desc_->AddCandidate(&bad_candidate2));
237}
238
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000239// Tests that repeatedly adding the same candidate, with or without credentials,
240// does not increase the number of candidates in the description.
241TEST_F(JsepSessionDescriptionTest, AddCandidateDuplicates) {
242 JsepIceCandidate jsep_candidate("", 0, candidate_);
243 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
244 EXPECT_EQ(1u, jsep_desc_->candidates(0)->count());
245
246 // Add the same candidate again. It should be ignored.
247 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
248 EXPECT_EQ(1u, jsep_desc_->candidates(0)->count());
249
250 // Create a new candidate, identical except that the ufrag and pwd are now
251 // populated.
252 candidate_.set_username(kCandidateUfragVoice);
253 candidate_.set_password(kCandidatePwdVoice);
254 JsepIceCandidate jsep_candidate_with_credentials("", 0, candidate_);
255
256 // This should also be identified as redundant and ignored.
257 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate_with_credentials));
258 EXPECT_EQ(1u, jsep_desc_->candidates(0)->count());
259}
260
Qingsi Wang56991422019-02-08 12:53:06 -0800261// Test that the connection address is set to a hostname address after adding a
262// hostname candidate.
263TEST_F(JsepSessionDescriptionTest, AddHostnameCandidate) {
264 cricket::Candidate c;
265 c.set_component(cricket::ICE_CANDIDATE_COMPONENT_RTP);
266 c.set_protocol(cricket::UDP_PROTOCOL_NAME);
267 c.set_address(rtc::SocketAddress("example.local", 1234));
268 c.set_type(cricket::LOCAL_PORT_TYPE);
Qingsi Wang3ae59d32019-07-11 21:53:45 -0700269 const size_t audio_index = 0;
270 JsepIceCandidate hostname_candidate("audio", audio_index, c);
Qingsi Wang56991422019-02-08 12:53:06 -0800271 EXPECT_TRUE(jsep_desc_->AddCandidate(&hostname_candidate));
Qingsi Wang3ae59d32019-07-11 21:53:45 -0700272
Qingsi Wang56991422019-02-08 12:53:06 -0800273 ASSERT_NE(nullptr, jsep_desc_->description());
Qingsi Wang3ae59d32019-07-11 21:53:45 -0700274 ASSERT_EQ(2u, jsep_desc_->description()->contents().size());
275 const auto& content = jsep_desc_->description()->contents()[audio_index];
276 EXPECT_EQ("0.0.0.0:9",
Qingsi Wang56991422019-02-08 12:53:06 -0800277 content.media_description()->connection_address().ToString());
278}
279
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000280// Test that we can serialize a JsepSessionDescription and deserialize it again.
281TEST_F(JsepSessionDescriptionTest, SerializeDeserialize) {
282 std::string sdp = Serialize(jsep_desc_.get());
283
Steve Antona3a92c22017-12-07 10:27:41 -0800284 auto parsed_jsep_desc = DeSerialize(sdp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285 EXPECT_EQ(2u, parsed_jsep_desc->number_of_mediasections());
286
287 std::string parsed_sdp = Serialize(parsed_jsep_desc.get());
288 EXPECT_EQ(sdp, parsed_sdp);
289}
290
Qingsi Wang3ae59d32019-07-11 21:53:45 -0700291// Test that we can serialize a JsepSessionDescription when a hostname candidate
292// is the default destination and deserialize it again. The connection address
293// in the deserialized description should be the dummy address 0.0.0.0:9.
294TEST_F(JsepSessionDescriptionTest, SerializeDeserializeWithHostnameCandidate) {
295 cricket::Candidate c;
296 c.set_component(cricket::ICE_CANDIDATE_COMPONENT_RTP);
297 c.set_protocol(cricket::UDP_PROTOCOL_NAME);
298 c.set_address(rtc::SocketAddress("example.local", 1234));
299 c.set_type(cricket::LOCAL_PORT_TYPE);
300 const size_t audio_index = 0;
301 const size_t video_index = 1;
302 JsepIceCandidate hostname_candidate_audio("audio", audio_index, c);
303 JsepIceCandidate hostname_candidate_video("video", video_index, c);
304 EXPECT_TRUE(jsep_desc_->AddCandidate(&hostname_candidate_audio));
305 EXPECT_TRUE(jsep_desc_->AddCandidate(&hostname_candidate_video));
306
307 std::string sdp = Serialize(jsep_desc_.get());
308
309 auto parsed_jsep_desc = DeSerialize(sdp);
310 EXPECT_EQ(2u, parsed_jsep_desc->number_of_mediasections());
311
312 ASSERT_NE(nullptr, parsed_jsep_desc->description());
313 ASSERT_EQ(2u, parsed_jsep_desc->description()->contents().size());
314 const auto& audio_content =
315 parsed_jsep_desc->description()->contents()[audio_index];
316 const auto& video_content =
317 parsed_jsep_desc->description()->contents()[video_index];
318 EXPECT_EQ("0.0.0.0:9",
319 audio_content.media_description()->connection_address().ToString());
320 EXPECT_EQ("0.0.0.0:9",
321 video_content.media_description()->connection_address().ToString());
322}
323
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000324// Tests that we can serialize and deserialize a JsepSesssionDescription
325// with candidates.
326TEST_F(JsepSessionDescriptionTest, SerializeDeserializeWithCandidates) {
327 std::string sdp = Serialize(jsep_desc_.get());
328
329 // Add a candidate and check that the serialized result is different.
330 JsepIceCandidate jsep_candidate("audio", 0, candidate_);
331 EXPECT_TRUE(jsep_desc_->AddCandidate(&jsep_candidate));
332 std::string sdp_with_candidate = Serialize(jsep_desc_.get());
333 EXPECT_NE(sdp, sdp_with_candidate);
334
Steve Antona3a92c22017-12-07 10:27:41 -0800335 auto parsed_jsep_desc = DeSerialize(sdp_with_candidate);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000336 std::string parsed_sdp_with_candidate = Serialize(parsed_jsep_desc.get());
337
338 EXPECT_EQ(sdp_with_candidate, parsed_sdp_with_candidate);
339}
zhihuang38989e52017-03-21 11:04:53 -0700340
341// TODO(zhihuang): Modify these tests. These are used to verify that after
342// adding the candidates, the connection_address field is set correctly. Modify
343// those so that the "connection address" is tested directly.
344// Tests serialization of SDP with only IPv6 candidates and verifies that IPv6
345// is used as default address in c line according to preference.
346TEST_F(JsepSessionDescriptionTest, SerializeSessionDescriptionWithIPv6Only) {
347 // Stun has a high preference than local host.
348 cricket::Candidate candidate1(
349 cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
350 rtc::SocketAddress("::1", 1234), kCandidatePriority, "", "",
351 cricket::STUN_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
352 cricket::Candidate candidate2(
353 cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
354 rtc::SocketAddress("::2", 1235), kCandidatePriority, "", "",
355 cricket::LOCAL_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
356
357 JsepIceCandidate jice1("audio", 0, candidate1);
358 JsepIceCandidate jice2("audio", 0, candidate2);
359 JsepIceCandidate jice3("video", 0, candidate1);
360 JsepIceCandidate jice4("video", 0, candidate2);
361 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice1));
362 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice2));
363 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice3));
364 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice4));
365 std::string message = Serialize(jsep_desc_.get());
366
367 // Should have a c line like this one.
368 EXPECT_NE(message.find("c=IN IP6 ::1"), std::string::npos);
369 // Shouldn't have a IP4 c line.
370 EXPECT_EQ(message.find("c=IN IP4"), std::string::npos);
371}
372
373// Tests serialization of SDP with both IPv4 and IPv6 candidates and
374// verifies that IPv4 is used as default address in c line even if the
375// preference of IPv4 is lower.
376TEST_F(JsepSessionDescriptionTest,
377 SerializeSessionDescriptionWithBothIPFamilies) {
378 cricket::Candidate candidate_v4(
379 cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
380 rtc::SocketAddress("192.168.1.5", 1234), kCandidatePriority, "", "",
381 cricket::STUN_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
382 cricket::Candidate candidate_v6(
383 cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
384 rtc::SocketAddress("::1", 1234), kCandidatePriority, "", "",
385 cricket::LOCAL_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
386
387 JsepIceCandidate jice_v4("audio", 0, candidate_v4);
388 JsepIceCandidate jice_v6("audio", 0, candidate_v6);
389 JsepIceCandidate jice_v4_video("video", 0, candidate_v4);
390 JsepIceCandidate jice_v6_video("video", 0, candidate_v6);
391 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v4));
392 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v6));
393 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v4_video));
394 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v6_video));
395 std::string message = Serialize(jsep_desc_.get());
396
397 // Should have a c line like this one.
398 EXPECT_NE(message.find("c=IN IP4 192.168.1.5"), std::string::npos);
399 // Shouldn't have a IP6 c line.
400 EXPECT_EQ(message.find("c=IN IP6"), std::string::npos);
401}
402
403// Tests serialization of SDP with both UDP and TCP candidates and
404// verifies that UDP is used as default address in c line even if the
405// preference of UDP is lower.
406TEST_F(JsepSessionDescriptionTest,
407 SerializeSessionDescriptionWithBothProtocols) {
408 // Stun has a high preference than local host.
409 cricket::Candidate candidate1(
410 cricket::ICE_CANDIDATE_COMPONENT_RTP, "tcp",
411 rtc::SocketAddress("::1", 1234), kCandidatePriority, "", "",
412 cricket::STUN_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
413 cricket::Candidate candidate2(
414 cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
415 rtc::SocketAddress("fe80::1234:5678:abcd:ef12", 1235), kCandidatePriority,
416 "", "", cricket::LOCAL_PORT_TYPE, kCandidateGeneration,
417 kCandidateFoundation);
418
419 JsepIceCandidate jice1("audio", 0, candidate1);
420 JsepIceCandidate jice2("audio", 0, candidate2);
421 JsepIceCandidate jice3("video", 0, candidate1);
422 JsepIceCandidate jice4("video", 0, candidate2);
423 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice1));
424 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice2));
425 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice3));
426 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice4));
427 std::string message = Serialize(jsep_desc_.get());
428
429 // Should have a c line like this one.
430 EXPECT_NE(message.find("c=IN IP6 fe80::1234:5678:abcd:ef12"),
431 std::string::npos);
432 // Shouldn't have a IP4 c line.
433 EXPECT_EQ(message.find("c=IN IP4"), std::string::npos);
434}
435
436// Tests serialization of SDP with only TCP candidates and verifies that
437// null IPv4 is used as default address in c line.
438TEST_F(JsepSessionDescriptionTest, SerializeSessionDescriptionWithTCPOnly) {
439 // Stun has a high preference than local host.
440 cricket::Candidate candidate1(
441 cricket::ICE_CANDIDATE_COMPONENT_RTP, "tcp",
442 rtc::SocketAddress("::1", 1234), kCandidatePriority, "", "",
443 cricket::STUN_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
444 cricket::Candidate candidate2(
445 cricket::ICE_CANDIDATE_COMPONENT_RTP, "tcp",
446 rtc::SocketAddress("::2", 1235), kCandidatePriority, "", "",
447 cricket::LOCAL_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
448
449 JsepIceCandidate jice1("audio", 0, candidate1);
450 JsepIceCandidate jice2("audio", 0, candidate2);
451 JsepIceCandidate jice3("video", 0, candidate1);
452 JsepIceCandidate jice4("video", 0, candidate2);
453 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice1));
454 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice2));
455 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice3));
456 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice4));
457
458 std::string message = Serialize(jsep_desc_.get());
459 EXPECT_EQ(message.find("c=IN IP6 ::3"), std::string::npos);
460 // Should have a c line like this one when no any default exists.
461 EXPECT_NE(message.find("c=IN IP4 0.0.0.0"), std::string::npos);
462}
463
464// Tests that the connection address will be correctly set when the Candidate is
465// removed.
466TEST_F(JsepSessionDescriptionTest, RemoveCandidateAndSetConnectionAddress) {
467 cricket::Candidate candidate1(
468 cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
469 rtc::SocketAddress("::1", 1234), kCandidatePriority, "", "",
470 cricket::LOCAL_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
471 candidate1.set_transport_name("audio");
472
473 cricket::Candidate candidate2(
474 cricket::ICE_CANDIDATE_COMPONENT_RTP, "tcp",
475 rtc::SocketAddress("::2", 1235), kCandidatePriority, "", "",
476 cricket::LOCAL_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
477 candidate2.set_transport_name("audio");
478
479 cricket::Candidate candidate3(
480 cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
481 rtc::SocketAddress("192.168.1.1", 1236), kCandidatePriority, "", "",
482 cricket::LOCAL_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
483 candidate3.set_transport_name("audio");
484
485 JsepIceCandidate jice1("audio", 0, candidate1);
486 JsepIceCandidate jice2("audio", 0, candidate2);
487 JsepIceCandidate jice3("audio", 0, candidate3);
488
489 size_t audio_index = 0;
Steve Antonb1c1de12017-12-21 15:14:30 -0800490 auto media_desc =
491 jsep_desc_->description()->contents()[audio_index].media_description();
zhihuang38989e52017-03-21 11:04:53 -0700492
493 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice1));
494 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice2));
495 ASSERT_TRUE(jsep_desc_->AddCandidate(&jice3));
496
497 std::vector<cricket::Candidate> candidates;
498 EXPECT_EQ("192.168.1.1:1236", media_desc->connection_address().ToString());
499
500 candidates.push_back(candidate3);
501 ASSERT_TRUE(jsep_desc_->RemoveCandidates(candidates));
502 EXPECT_EQ("[::1]:1234", media_desc->connection_address().ToString());
503
504 candidates.clear();
505 candidates.push_back(candidate2);
506 ASSERT_TRUE(jsep_desc_->RemoveCandidates(candidates));
507 EXPECT_EQ("[::1]:1234", media_desc->connection_address().ToString());
508
509 candidates.clear();
510 candidates.push_back(candidate1);
511 ASSERT_TRUE(jsep_desc_->RemoveCandidates(candidates));
512 EXPECT_EQ("0.0.0.0:9", media_desc->connection_address().ToString());
513}
Steve Anton88f2cb92017-12-05 12:47:32 -0800514
515class EnumerateAllSdpTypesTest : public ::testing::Test,
516 public ::testing::WithParamInterface<SdpType> {
517};
518
519TEST_P(EnumerateAllSdpTypesTest, TestIdentity) {
520 SdpType type = GetParam();
521
522 const char* str = webrtc::SdpTypeToString(type);
523 EXPECT_EQ(type, webrtc::SdpTypeFromString(str));
524}
525
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100526INSTANTIATE_TEST_SUITE_P(JsepSessionDescriptionTest,
527 EnumerateAllSdpTypesTest,
528 Values(SdpType::kOffer,
529 SdpType::kPrAnswer,
530 SdpType::kAnswer));