3 * Copyright 2011 Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "talk/p2p/base/constants.h"
29 #include "talk/p2p/base/fakesession.h"
30 #include "talk/p2p/base/p2ptransport.h"
31 #include "talk/p2p/base/parsing.h"
32 #include "talk/p2p/base/rawtransport.h"
33 #include "talk/p2p/base/sessionmessages.h"
34 #include "webrtc/libjingle/xmllite/xmlelement.h"
35 #include "talk/xmpp/constants.h"
36 #include "webrtc/base/fakesslidentity.h"
37 #include "webrtc/base/gunit.h"
38 #include "webrtc/base/thread.h"
40 using cricket::Candidate;
41 using cricket::Candidates;
42 using cricket::Transport;
43 using cricket::FakeTransport;
44 using cricket::TransportChannel;
45 using cricket::FakeTransportChannel;
46 using cricket::IceRole;
47 using cricket::TransportDescription;
48 using cricket::WriteError;
49 using cricket::ParseError;
50 using rtc::SocketAddress;
52 static const char kIceUfrag1[] = "TESTICEUFRAG0001";
53 static const char kIcePwd1[] = "TESTICEPWD00000000000001";
55 static const char kIceUfrag2[] = "TESTICEUFRAG0002";
56 static const char kIcePwd2[] = "TESTICEPWD00000000000002";
58 class TransportTest : public testing::Test,
59 public sigslot::has_slots<> {
62 : thread_(rtc::Thread::Current()),
63 transport_(new FakeTransport(
64 thread_, thread_, "test content name", NULL)),
66 connecting_signalled_(false),
69 transport_->SignalConnecting.connect(this, &TransportTest::OnConnecting);
70 transport_->SignalCompleted.connect(this, &TransportTest::OnCompleted);
71 transport_->SignalFailed.connect(this, &TransportTest::OnFailed);
74 transport_->DestroyAllChannels();
77 channel_ = CreateChannel(1);
78 return (channel_ != NULL);
80 FakeTransportChannel* CreateChannel(int component) {
81 return static_cast<FakeTransportChannel*>(
82 transport_->CreateChannel(component));
84 void DestroyChannel() {
85 transport_->DestroyChannel(1);
90 void OnConnecting(Transport* transport) {
91 connecting_signalled_ = true;
93 void OnCompleted(Transport* transport) {
96 void OnFailed(Transport* transport) {
100 rtc::Thread* thread_;
101 rtc::scoped_ptr<FakeTransport> transport_;
102 FakeTransportChannel* channel_;
103 bool connecting_signalled_;
108 class FakeCandidateTranslator : public cricket::CandidateTranslator {
110 void AddMapping(int component, const std::string& channel_name) {
111 name_to_component[channel_name] = component;
112 component_to_name[component] = channel_name;
115 bool GetChannelNameFromComponent(
116 int component, std::string* channel_name) const {
117 if (component_to_name.find(component) == component_to_name.end()) {
120 *channel_name = component_to_name.find(component)->second;
123 bool GetComponentFromChannelName(
124 const std::string& channel_name, int* component) const {
125 if (name_to_component.find(channel_name) == name_to_component.end()) {
128 *component = name_to_component.find(channel_name)->second;
132 std::map<std::string, int> name_to_component;
133 std::map<int, std::string> component_to_name;
136 // Test that calling ConnectChannels triggers an OnConnecting signal.
137 TEST_F(TransportTest, TestConnectChannelsDoesSignal) {
138 EXPECT_TRUE(SetupChannel());
139 transport_->ConnectChannels();
140 EXPECT_FALSE(connecting_signalled_);
142 EXPECT_TRUE_WAIT(connecting_signalled_, 100);
145 // Test that DestroyAllChannels kills any pending OnConnecting signals.
146 TEST_F(TransportTest, TestDestroyAllClearsPosts) {
147 EXPECT_TRUE(transport_->CreateChannel(1) != NULL);
149 transport_->ConnectChannels();
150 transport_->DestroyAllChannels();
152 thread_->ProcessMessages(0);
153 EXPECT_FALSE(connecting_signalled_);
156 // This test verifies channels are created with proper ICE
157 // role, tiebreaker and remote ice mode and credentials after offer and
158 // answer negotiations.
159 TEST_F(TransportTest, TestChannelIceParameters) {
160 transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
161 transport_->SetIceTiebreaker(99U);
162 cricket::TransportDescription local_desc(
163 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
164 ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
167 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
168 EXPECT_TRUE(SetupChannel());
169 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
170 EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
171 EXPECT_EQ(kIceUfrag1, channel_->ice_ufrag());
172 EXPECT_EQ(kIcePwd1, channel_->ice_pwd());
174 cricket::TransportDescription remote_desc(
175 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
176 ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
179 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
180 EXPECT_EQ(99U, channel_->IceTiebreaker());
181 EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
182 // Changing the transport role from CONTROLLING to CONTROLLED.
183 transport_->SetIceRole(cricket::ICEROLE_CONTROLLED);
184 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel_->GetIceRole());
185 EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
186 EXPECT_EQ(kIceUfrag1, channel_->remote_ice_ufrag());
187 EXPECT_EQ(kIcePwd1, channel_->remote_ice_pwd());
190 // Verifies that IceCredentialsChanged returns true when either ufrag or pwd
191 // changed, and false in other cases.
192 TEST_F(TransportTest, TestIceCredentialsChanged) {
193 EXPECT_TRUE(cricket::IceCredentialsChanged("u1", "p1", "u2", "p2"));
194 EXPECT_TRUE(cricket::IceCredentialsChanged("u1", "p1", "u2", "p1"));
195 EXPECT_TRUE(cricket::IceCredentialsChanged("u1", "p1", "u1", "p2"));
196 EXPECT_FALSE(cricket::IceCredentialsChanged("u1", "p1", "u1", "p1"));
199 // This test verifies that the callee's ICE role changes from controlled to
200 // controlling when the callee triggers an ICE restart.
201 TEST_F(TransportTest, TestIceControlledToControllingOnIceRestart) {
202 EXPECT_TRUE(SetupChannel());
203 transport_->SetIceRole(cricket::ICEROLE_CONTROLLED);
205 cricket::TransportDescription desc(
206 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
207 ASSERT_TRUE(transport_->SetRemoteTransportDescription(desc,
210 ASSERT_TRUE(transport_->SetLocalTransportDescription(desc,
213 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, transport_->ice_role());
215 cricket::TransportDescription new_local_desc(
216 cricket::NS_JINGLE_ICE_UDP, kIceUfrag2, kIcePwd2);
217 ASSERT_TRUE(transport_->SetLocalTransportDescription(new_local_desc,
220 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
221 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
224 // This test verifies that the caller's ICE role changes from controlling to
225 // controlled when the callee triggers an ICE restart.
226 TEST_F(TransportTest, TestIceControllingToControlledOnIceRestart) {
227 EXPECT_TRUE(SetupChannel());
228 transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
230 cricket::TransportDescription desc(
231 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
232 ASSERT_TRUE(transport_->SetLocalTransportDescription(desc,
235 ASSERT_TRUE(transport_->SetRemoteTransportDescription(desc,
238 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
240 cricket::TransportDescription new_local_desc(
241 cricket::NS_JINGLE_ICE_UDP, kIceUfrag2, kIcePwd2);
242 ASSERT_TRUE(transport_->SetLocalTransportDescription(new_local_desc,
245 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, transport_->ice_role());
246 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel_->GetIceRole());
249 // This test verifies that the caller's ICE role is still controlling after the
250 // callee triggers ICE restart if the callee's ICE mode is LITE.
251 TEST_F(TransportTest, TestIceControllingOnIceRestartIfRemoteIsIceLite) {
252 EXPECT_TRUE(SetupChannel());
253 transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
255 cricket::TransportDescription desc(
256 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
257 ASSERT_TRUE(transport_->SetLocalTransportDescription(desc,
261 cricket::TransportDescription remote_desc(
262 cricket::NS_JINGLE_ICE_UDP, std::vector<std::string>(),
263 kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE,
264 cricket::CONNECTIONROLE_NONE, NULL, cricket::Candidates());
265 ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
269 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
271 cricket::TransportDescription new_local_desc(
272 cricket::NS_JINGLE_ICE_UDP, kIceUfrag2, kIcePwd2);
273 ASSERT_TRUE(transport_->SetLocalTransportDescription(new_local_desc,
276 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
277 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
280 // This test verifies that the Completed and Failed states can be reached.
281 TEST_F(TransportTest, TestChannelCompletedAndFailed) {
282 transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
283 cricket::TransportDescription local_desc(
284 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
285 ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
288 EXPECT_TRUE(SetupChannel());
290 cricket::TransportDescription remote_desc(
291 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
292 ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
296 channel_->SetConnectionCount(2);
297 channel_->SignalCandidatesAllocationDone(channel_);
298 channel_->SetWritable(true);
299 EXPECT_TRUE_WAIT(transport_->all_channels_writable(), 100);
300 // ICE is not yet completed because there is still more than one connection.
301 EXPECT_FALSE(completed_);
302 EXPECT_FALSE(failed_);
304 // When the connection count drops to 1, SignalCompleted should be emitted,
305 // and completed() should be true.
306 channel_->SetConnectionCount(1);
307 EXPECT_TRUE_WAIT(completed_, 100);
310 // When the connection count drops to 0, SignalFailed should be emitted, and
311 // completed() should be false.
312 channel_->SetConnectionCount(0);
313 EXPECT_TRUE_WAIT(failed_, 100);
314 EXPECT_FALSE(completed_);
317 // Tests channel role is reversed after receiving ice-lite from remote.
318 TEST_F(TransportTest, TestSetRemoteIceLiteInOffer) {
319 transport_->SetIceRole(cricket::ICEROLE_CONTROLLED);
320 cricket::TransportDescription remote_desc(
321 cricket::NS_JINGLE_ICE_UDP, std::vector<std::string>(),
322 kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE,
323 cricket::CONNECTIONROLE_ACTPASS, NULL, cricket::Candidates());
324 ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
327 cricket::TransportDescription local_desc(
328 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
329 ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
332 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
333 EXPECT_TRUE(SetupChannel());
334 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
335 EXPECT_EQ(cricket::ICEMODE_LITE, channel_->remote_ice_mode());
338 // Tests ice-lite in remote answer.
339 TEST_F(TransportTest, TestSetRemoteIceLiteInAnswer) {
340 transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
341 cricket::TransportDescription local_desc(
342 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
343 ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
346 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
347 EXPECT_TRUE(SetupChannel());
348 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
349 // Channels will be created in ICEFULL_MODE.
350 EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
351 cricket::TransportDescription remote_desc(
352 cricket::NS_JINGLE_ICE_UDP, std::vector<std::string>(),
353 kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE,
354 cricket::CONNECTIONROLE_NONE, NULL, cricket::Candidates());
355 ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
358 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
359 // After receiving remote description with ICEMODE_LITE, channel should
360 // have mode set to ICEMODE_LITE.
361 EXPECT_EQ(cricket::ICEMODE_LITE, channel_->remote_ice_mode());
364 // Tests that we can properly serialize/deserialize candidates.
365 TEST_F(TransportTest, TestP2PTransportWriteAndParseCandidate) {
366 Candidate test_candidate(
368 rtc::SocketAddress("2001:db8:fefe::1", 9999),
369 738197504, "abcdef", "ghijkl", "foo", "testnet", 50, "");
370 Candidate test_candidate2(
372 rtc::SocketAddress("192.168.7.1", 9999),
373 1107296256, "mnopqr", "stuvwx", "bar", "testnet2", 100, "");
374 rtc::SocketAddress host_address("www.google.com", 24601);
375 host_address.SetResolvedIP(rtc::IPAddress(0x0A000001));
376 Candidate test_candidate3(
377 "", 3, "spdy", host_address, 1476395008, "yzabcd",
378 "efghij", "baz", "testnet3", 150, "");
379 WriteError write_error;
380 ParseError parse_error;
381 rtc::scoped_ptr<buzz::XmlElement> elem;
382 cricket::Candidate parsed_candidate;
383 cricket::P2PTransportParser parser;
385 FakeCandidateTranslator translator;
386 translator.AddMapping(1, "test");
387 translator.AddMapping(2, "test2");
388 translator.AddMapping(3, "test3");
390 EXPECT_TRUE(parser.WriteGingleCandidate(test_candidate, &translator,
391 elem.accept(), &write_error));
392 EXPECT_EQ("", write_error.text);
393 EXPECT_EQ("test", elem->Attr(buzz::QN_NAME));
394 EXPECT_EQ("udp", elem->Attr(cricket::QN_PROTOCOL));
395 EXPECT_EQ("2001:db8:fefe::1", elem->Attr(cricket::QN_ADDRESS));
396 EXPECT_EQ("9999", elem->Attr(cricket::QN_PORT));
397 EXPECT_EQ("0.34", elem->Attr(cricket::QN_PREFERENCE));
398 EXPECT_EQ("abcdef", elem->Attr(cricket::QN_USERNAME));
399 EXPECT_EQ("ghijkl", elem->Attr(cricket::QN_PASSWORD));
400 EXPECT_EQ("foo", elem->Attr(cricket::QN_TYPE));
401 EXPECT_EQ("testnet", elem->Attr(cricket::QN_NETWORK));
402 EXPECT_EQ("50", elem->Attr(cricket::QN_GENERATION));
404 EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
405 &parsed_candidate, &parse_error));
406 EXPECT_TRUE(test_candidate.IsEquivalent(parsed_candidate));
408 EXPECT_TRUE(parser.WriteGingleCandidate(test_candidate2, &translator,
409 elem.accept(), &write_error));
410 EXPECT_EQ("test2", elem->Attr(buzz::QN_NAME));
411 EXPECT_EQ("tcp", elem->Attr(cricket::QN_PROTOCOL));
412 EXPECT_EQ("192.168.7.1", elem->Attr(cricket::QN_ADDRESS));
413 EXPECT_EQ("9999", elem->Attr(cricket::QN_PORT));
414 EXPECT_EQ("0.51", elem->Attr(cricket::QN_PREFERENCE));
415 EXPECT_EQ("mnopqr", elem->Attr(cricket::QN_USERNAME));
416 EXPECT_EQ("stuvwx", elem->Attr(cricket::QN_PASSWORD));
417 EXPECT_EQ("bar", elem->Attr(cricket::QN_TYPE));
418 EXPECT_EQ("testnet2", elem->Attr(cricket::QN_NETWORK));
419 EXPECT_EQ("100", elem->Attr(cricket::QN_GENERATION));
421 EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
422 &parsed_candidate, &parse_error));
423 EXPECT_TRUE(test_candidate2.IsEquivalent(parsed_candidate));
425 // Check that an ip is preferred over hostname.
426 EXPECT_TRUE(parser.WriteGingleCandidate(test_candidate3, &translator,
427 elem.accept(), &write_error));
428 EXPECT_EQ("test3", elem->Attr(cricket::QN_NAME));
429 EXPECT_EQ("spdy", elem->Attr(cricket::QN_PROTOCOL));
430 EXPECT_EQ("10.0.0.1", elem->Attr(cricket::QN_ADDRESS));
431 EXPECT_EQ("24601", elem->Attr(cricket::QN_PORT));
432 EXPECT_EQ("0.69", elem->Attr(cricket::QN_PREFERENCE));
433 EXPECT_EQ("yzabcd", elem->Attr(cricket::QN_USERNAME));
434 EXPECT_EQ("efghij", elem->Attr(cricket::QN_PASSWORD));
435 EXPECT_EQ("baz", elem->Attr(cricket::QN_TYPE));
436 EXPECT_EQ("testnet3", elem->Attr(cricket::QN_NETWORK));
437 EXPECT_EQ("150", elem->Attr(cricket::QN_GENERATION));
439 EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
440 &parsed_candidate, &parse_error));
441 EXPECT_TRUE(test_candidate3.IsEquivalent(parsed_candidate));
444 TEST_F(TransportTest, TestGetStats) {
445 EXPECT_TRUE(SetupChannel());
446 cricket::TransportStats stats;
447 EXPECT_TRUE(transport_->GetStats(&stats));
448 // Note that this tests the behavior of a FakeTransportChannel.
449 ASSERT_EQ(1U, stats.channel_stats.size());
450 EXPECT_EQ(1, stats.channel_stats[0].component);
451 transport_->ConnectChannels();
452 EXPECT_TRUE(transport_->GetStats(&stats));
453 ASSERT_EQ(1U, stats.channel_stats.size());
454 EXPECT_EQ(1, stats.channel_stats[0].component);