blob: b91b1a0d0aa8f2eb455b333689fac40fc3b9a72c [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2011 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
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.
15 *
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.
26 */
27
28#include "talk/base/fakesslidentity.h"
29#include "talk/base/gunit.h"
30#include "talk/base/thread.h"
31#include "talk/p2p/base/constants.h"
32#include "talk/p2p/base/fakesession.h"
33#include "talk/p2p/base/parsing.h"
34#include "talk/p2p/base/p2ptransport.h"
35#include "talk/p2p/base/rawtransport.h"
36#include "talk/p2p/base/sessionmessages.h"
37#include "talk/xmllite/xmlelement.h"
38#include "talk/xmpp/constants.h"
39
40using cricket::Candidate;
41using cricket::Candidates;
42using cricket::Transport;
43using cricket::FakeTransport;
44using cricket::TransportChannel;
45using cricket::FakeTransportChannel;
mallinath@webrtc.orga5506692013-08-12 21:18:15 +000046using cricket::IceRole;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000047using cricket::TransportDescription;
48using cricket::WriteError;
49using cricket::ParseError;
50using talk_base::SocketAddress;
51
52static const char kIceUfrag1[] = "TESTICEUFRAG0001";
53static const char kIcePwd1[] = "TESTICEPWD00000000000001";
54
55class TransportTest : public testing::Test,
56 public sigslot::has_slots<> {
57 public:
58 TransportTest()
59 : thread_(talk_base::Thread::Current()),
60 transport_(new FakeTransport(
61 thread_, thread_, "test content name", NULL)),
62 channel_(NULL),
mallinath@webrtc.org385857d2014-02-14 00:56:12 +000063 connecting_signalled_(false),
64 completed_(false),
65 failed_(false) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066 transport_->SignalConnecting.connect(this, &TransportTest::OnConnecting);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +000067 transport_->SignalCompleted.connect(this, &TransportTest::OnCompleted);
68 transport_->SignalFailed.connect(this, &TransportTest::OnFailed);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000069 }
70 ~TransportTest() {
71 transport_->DestroyAllChannels();
72 }
73 bool SetupChannel() {
74 channel_ = CreateChannel(1);
75 return (channel_ != NULL);
76 }
77 FakeTransportChannel* CreateChannel(int component) {
78 return static_cast<FakeTransportChannel*>(
79 transport_->CreateChannel(component));
80 }
81 void DestroyChannel() {
82 transport_->DestroyChannel(1);
83 channel_ = NULL;
84 }
85
86 protected:
87 void OnConnecting(Transport* transport) {
88 connecting_signalled_ = true;
89 }
mallinath@webrtc.org385857d2014-02-14 00:56:12 +000090 void OnCompleted(Transport* transport) {
91 completed_ = true;
92 }
93 void OnFailed(Transport* transport) {
94 failed_ = true;
95 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000096
97 talk_base::Thread* thread_;
98 talk_base::scoped_ptr<FakeTransport> transport_;
99 FakeTransportChannel* channel_;
100 bool connecting_signalled_;
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000101 bool completed_;
102 bool failed_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103};
104
105class FakeCandidateTranslator : public cricket::CandidateTranslator {
106 public:
107 void AddMapping(int component, const std::string& channel_name) {
108 name_to_component[channel_name] = component;
109 component_to_name[component] = channel_name;
110 }
111
112 bool GetChannelNameFromComponent(
113 int component, std::string* channel_name) const {
114 if (component_to_name.find(component) == component_to_name.end()) {
115 return false;
116 }
117 *channel_name = component_to_name.find(component)->second;
118 return true;
119 }
120 bool GetComponentFromChannelName(
121 const std::string& channel_name, int* component) const {
122 if (name_to_component.find(channel_name) == name_to_component.end()) {
123 return false;
124 }
125 *component = name_to_component.find(channel_name)->second;
126 return true;
127 }
128
129 std::map<std::string, int> name_to_component;
130 std::map<int, std::string> component_to_name;
131};
132
133// Test that calling ConnectChannels triggers an OnConnecting signal.
134TEST_F(TransportTest, TestConnectChannelsDoesSignal) {
135 EXPECT_TRUE(SetupChannel());
136 transport_->ConnectChannels();
137 EXPECT_FALSE(connecting_signalled_);
138
139 EXPECT_TRUE_WAIT(connecting_signalled_, 100);
140}
141
142// Test that DestroyAllChannels kills any pending OnConnecting signals.
143TEST_F(TransportTest, TestDestroyAllClearsPosts) {
144 EXPECT_TRUE(transport_->CreateChannel(1) != NULL);
145
146 transport_->ConnectChannels();
147 transport_->DestroyAllChannels();
148
149 thread_->ProcessMessages(0);
150 EXPECT_FALSE(connecting_signalled_);
151}
152
153// This test verifies channels are created with proper ICE
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000154// role, tiebreaker and remote ice mode and credentials after offer and
155// answer negotiations.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000156TEST_F(TransportTest, TestChannelIceParameters) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000157 transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
158 transport_->SetIceTiebreaker(99U);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000159 cricket::TransportDescription local_desc(
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000160 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161 ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000162 cricket::CA_OFFER,
163 NULL));
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000164 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000165 EXPECT_TRUE(SetupChannel());
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000166 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000167 EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
168 EXPECT_EQ(kIceUfrag1, channel_->ice_ufrag());
169 EXPECT_EQ(kIcePwd1, channel_->ice_pwd());
170
171 cricket::TransportDescription remote_desc(
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000172 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000173 ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000174 cricket::CA_ANSWER,
175 NULL));
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000176 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
177 EXPECT_EQ(99U, channel_->IceTiebreaker());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000178 EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
179 // Changing the transport role from CONTROLLING to CONTROLLED.
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000180 transport_->SetIceRole(cricket::ICEROLE_CONTROLLED);
181 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel_->GetIceRole());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000182 EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
183 EXPECT_EQ(kIceUfrag1, channel_->remote_ice_ufrag());
184 EXPECT_EQ(kIcePwd1, channel_->remote_ice_pwd());
185}
186
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000187// This test verifies that the Completed and Failed states can be reached.
188TEST_F(TransportTest, TestChannelCompletedAndFailed) {
189 transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
190 cricket::TransportDescription local_desc(
191 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
192 ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
193 cricket::CA_OFFER,
194 NULL));
195 EXPECT_TRUE(SetupChannel());
196
197 cricket::TransportDescription remote_desc(
198 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
199 ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
200 cricket::CA_ANSWER,
201 NULL));
202
203 channel_->SetConnectionCount(2);
204 channel_->SignalCandidatesAllocationDone(channel_);
205 channel_->SetWritable(true);
206 EXPECT_TRUE_WAIT(transport_->all_channels_writable(), 100);
207 // ICE is not yet completed because there is still more than one connection.
208 EXPECT_FALSE(completed_);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000209 EXPECT_FALSE(failed_);
210
211 // When the connection count drops to 1, SignalCompleted should be emitted,
212 // and completed() should be true.
213 channel_->SetConnectionCount(1);
214 EXPECT_TRUE_WAIT(completed_, 100);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000215 completed_ = false;
216
217 // When the connection count drops to 0, SignalFailed should be emitted, and
218 // completed() should be false.
219 channel_->SetConnectionCount(0);
220 EXPECT_TRUE_WAIT(failed_, 100);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000221 EXPECT_FALSE(completed_);
222}
223
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000224// Tests channel role is reversed after receiving ice-lite from remote.
225TEST_F(TransportTest, TestSetRemoteIceLiteInOffer) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000226 transport_->SetIceRole(cricket::ICEROLE_CONTROLLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000227 cricket::TransportDescription remote_desc(
228 cricket::NS_JINGLE_ICE_UDP, std::vector<std::string>(),
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000229 kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE,
230 cricket::CONNECTIONROLE_ACTPASS, NULL, cricket::Candidates());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000231 ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000232 cricket::CA_OFFER,
233 NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000234 cricket::TransportDescription local_desc(
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000235 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000236 ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000237 cricket::CA_ANSWER,
238 NULL));
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000239 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000240 EXPECT_TRUE(SetupChannel());
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000241 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000242 EXPECT_EQ(cricket::ICEMODE_LITE, channel_->remote_ice_mode());
243}
244
245// Tests ice-lite in remote answer.
246TEST_F(TransportTest, TestSetRemoteIceLiteInAnswer) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000247 transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000248 cricket::TransportDescription local_desc(
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000249 cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000250 ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000251 cricket::CA_OFFER,
252 NULL));
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000253 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000254 EXPECT_TRUE(SetupChannel());
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000255 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000256 // Channels will be created in ICEFULL_MODE.
257 EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
258 cricket::TransportDescription remote_desc(
259 cricket::NS_JINGLE_ICE_UDP, std::vector<std::string>(),
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000260 kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE,
261 cricket::CONNECTIONROLE_NONE, NULL, cricket::Candidates());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000262 ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000263 cricket::CA_ANSWER,
264 NULL));
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000265 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000266 // After receiving remote description with ICEMODE_LITE, channel should
267 // have mode set to ICEMODE_LITE.
268 EXPECT_EQ(cricket::ICEMODE_LITE, channel_->remote_ice_mode());
269}
270
271// Tests that we can properly serialize/deserialize candidates.
272TEST_F(TransportTest, TestP2PTransportWriteAndParseCandidate) {
273 Candidate test_candidate(
274 "", 1, "udp",
275 talk_base::SocketAddress("2001:db8:fefe::1", 9999),
276 738197504, "abcdef", "ghijkl", "foo", "testnet", 50, "");
277 Candidate test_candidate2(
278 "", 2, "tcp",
279 talk_base::SocketAddress("192.168.7.1", 9999),
280 1107296256, "mnopqr", "stuvwx", "bar", "testnet2", 100, "");
281 talk_base::SocketAddress host_address("www.google.com", 24601);
282 host_address.SetResolvedIP(talk_base::IPAddress(0x0A000001));
283 Candidate test_candidate3(
284 "", 3, "spdy", host_address, 1476395008, "yzabcd",
285 "efghij", "baz", "testnet3", 150, "");
286 WriteError write_error;
287 ParseError parse_error;
288 talk_base::scoped_ptr<buzz::XmlElement> elem;
289 cricket::Candidate parsed_candidate;
290 cricket::P2PTransportParser parser;
291
292 FakeCandidateTranslator translator;
293 translator.AddMapping(1, "test");
294 translator.AddMapping(2, "test2");
295 translator.AddMapping(3, "test3");
296
297 EXPECT_TRUE(parser.WriteGingleCandidate(test_candidate, &translator,
298 elem.accept(), &write_error));
299 EXPECT_EQ("", write_error.text);
300 EXPECT_EQ("test", elem->Attr(buzz::QN_NAME));
301 EXPECT_EQ("udp", elem->Attr(cricket::QN_PROTOCOL));
302 EXPECT_EQ("2001:db8:fefe::1", elem->Attr(cricket::QN_ADDRESS));
303 EXPECT_EQ("9999", elem->Attr(cricket::QN_PORT));
304 EXPECT_EQ("0.34", elem->Attr(cricket::QN_PREFERENCE));
305 EXPECT_EQ("abcdef", elem->Attr(cricket::QN_USERNAME));
306 EXPECT_EQ("ghijkl", elem->Attr(cricket::QN_PASSWORD));
307 EXPECT_EQ("foo", elem->Attr(cricket::QN_TYPE));
308 EXPECT_EQ("testnet", elem->Attr(cricket::QN_NETWORK));
309 EXPECT_EQ("50", elem->Attr(cricket::QN_GENERATION));
310
311 EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
312 &parsed_candidate, &parse_error));
313 EXPECT_TRUE(test_candidate.IsEquivalent(parsed_candidate));
314
315 EXPECT_TRUE(parser.WriteGingleCandidate(test_candidate2, &translator,
316 elem.accept(), &write_error));
317 EXPECT_EQ("test2", elem->Attr(buzz::QN_NAME));
318 EXPECT_EQ("tcp", elem->Attr(cricket::QN_PROTOCOL));
319 EXPECT_EQ("192.168.7.1", elem->Attr(cricket::QN_ADDRESS));
320 EXPECT_EQ("9999", elem->Attr(cricket::QN_PORT));
321 EXPECT_EQ("0.51", elem->Attr(cricket::QN_PREFERENCE));
322 EXPECT_EQ("mnopqr", elem->Attr(cricket::QN_USERNAME));
323 EXPECT_EQ("stuvwx", elem->Attr(cricket::QN_PASSWORD));
324 EXPECT_EQ("bar", elem->Attr(cricket::QN_TYPE));
325 EXPECT_EQ("testnet2", elem->Attr(cricket::QN_NETWORK));
326 EXPECT_EQ("100", elem->Attr(cricket::QN_GENERATION));
327
328 EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
329 &parsed_candidate, &parse_error));
330 EXPECT_TRUE(test_candidate2.IsEquivalent(parsed_candidate));
331
332 // Check that an ip is preferred over hostname.
333 EXPECT_TRUE(parser.WriteGingleCandidate(test_candidate3, &translator,
334 elem.accept(), &write_error));
335 EXPECT_EQ("test3", elem->Attr(cricket::QN_NAME));
336 EXPECT_EQ("spdy", elem->Attr(cricket::QN_PROTOCOL));
337 EXPECT_EQ("10.0.0.1", elem->Attr(cricket::QN_ADDRESS));
338 EXPECT_EQ("24601", elem->Attr(cricket::QN_PORT));
339 EXPECT_EQ("0.69", elem->Attr(cricket::QN_PREFERENCE));
340 EXPECT_EQ("yzabcd", elem->Attr(cricket::QN_USERNAME));
341 EXPECT_EQ("efghij", elem->Attr(cricket::QN_PASSWORD));
342 EXPECT_EQ("baz", elem->Attr(cricket::QN_TYPE));
343 EXPECT_EQ("testnet3", elem->Attr(cricket::QN_NETWORK));
344 EXPECT_EQ("150", elem->Attr(cricket::QN_GENERATION));
345
346 EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
347 &parsed_candidate, &parse_error));
348 EXPECT_TRUE(test_candidate3.IsEquivalent(parsed_candidate));
349}
350
351TEST_F(TransportTest, TestGetStats) {
352 EXPECT_TRUE(SetupChannel());
353 cricket::TransportStats stats;
354 EXPECT_TRUE(transport_->GetStats(&stats));
355 // Note that this tests the behavior of a FakeTransportChannel.
356 ASSERT_EQ(1U, stats.channel_stats.size());
357 EXPECT_EQ(1, stats.channel_stats[0].component);
358 transport_->ConnectChannels();
359 EXPECT_TRUE(transport_->GetStats(&stats));
360 ASSERT_EQ(1U, stats.channel_stats.size());
361 EXPECT_EQ(1, stats.channel_stats[0].component);
362}