Home | History | Annotate | Download | only in base
      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/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 
     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 talk_base::SocketAddress;
     51 
     52 static const char kIceUfrag1[] = "TESTICEUFRAG0001";
     53 static const char kIcePwd1[] = "TESTICEPWD00000000000001";
     54 
     55 class 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),
     63         connecting_signalled_(false) {
     64     transport_->SignalConnecting.connect(this, &TransportTest::OnConnecting);
     65   }
     66   ~TransportTest() {
     67     transport_->DestroyAllChannels();
     68   }
     69   bool SetupChannel() {
     70     channel_ = CreateChannel(1);
     71     return (channel_ != NULL);
     72   }
     73   FakeTransportChannel* CreateChannel(int component) {
     74     return static_cast<FakeTransportChannel*>(
     75         transport_->CreateChannel(component));
     76   }
     77   void DestroyChannel() {
     78     transport_->DestroyChannel(1);
     79     channel_ = NULL;
     80   }
     81 
     82  protected:
     83   void OnConnecting(Transport* transport) {
     84     connecting_signalled_ = true;
     85   }
     86 
     87   talk_base::Thread* thread_;
     88   talk_base::scoped_ptr<FakeTransport> transport_;
     89   FakeTransportChannel* channel_;
     90   bool connecting_signalled_;
     91 };
     92 
     93 class FakeCandidateTranslator : public cricket::CandidateTranslator {
     94  public:
     95   void AddMapping(int component, const std::string& channel_name) {
     96     name_to_component[channel_name] = component;
     97     component_to_name[component] = channel_name;
     98   }
     99 
    100   bool GetChannelNameFromComponent(
    101       int component, std::string* channel_name) const {
    102     if (component_to_name.find(component) == component_to_name.end()) {
    103       return false;
    104     }
    105     *channel_name = component_to_name.find(component)->second;
    106     return true;
    107   }
    108   bool GetComponentFromChannelName(
    109       const std::string& channel_name, int* component) const {
    110     if (name_to_component.find(channel_name) == name_to_component.end()) {
    111       return false;
    112     }
    113     *component = name_to_component.find(channel_name)->second;
    114     return true;
    115   }
    116 
    117   std::map<std::string, int> name_to_component;
    118   std::map<int, std::string> component_to_name;
    119 };
    120 
    121 // Test that calling ConnectChannels triggers an OnConnecting signal.
    122 TEST_F(TransportTest, TestConnectChannelsDoesSignal) {
    123   EXPECT_TRUE(SetupChannel());
    124   transport_->ConnectChannels();
    125   EXPECT_FALSE(connecting_signalled_);
    126 
    127   EXPECT_TRUE_WAIT(connecting_signalled_, 100);
    128 }
    129 
    130 // Test that DestroyAllChannels kills any pending OnConnecting signals.
    131 TEST_F(TransportTest, TestDestroyAllClearsPosts) {
    132   EXPECT_TRUE(transport_->CreateChannel(1) != NULL);
    133 
    134   transport_->ConnectChannels();
    135   transport_->DestroyAllChannels();
    136 
    137   thread_->ProcessMessages(0);
    138   EXPECT_FALSE(connecting_signalled_);
    139 }
    140 
    141 // This test verifies channels are created with proper ICE
    142 // role, tiebreaker and remote ice mode and credentials after offer and
    143 // answer negotiations.
    144 TEST_F(TransportTest, TestChannelIceParameters) {
    145   transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
    146   transport_->SetIceTiebreaker(99U);
    147   cricket::TransportDescription local_desc(
    148       cricket::NS_JINGLE_ICE_UDP, std::vector<std::string>(),
    149       kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, NULL, cricket::Candidates());
    150   ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
    151                                                        cricket::CA_OFFER));
    152   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
    153   EXPECT_TRUE(SetupChannel());
    154   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
    155   EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
    156   EXPECT_EQ(kIceUfrag1, channel_->ice_ufrag());
    157   EXPECT_EQ(kIcePwd1, channel_->ice_pwd());
    158 
    159   cricket::TransportDescription remote_desc(
    160       cricket::NS_JINGLE_ICE_UDP, std::vector<std::string>(),
    161       kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, NULL, cricket::Candidates());
    162   ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
    163                                                         cricket::CA_ANSWER));
    164   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
    165   EXPECT_EQ(99U, channel_->IceTiebreaker());
    166   EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
    167   // Changing the transport role from CONTROLLING to CONTROLLED.
    168   transport_->SetIceRole(cricket::ICEROLE_CONTROLLED);
    169   EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel_->GetIceRole());
    170   EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
    171   EXPECT_EQ(kIceUfrag1, channel_->remote_ice_ufrag());
    172   EXPECT_EQ(kIcePwd1, channel_->remote_ice_pwd());
    173 }
    174 
    175 // Tests channel role is reversed after receiving ice-lite from remote.
    176 TEST_F(TransportTest, TestSetRemoteIceLiteInOffer) {
    177   transport_->SetIceRole(cricket::ICEROLE_CONTROLLED);
    178   cricket::TransportDescription remote_desc(
    179       cricket::NS_JINGLE_ICE_UDP, std::vector<std::string>(),
    180       kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE, NULL, cricket::Candidates());
    181   ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
    182                                                         cricket::CA_OFFER));
    183   cricket::TransportDescription local_desc(
    184       cricket::NS_JINGLE_ICE_UDP, std::vector<std::string>(),
    185       kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, NULL, cricket::Candidates());
    186   ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
    187                                                        cricket::CA_ANSWER));
    188   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
    189   EXPECT_TRUE(SetupChannel());
    190   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
    191   EXPECT_EQ(cricket::ICEMODE_LITE, channel_->remote_ice_mode());
    192 }
    193 
    194 // Tests ice-lite in remote answer.
    195 TEST_F(TransportTest, TestSetRemoteIceLiteInAnswer) {
    196   transport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
    197   cricket::TransportDescription local_desc(
    198       cricket::NS_JINGLE_ICE_UDP, std::vector<std::string>(),
    199       kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, NULL, cricket::Candidates());
    200   ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
    201                                                        cricket::CA_OFFER));
    202   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_->ice_role());
    203   EXPECT_TRUE(SetupChannel());
    204   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
    205   // Channels will be created in ICEFULL_MODE.
    206   EXPECT_EQ(cricket::ICEMODE_FULL, channel_->remote_ice_mode());
    207   cricket::TransportDescription remote_desc(
    208       cricket::NS_JINGLE_ICE_UDP, std::vector<std::string>(),
    209       kIceUfrag1, kIcePwd1, cricket::ICEMODE_LITE, NULL, cricket::Candidates());
    210   ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
    211                                                         cricket::CA_ANSWER));
    212   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel_->GetIceRole());
    213   // After receiving remote description with ICEMODE_LITE, channel should
    214   // have mode set to ICEMODE_LITE.
    215   EXPECT_EQ(cricket::ICEMODE_LITE, channel_->remote_ice_mode());
    216 }
    217 
    218 // Tests that we can properly serialize/deserialize candidates.
    219 TEST_F(TransportTest, TestP2PTransportWriteAndParseCandidate) {
    220   Candidate test_candidate(
    221       "", 1, "udp",
    222       talk_base::SocketAddress("2001:db8:fefe::1", 9999),
    223       738197504, "abcdef", "ghijkl", "foo", "testnet", 50, "");
    224   Candidate test_candidate2(
    225       "", 2, "tcp",
    226       talk_base::SocketAddress("192.168.7.1", 9999),
    227       1107296256, "mnopqr", "stuvwx", "bar", "testnet2", 100, "");
    228   talk_base::SocketAddress host_address("www.google.com", 24601);
    229   host_address.SetResolvedIP(talk_base::IPAddress(0x0A000001));
    230   Candidate test_candidate3(
    231       "", 3, "spdy", host_address, 1476395008, "yzabcd",
    232       "efghij", "baz", "testnet3", 150, "");
    233   WriteError write_error;
    234   ParseError parse_error;
    235   talk_base::scoped_ptr<buzz::XmlElement> elem;
    236   cricket::Candidate parsed_candidate;
    237   cricket::P2PTransportParser parser;
    238 
    239   FakeCandidateTranslator translator;
    240   translator.AddMapping(1, "test");
    241   translator.AddMapping(2, "test2");
    242   translator.AddMapping(3, "test3");
    243 
    244   EXPECT_TRUE(parser.WriteGingleCandidate(test_candidate, &translator,
    245                                           elem.accept(), &write_error));
    246   EXPECT_EQ("", write_error.text);
    247   EXPECT_EQ("test", elem->Attr(buzz::QN_NAME));
    248   EXPECT_EQ("udp", elem->Attr(cricket::QN_PROTOCOL));
    249   EXPECT_EQ("2001:db8:fefe::1", elem->Attr(cricket::QN_ADDRESS));
    250   EXPECT_EQ("9999", elem->Attr(cricket::QN_PORT));
    251   EXPECT_EQ("0.34", elem->Attr(cricket::QN_PREFERENCE));
    252   EXPECT_EQ("abcdef", elem->Attr(cricket::QN_USERNAME));
    253   EXPECT_EQ("ghijkl", elem->Attr(cricket::QN_PASSWORD));
    254   EXPECT_EQ("foo", elem->Attr(cricket::QN_TYPE));
    255   EXPECT_EQ("testnet", elem->Attr(cricket::QN_NETWORK));
    256   EXPECT_EQ("50", elem->Attr(cricket::QN_GENERATION));
    257 
    258   EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
    259                                           &parsed_candidate, &parse_error));
    260   EXPECT_TRUE(test_candidate.IsEquivalent(parsed_candidate));
    261 
    262   EXPECT_TRUE(parser.WriteGingleCandidate(test_candidate2, &translator,
    263                                           elem.accept(), &write_error));
    264   EXPECT_EQ("test2", elem->Attr(buzz::QN_NAME));
    265   EXPECT_EQ("tcp", elem->Attr(cricket::QN_PROTOCOL));
    266   EXPECT_EQ("192.168.7.1", elem->Attr(cricket::QN_ADDRESS));
    267   EXPECT_EQ("9999", elem->Attr(cricket::QN_PORT));
    268   EXPECT_EQ("0.51", elem->Attr(cricket::QN_PREFERENCE));
    269   EXPECT_EQ("mnopqr", elem->Attr(cricket::QN_USERNAME));
    270   EXPECT_EQ("stuvwx", elem->Attr(cricket::QN_PASSWORD));
    271   EXPECT_EQ("bar", elem->Attr(cricket::QN_TYPE));
    272   EXPECT_EQ("testnet2", elem->Attr(cricket::QN_NETWORK));
    273   EXPECT_EQ("100", elem->Attr(cricket::QN_GENERATION));
    274 
    275   EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
    276                                           &parsed_candidate, &parse_error));
    277   EXPECT_TRUE(test_candidate2.IsEquivalent(parsed_candidate));
    278 
    279   // Check that an ip is preferred over hostname.
    280   EXPECT_TRUE(parser.WriteGingleCandidate(test_candidate3, &translator,
    281                                           elem.accept(), &write_error));
    282   EXPECT_EQ("test3", elem->Attr(cricket::QN_NAME));
    283   EXPECT_EQ("spdy", elem->Attr(cricket::QN_PROTOCOL));
    284   EXPECT_EQ("10.0.0.1", elem->Attr(cricket::QN_ADDRESS));
    285   EXPECT_EQ("24601", elem->Attr(cricket::QN_PORT));
    286   EXPECT_EQ("0.69", elem->Attr(cricket::QN_PREFERENCE));
    287   EXPECT_EQ("yzabcd", elem->Attr(cricket::QN_USERNAME));
    288   EXPECT_EQ("efghij", elem->Attr(cricket::QN_PASSWORD));
    289   EXPECT_EQ("baz", elem->Attr(cricket::QN_TYPE));
    290   EXPECT_EQ("testnet3", elem->Attr(cricket::QN_NETWORK));
    291   EXPECT_EQ("150", elem->Attr(cricket::QN_GENERATION));
    292 
    293   EXPECT_TRUE(parser.ParseGingleCandidate(elem.get(), &translator,
    294                                           &parsed_candidate, &parse_error));
    295   EXPECT_TRUE(test_candidate3.IsEquivalent(parsed_candidate));
    296 }
    297 
    298 TEST_F(TransportTest, TestGetStats) {
    299   EXPECT_TRUE(SetupChannel());
    300   cricket::TransportStats stats;
    301   EXPECT_TRUE(transport_->GetStats(&stats));
    302   // Note that this tests the behavior of a FakeTransportChannel.
    303   ASSERT_EQ(1U, stats.channel_stats.size());
    304   EXPECT_EQ(1, stats.channel_stats[0].component);
    305   transport_->ConnectChannels();
    306   EXPECT_TRUE(transport_->GetStats(&stats));
    307   ASSERT_EQ(1U, stats.channel_stats.size());
    308   EXPECT_EQ(1, stats.channel_stats[0].component);
    309 }
    310