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