• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@test.com:1234";
61 static const char kTurnIceServerWithTransport[] =
62     "turn:test@hello.com?transport=tcp";
63 static const char kSecureTurnIceServer[] =
64     "turns:test@hello.com?transport=tcp";
65 static const char kSecureTurnIceServerWithoutTransportParam[] =
66     "turns:test_no_transport@hello.com:443";
67 static const char kSecureTurnIceServerWithoutTransportAndPortParam[] =
68     "turns:test_no_transport@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:
OnMessage(const std::string & msg)85   virtual void OnMessage(const std::string& msg) {}
OnSignalingMessage(const std::string & msg)86   virtual void OnSignalingMessage(const std::string& msg) {}
OnSignalingChange(PeerConnectionInterface::SignalingState new_state)87   virtual void OnSignalingChange(
88       PeerConnectionInterface::SignalingState new_state) {}
OnAddStream(MediaStreamInterface * stream)89   virtual void OnAddStream(MediaStreamInterface* stream) {}
OnRemoveStream(MediaStreamInterface * stream)90   virtual void OnRemoveStream(MediaStreamInterface* stream) {}
OnDataChannel(DataChannelInterface * data_channel)91   virtual void OnDataChannel(DataChannelInterface* data_channel) {}
OnRenegotiationNeeded()92   virtual void OnRenegotiationNeeded() {}
OnIceConnectionChange(PeerConnectionInterface::IceConnectionState new_state)93   virtual void OnIceConnectionChange(
94       PeerConnectionInterface::IceConnectionState new_state) {}
OnIceGatheringChange(PeerConnectionInterface::IceGatheringState new_state)95   virtual void OnIceGatheringChange(
96       PeerConnectionInterface::IceGatheringState new_state) {}
OnIceCandidate(const webrtc::IceCandidateInterface * candidate)97   virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {}
98 };
99 
100 }  // namespace
101 
102 class PeerConnectionFactoryTest : public testing::Test {
SetUp()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:
VerifyStunServers(cricket::ServerAddresses stun_servers)120   void VerifyStunServers(cricket::ServerAddresses stun_servers) {
121     EXPECT_EQ(stun_servers, raw_port_allocator_->stun_servers());
122   }
123 
VerifyTurnServers(std::vector<cricket::RelayServerConfig> turn_servers)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.
TEST(PeerConnectionFactoryTestInternal,CreatePCUsingInternalModules)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.
TEST_F(PeerConnectionFactoryTest,CreatePCUsingIceServers)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@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.
TEST_F(PeerConnectionFactoryTest,CreatePCUsingIceServersUrls)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@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 
TEST_F(PeerConnectionFactoryTest,CreatePCUsingNoUsernameInUri)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.
TEST_F(PeerConnectionFactoryTest,CreatePCUsingTurnUrlWithTransportParam)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 
TEST_F(PeerConnectionFactoryTest,CreatePCUsingSecureTurnUrl)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 
TEST_F(PeerConnectionFactoryTest,CreatePCUsingIPLiteralAddress)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.
TEST_F(PeerConnectionFactoryTest,LocalRendering)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