1/*
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/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"
39
40using cricket::Candidate;
41using cricket::Candidates;
42using cricket::Transport;
43using cricket::FakeTransport;
44using cricket::TransportChannel;
45using cricket::FakeTransportChannel;
46using cricket::IceRole;
47using cricket::TransportDescription;
48using cricket::WriteError;
49using cricket::ParseError;
50using rtc::SocketAddress;
51
52static const char kIceUfrag1[] = "TESTICEUFRAG0001";
53static const char kIcePwd1[] = "TESTICEPWD00000000000001";
54
55static const char kIceUfrag2[] = "TESTICEUFRAG0002";
56static const char kIcePwd2[] = "TESTICEPWD00000000000002";
57
58class TransportTest : public testing::Test,
59                      public sigslot::has_slots<> {
60 public:
61  TransportTest()
62      : thread_(rtc::Thread::Current()),
63        transport_(new FakeTransport(
64            thread_, thread_, "test content name", NULL)),
65        channel_(NULL),
66        connecting_signalled_(false),
67        completed_(false),
68        failed_(false) {
69    transport_->SignalConnecting.connect(this, &TransportTest::OnConnecting);
70    transport_->SignalCompleted.connect(this, &TransportTest::OnCompleted);
71    transport_->SignalFailed.connect(this, &TransportTest::OnFailed);
72  }
73  ~TransportTest() {
74    transport_->DestroyAllChannels();
75  }
76  bool SetupChannel() {
77    channel_ = CreateChannel(1);
78    return (channel_ != NULL);
79  }
80  FakeTransportChannel* CreateChannel(int component) {
81    return static_cast<FakeTransportChannel*>(
82        transport_->CreateChannel(component));
83  }
84  void DestroyChannel() {
85    transport_->DestroyChannel(1);
86    channel_ = NULL;
87  }
88
89 protected:
90  void OnConnecting(Transport* transport) {
91    connecting_signalled_ = true;
92  }
93  void OnCompleted(Transport* transport) {
94    completed_ = true;
95  }
96  void OnFailed(Transport* transport) {
97    failed_ = true;
98  }
99
100  rtc::Thread* thread_;
101  rtc::scoped_ptr<FakeTransport> transport_;
102  FakeTransportChannel* channel_;
103  bool connecting_signalled_;
104  bool completed_;
105  bool failed_;
106};
107
108class FakeCandidateTranslator : public cricket::CandidateTranslator {
109 public:
110  void AddMapping(int component, const std::string& channel_name) {
111    name_to_component[channel_name] = component;
112    component_to_name[component] = channel_name;
113  }
114
115  bool GetChannelNameFromComponent(
116      int component, std::string* channel_name) const {
117    if (component_to_name.find(component) == component_to_name.end()) {
118      return false;
119    }
120    *channel_name = component_to_name.find(component)->second;
121    return true;
122  }
123  bool GetComponentFromChannelName(
124      const std::string& channel_name, int* component) const {
125    if (name_to_component.find(channel_name) == name_to_component.end()) {
126      return false;
127    }
128    *component = name_to_component.find(channel_name)->second;
129    return true;
130  }
131
132  std::map<std::string, int> name_to_component;
133  std::map<int, std::string> component_to_name;
134};
135
136// Test that calling ConnectChannels triggers an OnConnecting signal.
137TEST_F(TransportTest, TestConnectChannelsDoesSignal) {
138  EXPECT_TRUE(SetupChannel());
139  transport_->ConnectChannels();
140  EXPECT_FALSE(connecting_signalled_);
141
142  EXPECT_TRUE_WAIT(connecting_signalled_, 100);
143}
144
145// Test that DestroyAllChannels kills any pending OnConnecting signals.
146TEST_F(TransportTest, TestDestroyAllClearsPosts) {
147  EXPECT_TRUE(transport_->CreateChannel(1) != NULL);
148
149  transport_->ConnectChannels();
150  transport_->DestroyAllChannels();
151
152  thread_->ProcessMessages(0);
153  EXPECT_FALSE(connecting_signalled_);
154}
155
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.
159TEST_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,
165                                                       cricket::CA_OFFER,
166                                                       NULL));
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());
173
174  cricket::TransportDescription remote_desc(
175      cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
176  ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
177                                                        cricket::CA_ANSWER,
178                                                        NULL));
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());
188}
189
190// Verifies that IceCredentialsChanged returns true when either ufrag or pwd
191// changed, and false in other cases.
192TEST_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"));
197}
198
199// This test verifies that the callee's ICE role changes from controlled to
200// controlling when the callee triggers an ICE restart.
201TEST_F(TransportTest, TestIceControlledToControllingOnIceRestart) {
202  EXPECT_TRUE(SetupChannel());
203  transport_->SetIceRole(cricket::ICEROLE_CONTROLLED);
204
205  cricket::TransportDescription desc(
206      cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
207  ASSERT_TRUE(transport_->SetRemoteTransportDescription(desc,
208                                                        cricket::CA_OFFER,
209                                                        NULL));
210  ASSERT_TRUE(transport_->SetLocalTransportDescription(desc,
211                                                       cricket::CA_ANSWER,
212                                                       NULL));
213  EXPECT_EQ(cricket::ICEROLE_CONTROLLED, transport_->ice_role());
214
215  cricket::TransportDescription new_local_desc(
216      cricket::NS_JINGLE_ICE_UDP, kIceUfrag2, kIcePwd2);
217  ASSERT_TRUE(transport_->SetLocalTransportDescription(new_local_desc,
218                                                       cricket::CA_OFFER,
219                                                       NULL));
220  EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
221  EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
222}
223
224// This test verifies that the caller's ICE role changes from controlling to
225// controlled when the callee triggers an ICE restart.
226TEST_F(TransportTest, TestIceControllingToControlledOnIceRestart) {
227  EXPECT_TRUE(SetupChannel());
228  transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
229
230  cricket::TransportDescription desc(
231      cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
232  ASSERT_TRUE(transport_->SetLocalTransportDescription(desc,
233                                                       cricket::CA_OFFER,
234                                                       NULL));
235  ASSERT_TRUE(transport_->SetRemoteTransportDescription(desc,
236                                                        cricket::CA_ANSWER,
237                                                        NULL));
238  EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
239
240  cricket::TransportDescription new_local_desc(
241      cricket::NS_JINGLE_ICE_UDP, kIceUfrag2, kIcePwd2);
242  ASSERT_TRUE(transport_->SetLocalTransportDescription(new_local_desc,
243                                                       cricket::CA_ANSWER,
244                                                       NULL));
245  EXPECT_EQ(cricket::ICEROLE_CONTROLLED, transport_->ice_role());
246  EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel_->GetIceRole());
247}
248
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.
251TEST_F(TransportTest, TestIceControllingOnIceRestartIfRemoteIsIceLite) {
252  EXPECT_TRUE(SetupChannel());
253  transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
254
255  cricket::TransportDescription desc(
256      cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
257  ASSERT_TRUE(transport_->SetLocalTransportDescription(desc,
258                                                       cricket::CA_OFFER,
259                                                       NULL));
260
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,
266                                                        cricket::CA_ANSWER,
267                                                        NULL));
268
269  EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
270
271  cricket::TransportDescription new_local_desc(
272      cricket::NS_JINGLE_ICE_UDP, kIceUfrag2, kIcePwd2);
273  ASSERT_TRUE(transport_->SetLocalTransportDescription(new_local_desc,
274                                                       cricket::CA_ANSWER,
275                                                       NULL));
276  EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
277  EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
278}
279
280// This test verifies that the Completed and Failed states can be reached.
281TEST_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,
286                                                       cricket::CA_OFFER,
287                                                       NULL));
288  EXPECT_TRUE(SetupChannel());
289
290  cricket::TransportDescription remote_desc(
291      cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
292  ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
293                                                        cricket::CA_ANSWER,
294                                                        NULL));
295
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_);
303
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);
308  completed_ = false;
309
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_);
315}
316
317// Tests channel role is reversed after receiving ice-lite from remote.
318TEST_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,
325                                                        cricket::CA_OFFER,
326                                                        NULL));
327  cricket::TransportDescription local_desc(
328      cricket::NS_JINGLE_ICE_UDP, kIceUfrag1, kIcePwd1);
329  ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
330                                                       cricket::CA_ANSWER,
331                                                       NULL));
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());
336}
337
338// Tests ice-lite in remote answer.
339TEST_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,
344                                                       cricket::CA_OFFER,
345                                                       NULL));
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,
356                                                        cricket::CA_ANSWER,
357                                                        NULL));
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());
362}
363
364// Tests that we can properly serialize/deserialize candidates.
365TEST_F(TransportTest, TestP2PTransportWriteAndParseCandidate) {
366  Candidate test_candidate(
367      "", 1, "udp",
368      rtc::SocketAddress("2001:db8:fefe::1", 9999),
369      738197504, "abcdef", "ghijkl", "foo", "testnet", 50, "");
370  Candidate test_candidate2(
371      "", 2, "tcp",
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;
384
385  FakeCandidateTranslator translator;
386  translator.AddMapping(1, "test");
387  translator.AddMapping(2, "test2");
388  translator.AddMapping(3, "test3");
389
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));
403
404  EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
405                                          &parsed_candidate, &parse_error));
406  EXPECT_TRUE(test_candidate.IsEquivalent(parsed_candidate));
407
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));
420
421  EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
422                                          &parsed_candidate, &parse_error));
423  EXPECT_TRUE(test_candidate2.IsEquivalent(parsed_candidate));
424
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));
438
439  EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
440                                          &parsed_candidate, &parse_error));
441  EXPECT_TRUE(test_candidate3.IsEquivalent(parsed_candidate));
442}
443
444TEST_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);
455}
456