Home | History | Annotate | Download | only in webrtc
      1 /*
      2  * libjingle
      3  * Copyright 2012 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 <string>
     29 #include <utility>
     30 
     31 #include "talk/app/webrtc/mediastreaminterface.h"
     32 #include "talk/app/webrtc/peerconnectionfactory.h"
     33 #ifdef WEBRTC_ANDROID
     34 #include "talk/app/webrtc/test/androidtestinitializer.h"
     35 #endif
     36 #include "talk/app/webrtc/test/fakedtlsidentitystore.h"
     37 #include "talk/app/webrtc/test/fakevideotrackrenderer.h"
     38 #include "talk/app/webrtc/videosourceinterface.h"
     39 #include "talk/media/base/fakevideocapturer.h"
     40 #include "talk/media/webrtc/webrtccommon.h"
     41 #include "talk/media/webrtc/webrtcvoe.h"
     42 #include "webrtc/base/gunit.h"
     43 #include "webrtc/base/scoped_ptr.h"
     44 #include "webrtc/base/thread.h"
     45 #include "webrtc/p2p/client/fakeportallocator.h"
     46 
     47 using webrtc::DataChannelInterface;
     48 using webrtc::DtlsIdentityStoreInterface;
     49 using webrtc::FakeVideoTrackRenderer;
     50 using webrtc::MediaStreamInterface;
     51 using webrtc::PeerConnectionFactoryInterface;
     52 using webrtc::PeerConnectionInterface;
     53 using webrtc::PeerConnectionObserver;
     54 using webrtc::VideoSourceInterface;
     55 using webrtc::VideoTrackInterface;
     56 
     57 namespace {
     58 
     59 static const char kStunIceServer[] = "stun:stun.l.google.com:19302";
     60 static const char kTurnIceServer[] = "turn:test%40hello.com (at) test.com:1234";
     61 static const char kTurnIceServerWithTransport[] =
     62     "turn:test (at) hello.com?transport=tcp";
     63 static const char kSecureTurnIceServer[] =
     64     "turns:test (at) hello.com?transport=tcp";
     65 static const char kSecureTurnIceServerWithoutTransportParam[] =
     66     "turns:test_no_transport (at) hello.com:443";
     67 static const char kSecureTurnIceServerWithoutTransportAndPortParam[] =
     68     "turns:test_no_transport (at) hello.com";
     69 static const char kTurnIceServerWithNoUsernameInUri[] =
     70     "turn:test.com:1234";
     71 static const char kTurnPassword[] = "turnpassword";
     72 static const int kDefaultStunPort = 3478;
     73 static const int kDefaultStunTlsPort = 5349;
     74 static const char kTurnUsername[] = "test";
     75 static const char kStunIceServerWithIPv4Address[] = "stun:1.2.3.4:1234";
     76 static const char kStunIceServerWithIPv4AddressWithoutPort[] = "stun:1.2.3.4";
     77 static const char kStunIceServerWithIPv6Address[] = "stun:[2401:fa00:4::]:1234";
     78 static const char kStunIceServerWithIPv6AddressWithoutPort[] =
     79     "stun:[2401:fa00:4::]";
     80 static const char kTurnIceServerWithIPv6Address[] =
     81     "turn:test@[2401:fa00:4::]:1234";
     82 
     83 class NullPeerConnectionObserver : public PeerConnectionObserver {
     84  public:
     85   virtual void OnMessage(const std::string& msg) {}
     86   virtual void OnSignalingMessage(const std::string& msg) {}
     87   virtual void OnSignalingChange(
     88       PeerConnectionInterface::SignalingState new_state) {}
     89   virtual void OnAddStream(MediaStreamInterface* stream) {}
     90   virtual void OnRemoveStream(MediaStreamInterface* stream) {}
     91   virtual void OnDataChannel(DataChannelInterface* data_channel) {}
     92   virtual void OnRenegotiationNeeded() {}
     93   virtual void OnIceConnectionChange(
     94       PeerConnectionInterface::IceConnectionState new_state) {}
     95   virtual void OnIceGatheringChange(
     96       PeerConnectionInterface::IceGatheringState new_state) {}
     97   virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {}
     98 };
     99 
    100 }  // namespace
    101 
    102 class PeerConnectionFactoryTest : public testing::Test {
    103   void SetUp() {
    104 #ifdef WEBRTC_ANDROID
    105     webrtc::InitializeAndroidObjects();
    106 #endif
    107     factory_ = webrtc::CreatePeerConnectionFactory(rtc::Thread::Current(),
    108                                                    rtc::Thread::Current(),
    109                                                    NULL,
    110                                                    NULL,
    111                                                    NULL);
    112 
    113     ASSERT_TRUE(factory_.get() != NULL);
    114     port_allocator_.reset(
    115         new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr));
    116     raw_port_allocator_ = port_allocator_.get();
    117   }
    118 
    119  protected:
    120   void VerifyStunServers(cricket::ServerAddresses stun_servers) {
    121     EXPECT_EQ(stun_servers, raw_port_allocator_->stun_servers());
    122   }
    123 
    124   void VerifyTurnServers(std::vector<cricket::RelayServerConfig> turn_servers) {
    125     EXPECT_EQ(turn_servers.size(), raw_port_allocator_->turn_servers().size());
    126     for (size_t i = 0; i < turn_servers.size(); ++i) {
    127       ASSERT_EQ(1u, turn_servers[i].ports.size());
    128       EXPECT_EQ(1u, raw_port_allocator_->turn_servers()[i].ports.size());
    129       EXPECT_EQ(
    130           turn_servers[i].ports[0].address.ToString(),
    131           raw_port_allocator_->turn_servers()[i].ports[0].address.ToString());
    132       EXPECT_EQ(turn_servers[i].ports[0].proto,
    133                 raw_port_allocator_->turn_servers()[i].ports[0].proto);
    134       EXPECT_EQ(turn_servers[i].credentials.username,
    135                 raw_port_allocator_->turn_servers()[i].credentials.username);
    136       EXPECT_EQ(turn_servers[i].credentials.password,
    137                 raw_port_allocator_->turn_servers()[i].credentials.password);
    138     }
    139   }
    140 
    141   rtc::scoped_refptr<PeerConnectionFactoryInterface> factory_;
    142   NullPeerConnectionObserver observer_;
    143   rtc::scoped_ptr<cricket::FakePortAllocator> port_allocator_;
    144   // Since the PC owns the port allocator after it's been initialized,
    145   // this should only be used when known to be safe.
    146   cricket::FakePortAllocator* raw_port_allocator_;
    147 };
    148 
    149 // Verify creation of PeerConnection using internal ADM, video factory and
    150 // internal libjingle threads.
    151 TEST(PeerConnectionFactoryTestInternal, CreatePCUsingInternalModules) {
    152 #ifdef WEBRTC_ANDROID
    153   webrtc::InitializeAndroidObjects();
    154 #endif
    155 
    156   rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
    157       webrtc::CreatePeerConnectionFactory());
    158 
    159   NullPeerConnectionObserver observer;
    160   webrtc::PeerConnectionInterface::RTCConfiguration config;
    161 
    162   rtc::scoped_ptr<FakeDtlsIdentityStore> dtls_identity_store(
    163       new FakeDtlsIdentityStore());
    164   rtc::scoped_refptr<PeerConnectionInterface> pc(factory->CreatePeerConnection(
    165       config, nullptr, nullptr, std::move(dtls_identity_store), &observer));
    166 
    167   EXPECT_TRUE(pc.get() != nullptr);
    168 }
    169 
    170 // This test verifies creation of PeerConnection with valid STUN and TURN
    171 // configuration. Also verifies the URL's parsed correctly as expected.
    172 TEST_F(PeerConnectionFactoryTest, CreatePCUsingIceServers) {
    173   PeerConnectionInterface::RTCConfiguration config;
    174   webrtc::PeerConnectionInterface::IceServer ice_server;
    175   ice_server.uri = kStunIceServer;
    176   config.servers.push_back(ice_server);
    177   ice_server.uri = kTurnIceServer;
    178   ice_server.password = kTurnPassword;
    179   config.servers.push_back(ice_server);
    180   ice_server.uri = kTurnIceServerWithTransport;
    181   ice_server.password = kTurnPassword;
    182   config.servers.push_back(ice_server);
    183   rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store(
    184       new FakeDtlsIdentityStore());
    185   rtc::scoped_refptr<PeerConnectionInterface> pc(factory_->CreatePeerConnection(
    186       config, nullptr, std::move(port_allocator_),
    187       std::move(dtls_identity_store), &observer_));
    188   ASSERT_TRUE(pc.get() != NULL);
    189   cricket::ServerAddresses stun_servers;
    190   rtc::SocketAddress stun1("stun.l.google.com", 19302);
    191   stun_servers.insert(stun1);
    192   VerifyStunServers(stun_servers);
    193   std::vector<cricket::RelayServerConfig> turn_servers;
    194   cricket::RelayServerConfig turn1("test.com", 1234, "test (at) hello.com",
    195                                    kTurnPassword, cricket::PROTO_UDP, false);
    196   turn_servers.push_back(turn1);
    197   cricket::RelayServerConfig turn2("hello.com", kDefaultStunPort, "test",
    198                                    kTurnPassword, cricket::PROTO_TCP, false);
    199   turn_servers.push_back(turn2);
    200   VerifyTurnServers(turn_servers);
    201 }
    202 
    203 // This test verifies creation of PeerConnection with valid STUN and TURN
    204 // configuration. Also verifies the list of URL's parsed correctly as expected.
    205 TEST_F(PeerConnectionFactoryTest, CreatePCUsingIceServersUrls) {
    206   PeerConnectionInterface::RTCConfiguration config;
    207   webrtc::PeerConnectionInterface::IceServer ice_server;
    208   ice_server.urls.push_back(kStunIceServer);
    209   ice_server.urls.push_back(kTurnIceServer);
    210   ice_server.urls.push_back(kTurnIceServerWithTransport);
    211   ice_server.password = kTurnPassword;
    212   config.servers.push_back(ice_server);
    213   rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store(
    214       new FakeDtlsIdentityStore());
    215   rtc::scoped_refptr<PeerConnectionInterface> pc(factory_->CreatePeerConnection(
    216       config, nullptr, std::move(port_allocator_),
    217       std::move(dtls_identity_store), &observer_));
    218   ASSERT_TRUE(pc.get() != NULL);
    219   cricket::ServerAddresses stun_servers;
    220   rtc::SocketAddress stun1("stun.l.google.com", 19302);
    221   stun_servers.insert(stun1);
    222   VerifyStunServers(stun_servers);
    223   std::vector<cricket::RelayServerConfig> turn_servers;
    224   cricket::RelayServerConfig turn1("test.com", 1234, "test (at) hello.com",
    225                                    kTurnPassword, cricket::PROTO_UDP, false);
    226   turn_servers.push_back(turn1);
    227   cricket::RelayServerConfig turn2("hello.com", kDefaultStunPort, "test",
    228                                    kTurnPassword, cricket::PROTO_TCP, false);
    229   turn_servers.push_back(turn2);
    230   VerifyTurnServers(turn_servers);
    231 }
    232 
    233 TEST_F(PeerConnectionFactoryTest, CreatePCUsingNoUsernameInUri) {
    234   PeerConnectionInterface::RTCConfiguration config;
    235   webrtc::PeerConnectionInterface::IceServer ice_server;
    236   ice_server.uri = kStunIceServer;
    237   config.servers.push_back(ice_server);
    238   ice_server.uri = kTurnIceServerWithNoUsernameInUri;
    239   ice_server.username = kTurnUsername;
    240   ice_server.password = kTurnPassword;
    241   config.servers.push_back(ice_server);
    242   rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store(
    243       new FakeDtlsIdentityStore());
    244   rtc::scoped_refptr<PeerConnectionInterface> pc(factory_->CreatePeerConnection(
    245       config, nullptr, std::move(port_allocator_),
    246       std::move(dtls_identity_store), &observer_));
    247   ASSERT_TRUE(pc.get() != NULL);
    248   std::vector<cricket::RelayServerConfig> turn_servers;
    249   cricket::RelayServerConfig turn("test.com", 1234, kTurnUsername,
    250                                   kTurnPassword, cricket::PROTO_UDP, false);
    251   turn_servers.push_back(turn);
    252   VerifyTurnServers(turn_servers);
    253 }
    254 
    255 // This test verifies the PeerConnection created properly with TURN url which
    256 // has transport parameter in it.
    257 TEST_F(PeerConnectionFactoryTest, CreatePCUsingTurnUrlWithTransportParam) {
    258   PeerConnectionInterface::RTCConfiguration config;
    259   webrtc::PeerConnectionInterface::IceServer ice_server;
    260   ice_server.uri = kTurnIceServerWithTransport;
    261   ice_server.password = kTurnPassword;
    262   config.servers.push_back(ice_server);
    263   rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store(
    264       new FakeDtlsIdentityStore());
    265   rtc::scoped_refptr<PeerConnectionInterface> pc(factory_->CreatePeerConnection(
    266       config, nullptr, std::move(port_allocator_),
    267       std::move(dtls_identity_store), &observer_));
    268   ASSERT_TRUE(pc.get() != NULL);
    269   std::vector<cricket::RelayServerConfig> turn_servers;
    270   cricket::RelayServerConfig turn("hello.com", kDefaultStunPort, "test",
    271                                   kTurnPassword, cricket::PROTO_TCP, false);
    272   turn_servers.push_back(turn);
    273   VerifyTurnServers(turn_servers);
    274 }
    275 
    276 TEST_F(PeerConnectionFactoryTest, CreatePCUsingSecureTurnUrl) {
    277   PeerConnectionInterface::RTCConfiguration config;
    278   webrtc::PeerConnectionInterface::IceServer ice_server;
    279   ice_server.uri = kSecureTurnIceServer;
    280   ice_server.password = kTurnPassword;
    281   config.servers.push_back(ice_server);
    282   ice_server.uri = kSecureTurnIceServerWithoutTransportParam;
    283   ice_server.password = kTurnPassword;
    284   config.servers.push_back(ice_server);
    285   ice_server.uri = kSecureTurnIceServerWithoutTransportAndPortParam;
    286   ice_server.password = kTurnPassword;
    287   config.servers.push_back(ice_server);
    288   rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store(
    289       new FakeDtlsIdentityStore());
    290   rtc::scoped_refptr<PeerConnectionInterface> pc(factory_->CreatePeerConnection(
    291       config, nullptr, std::move(port_allocator_),
    292       std::move(dtls_identity_store), &observer_));
    293   ASSERT_TRUE(pc.get() != NULL);
    294   std::vector<cricket::RelayServerConfig> turn_servers;
    295   cricket::RelayServerConfig turn1("hello.com", kDefaultStunTlsPort, "test",
    296                                    kTurnPassword, cricket::PROTO_TCP, true);
    297   turn_servers.push_back(turn1);
    298   // TURNS with transport param should be default to tcp.
    299   cricket::RelayServerConfig turn2("hello.com", 443, "test_no_transport",
    300                                    kTurnPassword, cricket::PROTO_TCP, true);
    301   turn_servers.push_back(turn2);
    302   cricket::RelayServerConfig turn3("hello.com", kDefaultStunTlsPort,
    303                                    "test_no_transport", kTurnPassword,
    304                                    cricket::PROTO_TCP, true);
    305   turn_servers.push_back(turn3);
    306   VerifyTurnServers(turn_servers);
    307 }
    308 
    309 TEST_F(PeerConnectionFactoryTest, CreatePCUsingIPLiteralAddress) {
    310   PeerConnectionInterface::RTCConfiguration config;
    311   webrtc::PeerConnectionInterface::IceServer ice_server;
    312   ice_server.uri = kStunIceServerWithIPv4Address;
    313   config.servers.push_back(ice_server);
    314   ice_server.uri = kStunIceServerWithIPv4AddressWithoutPort;
    315   config.servers.push_back(ice_server);
    316   ice_server.uri = kStunIceServerWithIPv6Address;
    317   config.servers.push_back(ice_server);
    318   ice_server.uri = kStunIceServerWithIPv6AddressWithoutPort;
    319   config.servers.push_back(ice_server);
    320   ice_server.uri = kTurnIceServerWithIPv6Address;
    321   ice_server.password = kTurnPassword;
    322   config.servers.push_back(ice_server);
    323   rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store(
    324       new FakeDtlsIdentityStore());
    325   rtc::scoped_refptr<PeerConnectionInterface> pc(factory_->CreatePeerConnection(
    326       config, nullptr, std::move(port_allocator_),
    327       std::move(dtls_identity_store), &observer_));
    328   ASSERT_TRUE(pc.get() != NULL);
    329   cricket::ServerAddresses stun_servers;
    330   rtc::SocketAddress stun1("1.2.3.4", 1234);
    331   stun_servers.insert(stun1);
    332   rtc::SocketAddress stun2("1.2.3.4", 3478);
    333   stun_servers.insert(stun2);  // Default port
    334   rtc::SocketAddress stun3("2401:fa00:4::", 1234);
    335   stun_servers.insert(stun3);
    336   rtc::SocketAddress stun4("2401:fa00:4::", 3478);
    337   stun_servers.insert(stun4);  // Default port
    338   VerifyStunServers(stun_servers);
    339 
    340   std::vector<cricket::RelayServerConfig> turn_servers;
    341   cricket::RelayServerConfig turn1("2401:fa00:4::", 1234, "test", kTurnPassword,
    342                                    cricket::PROTO_UDP, false);
    343   turn_servers.push_back(turn1);
    344   VerifyTurnServers(turn_servers);
    345 }
    346 
    347 // This test verifies the captured stream is rendered locally using a
    348 // local video track.
    349 TEST_F(PeerConnectionFactoryTest, LocalRendering) {
    350   cricket::FakeVideoCapturer* capturer = new cricket::FakeVideoCapturer();
    351   // The source take ownership of |capturer|.
    352   rtc::scoped_refptr<VideoSourceInterface> source(
    353       factory_->CreateVideoSource(capturer, NULL));
    354   ASSERT_TRUE(source.get() != NULL);
    355   rtc::scoped_refptr<VideoTrackInterface> track(
    356       factory_->CreateVideoTrack("testlabel", source));
    357   ASSERT_TRUE(track.get() != NULL);
    358   FakeVideoTrackRenderer local_renderer(track);
    359 
    360   EXPECT_EQ(0, local_renderer.num_rendered_frames());
    361   EXPECT_TRUE(capturer->CaptureFrame());
    362   EXPECT_EQ(1, local_renderer.num_rendered_frames());
    363 
    364   track->set_enabled(false);
    365   EXPECT_TRUE(capturer->CaptureFrame());
    366   EXPECT_EQ(1, local_renderer.num_rendered_frames());
    367 
    368   track->set_enabled(true);
    369   EXPECT_TRUE(capturer->CaptureFrame());
    370   EXPECT_EQ(2, local_renderer.num_rendered_frames());
    371 }
    372 
    373