3
* Copyright 2009 Google Inc.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
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.
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.
28
#include "talk/base/fakenetwork.h"
29
#include "talk/base/firewallsocketserver.h"
30
#include "talk/base/gunit.h"
31
#include "talk/base/helpers.h"
32
#include "talk/base/logging.h"
33
#include "talk/base/network.h"
34
#include "talk/base/physicalsocketserver.h"
35
#include "talk/base/socketaddress.h"
36
#include "talk/base/thread.h"
37
#include "talk/base/virtualsocketserver.h"
38
#include "talk/p2p/base/p2ptransportchannel.h"
39
#include "talk/p2p/base/portallocatorsessionproxy.h"
40
#include "talk/p2p/base/testrelayserver.h"
41
#include "talk/p2p/base/teststunserver.h"
42
#include "talk/p2p/client/basicportallocator.h"
43
#include "talk/p2p/client/httpportallocator.h"
45
using talk_base::SocketAddress;
46
using talk_base::Thread;
48
static const SocketAddress kClientAddr("11.11.11.11", 0);
49
static const SocketAddress kRemoteClientAddr("22.22.22.22", 0);
50
static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT);
51
static const SocketAddress kRelayUdpIntAddr("99.99.99.2", 5000);
52
static const SocketAddress kRelayUdpExtAddr("99.99.99.3", 5001);
53
static const SocketAddress kRelayTcpIntAddr("99.99.99.2", 5002);
54
static const SocketAddress kRelayTcpExtAddr("99.99.99.3", 5003);
55
static const SocketAddress kRelaySslTcpIntAddr("99.99.99.2", 5004);
56
static const SocketAddress kRelaySslTcpExtAddr("99.99.99.3", 5005);
58
// Minimum and maximum port for port range tests.
59
static const int kMinPort = 10000;
60
static const int kMaxPort = 10099;
62
// Helper for dumping candidates
63
std::ostream& operator<<(std::ostream& os, const cricket::Candidate& c) {
68
class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> {
70
static void SetUpTestCase() {
71
// Ensure the RNG is inited.
72
talk_base::InitRandom(NULL, 0);
75
: pss_(new talk_base::PhysicalSocketServer),
76
vss_(new talk_base::VirtualSocketServer(pss_.get())),
77
fss_(new talk_base::FirewallSocketServer(vss_.get())),
78
ss_scope_(fss_.get()),
79
stun_server_(Thread::Current(), kStunAddr),
80
relay_server_(Thread::Current(), kRelayUdpIntAddr, kRelayUdpExtAddr,
81
kRelayTcpIntAddr, kRelayTcpExtAddr,
82
kRelaySslTcpIntAddr, kRelaySslTcpExtAddr),
83
allocator_(new cricket::BasicPortAllocator(
84
&network_manager_, kStunAddr,
85
kRelayUdpIntAddr, kRelayTcpIntAddr, kRelaySslTcpIntAddr)),
86
candidate_allocation_done_(false) {
89
void AddInterface(const SocketAddress& addr) {
90
network_manager_.AddInterface(addr);
92
bool SetPortRange(int min_port, int max_port) {
93
return allocator_->SetPortRange(min_port, max_port);
96
bool CreateSession(const std::string& name, const std::string& type) {
97
session_.reset(CreateSession("session", name, type));
103
cricket::PortAllocatorSession* CreateSession(
104
const std::string& sid, const std::string& name,
105
const std::string& type) {
106
cricket::PortAllocatorSession* session =
107
allocator_->CreateSession(sid, name, type);
108
session->SignalPortReady.connect(this,
109
&PortAllocatorTest::OnPortReady);
110
session->SignalCandidatesReady.connect(this,
111
&PortAllocatorTest::OnCandidatesReady);
112
session->SignalCandidatesAllocationDone.connect(this,
113
&PortAllocatorTest::OnCandidatesAllocationDone);
117
static bool CheckCandidate(const cricket::Candidate& c,
118
const std::string& name, const std::string& type,
119
const std::string& proto,
120
const SocketAddress& addr) {
121
return (c.name() == name && c.type() == type &&
122
c.protocol() == proto && c.address().ipaddr() == addr.ipaddr() &&
123
(addr.port() == 0 || (c.address().port() == addr.port())));
125
static bool CheckPort(const talk_base::SocketAddress& addr,
126
int min_port, int max_port) {
127
return (addr.port() >= min_port && addr.port() <= max_port);
130
void OnCandidatesAllocationDone(cricket::PortAllocatorSession* allocator) {
131
candidate_allocation_done_ = true;
135
cricket::BasicPortAllocator& allocator() {
136
return reinterpret_cast<cricket::BasicPortAllocator&> (*(allocator_.get()));
139
void OnPortReady(cricket::PortAllocatorSession* ses, cricket::Port* port) {
140
LOG(LS_INFO) << "OnPortReady: " << port->ToString();
141
ports_.push_back(port);
143
void OnCandidatesReady(cricket::PortAllocatorSession* ses,
144
const std::vector<cricket::Candidate>& candidates) {
145
for (size_t i = 0; i < candidates.size(); ++i) {
146
LOG(LS_INFO) << "OnCandidatesReady: " << candidates[i].ToString();
147
candidates_.push_back(candidates[i]);
151
talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
152
talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
153
talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
154
talk_base::SocketServerScope ss_scope_;
155
cricket::TestStunServer stun_server_;
156
cricket::TestRelayServer relay_server_;
157
talk_base::FakeNetworkManager network_manager_;
158
talk_base::scoped_ptr<cricket::PortAllocator> allocator_;
159
talk_base::scoped_ptr<cricket::PortAllocatorSession> session_;
160
std::vector<cricket::Port*> ports_;
161
std::vector<cricket::Candidate> candidates_;
162
bool candidate_allocation_done_;
165
// Tests that we can init the port allocator and create a session.
166
TEST_F(PortAllocatorTest, TestBasic) {
167
EXPECT_EQ(&network_manager_, allocator().network_manager());
168
EXPECT_EQ(kStunAddr, allocator().stun_address());
169
EXPECT_EQ(kRelayUdpIntAddr, allocator().relay_address_udp());
170
EXPECT_EQ(kRelayTcpIntAddr, allocator().relay_address_tcp());
171
EXPECT_EQ(kRelaySslTcpIntAddr, allocator().relay_address_ssl());
172
EXPECT_TRUE(CreateSession("rtp", "unittest"));
175
// Tests that we can get the local and STUN addresses successfully.
176
TEST_F(PortAllocatorTest, TestGetInitialPorts) {
177
AddInterface(kClientAddr);
178
EXPECT_TRUE(CreateSession("rtp", "unittest"));
179
session_->GetInitialPorts();
180
ASSERT_EQ_WAIT(2U, candidates_.size(), 1000);
181
EXPECT_PRED5(CheckCandidate, candidates_[0],
182
"rtp", "local", "udp", kClientAddr);
183
EXPECT_PRED5(CheckCandidate, candidates_[1],
184
"rtp", "stun", "udp", kClientAddr);
185
EXPECT_EQ(2U, ports_.size());
188
// Tests that we can get all the desired addresses successfully.
189
TEST_F(PortAllocatorTest, TestGetAllPorts) {
190
AddInterface(kClientAddr);
191
EXPECT_TRUE(CreateSession("rtp", "unittest"));
192
session_->GetInitialPorts();
193
session_->StartGetAllPorts();
194
ASSERT_EQ_WAIT(2U, candidates_.size(), 1000);
195
EXPECT_EQ(2U, ports_.size());
196
ASSERT_EQ_WAIT(4U, candidates_.size(), 2000);
197
EXPECT_EQ(3U, ports_.size());
198
EXPECT_PRED5(CheckCandidate, candidates_[2],
199
"rtp", "relay", "udp", kRelayUdpIntAddr);
200
EXPECT_PRED5(CheckCandidate, candidates_[3],
201
"rtp", "relay", "udp", kRelayUdpExtAddr);
202
ASSERT_EQ_WAIT(6U, candidates_.size(), 1500);
203
EXPECT_PRED5(CheckCandidate, candidates_[4],
204
"rtp", "relay", "tcp", kRelayTcpIntAddr);
205
EXPECT_PRED5(CheckCandidate, candidates_[5],
206
"rtp", "local", "tcp", kClientAddr);
207
EXPECT_EQ(4U, ports_.size());
208
ASSERT_EQ_WAIT(7U, candidates_.size(), 2000);
209
EXPECT_PRED5(CheckCandidate, candidates_[6],
210
"rtp", "relay", "ssltcp", kRelaySslTcpIntAddr);
211
EXPECT_EQ(4U, ports_.size());
212
EXPECT_TRUE(candidate_allocation_done_);
215
// Test that we restrict client ports appropriately when a port range is set.
216
// We check the candidates for udp/stun/tcp ports, and the from address
218
TEST_F(PortAllocatorTest, TestGetAllPortsPortRange) {
219
AddInterface(kClientAddr);
220
// Check that an invalid port range fails.
221
EXPECT_FALSE(SetPortRange(kMaxPort, kMinPort));
222
// Check that a null port range succeeds.
223
EXPECT_TRUE(SetPortRange(0, 0));
224
// Check that a valid port range succeeds.
225
EXPECT_TRUE(SetPortRange(kMinPort, kMaxPort));
226
EXPECT_TRUE(CreateSession("rtp", "unittest"));
227
session_->GetInitialPorts();
228
session_->StartGetAllPorts();
229
ASSERT_EQ_WAIT(2U, candidates_.size(), 1000);
230
EXPECT_EQ(2U, ports_.size());
231
// Check the port number for the UDP port object.
232
EXPECT_PRED3(CheckPort, candidates_[0].address(), kMinPort, kMaxPort);
233
// Check the port number for the STUN port object.
234
EXPECT_PRED3(CheckPort, candidates_[1].address(), kMinPort, kMaxPort);
235
ASSERT_EQ_WAIT(4U, candidates_.size(), 2000);
236
EXPECT_EQ(3U, ports_.size());
237
// Check the port number used to connect to the relay server.
238
EXPECT_PRED3(CheckPort, relay_server_.GetConnection(0).source(),
240
ASSERT_EQ_WAIT(6U, candidates_.size(), 1500);
241
EXPECT_EQ(4U, ports_.size());
242
ASSERT_EQ_WAIT(7U, candidates_.size(), 2000);
243
EXPECT_EQ(4U, ports_.size());
244
EXPECT_TRUE(candidate_allocation_done_);
245
// Check the port number for the TCP port object.
246
EXPECT_PRED3(CheckPort, candidates_[5].address(), kMinPort, kMaxPort);
249
// Test that we don't crash or malfunction if we have no network adapters.
250
// TODO: Find a way to exit early here.
251
TEST_F(PortAllocatorTest, TestGetAllPortsNoAdapters) {
252
EXPECT_TRUE(CreateSession("rtp", "unittest"));
253
session_->GetInitialPorts();
254
session_->StartGetAllPorts();
255
WAIT(candidates_.size() > 0, 2000);
256
EXPECT_TRUE(candidate_allocation_done_);
259
// Test that we don't crash or malfunction if we can't create UDP sockets.
260
TEST_F(PortAllocatorTest, TestGetAllPortsNoUdpSockets) {
261
AddInterface(kClientAddr);
262
fss_->set_udp_sockets_enabled(false);
263
EXPECT_TRUE(CreateSession("rtp", "unittest"));
264
session_->GetInitialPorts();
265
session_->StartGetAllPorts();
266
ASSERT_EQ_WAIT(2U, candidates_.size(), 2000);
267
EXPECT_PRED5(CheckCandidate, candidates_[0],
268
"rtp", "relay", "udp", kRelayUdpIntAddr);
269
EXPECT_PRED5(CheckCandidate, candidates_[1],
270
"rtp", "relay", "udp", kRelayUdpExtAddr);
271
ASSERT_EQ_WAIT(4U, candidates_.size(), 2000);
272
EXPECT_PRED5(CheckCandidate, candidates_[2],
273
"rtp", "relay", "tcp", kRelayTcpIntAddr);
274
EXPECT_PRED5(CheckCandidate, candidates_[3],
275
"rtp", "local", "tcp", kClientAddr);
276
EXPECT_EQ(2U, ports_.size());
277
ASSERT_EQ_WAIT(5U, candidates_.size(), 2000);
278
EXPECT_PRED5(CheckCandidate, candidates_[4],
279
"rtp", "relay", "ssltcp", kRelaySslTcpIntAddr);
280
EXPECT_EQ(2U, ports_.size());
281
EXPECT_TRUE(candidate_allocation_done_);
284
// Test that we don't crash or malfunction if we can't create UDP sockets or
285
// listen on TCP sockets. We still give out a local TCP address, since
286
// apparently this is needed for the remote side to accept our connection.
287
TEST_F(PortAllocatorTest, TestGetAllPortsNoUdpSocketsNoTcpListen) {
288
AddInterface(kClientAddr);
289
fss_->set_udp_sockets_enabled(false);
290
fss_->set_tcp_listen_enabled(false);
291
EXPECT_TRUE(CreateSession("rtp", "unittest"));
292
session_->GetInitialPorts();
293
session_->StartGetAllPorts();
294
ASSERT_EQ_WAIT(2U, candidates_.size(), 3000);
295
EXPECT_PRED5(CheckCandidate, candidates_[0],
296
"rtp", "relay", "udp", kRelayUdpIntAddr);
297
EXPECT_PRED5(CheckCandidate, candidates_[1],
298
"rtp", "relay", "udp", kRelayUdpExtAddr);
299
ASSERT_EQ_WAIT(4U, candidates_.size(), 2000);
300
EXPECT_PRED5(CheckCandidate, candidates_[2],
301
"rtp", "relay", "tcp", kRelayTcpIntAddr);
302
EXPECT_PRED5(CheckCandidate, candidates_[3],
303
"rtp", "local", "tcp", kClientAddr);
304
EXPECT_EQ(2U, ports_.size());
305
ASSERT_EQ_WAIT(5U, candidates_.size(), 2000);
306
EXPECT_PRED5(CheckCandidate, candidates_[4],
307
"rtp", "relay", "ssltcp", kRelaySslTcpIntAddr);
308
EXPECT_EQ(2U, ports_.size());
309
EXPECT_TRUE(candidate_allocation_done_);
312
// Test that we don't crash or malfunction if we can't create any sockets.
313
// TODO: Find a way to exit early here.
314
TEST_F(PortAllocatorTest, TestGetAllPortsNoSockets) {
315
AddInterface(kClientAddr);
316
fss_->set_tcp_sockets_enabled(false);
317
fss_->set_udp_sockets_enabled(false);
318
EXPECT_TRUE(CreateSession("rtp", "unittest"));
319
session_->GetInitialPorts();
320
session_->StartGetAllPorts();
321
WAIT(candidates_.size() > 0, 2000);
322
// TODO - Check candidate_allocation_done signal.
323
// In case of Relay, ports creation will succeed but sockets will fail.
324
// There is no error reporting from RelayEntry to handle this failure.
327
// Testing STUN timeout.
328
TEST_F(PortAllocatorTest, TestGetAllPortsNoUdpAllowed) {
329
fss_->AddRule(false, talk_base::FP_UDP, talk_base::FD_ANY, kClientAddr);
330
AddInterface(kClientAddr);
331
EXPECT_TRUE(CreateSession("rtp", "unittest"));
332
session_->GetInitialPorts();
333
session_->StartGetAllPorts();
334
EXPECT_EQ_WAIT(1U, candidates_.size(), 1000);
335
EXPECT_PRED5(CheckCandidate, candidates_[0],
336
"rtp", "local", "udp", kClientAddr);
337
EXPECT_EQ_WAIT(2U, candidates_.size(), 3000);
338
EXPECT_PRED5(CheckCandidate, candidates_[1],
339
"rtp", "local", "tcp", kClientAddr);
340
EXPECT_EQ(2U, ports_.size());
341
EXPECT_EQ_WAIT(6U, candidates_.size(), 3000);
342
EXPECT_PRED5(CheckCandidate, candidates_[2],
343
"rtp", "relay", "udp", kRelayUdpIntAddr);
344
EXPECT_PRED5(CheckCandidate, candidates_[3],
345
"rtp", "relay", "tcp", kRelayTcpIntAddr);
346
EXPECT_PRED5(CheckCandidate, candidates_[4],
347
"rtp", "relay", "ssltcp", kRelaySslTcpIntAddr);
348
EXPECT_PRED5(CheckCandidate, candidates_[5],
349
"rtp", "relay", "udp", kRelayUdpExtAddr);
350
EXPECT_EQ(3U, ports_.size());
351
// Stun Timeout is 9sec.
352
EXPECT_TRUE_WAIT(candidate_allocation_done_, 9000);
355
// Test to verify ICE restart process.
356
TEST_F(PortAllocatorTest, TestGetAllPortsRestarts) {
357
AddInterface(kClientAddr);
358
EXPECT_TRUE(CreateSession("rtp", "unittest"));
359
session_->GetInitialPorts();
360
session_->StartGetAllPorts();
361
EXPECT_EQ_WAIT(2U, candidates_.size(), 1000);
362
EXPECT_EQ(2U, ports_.size());
363
EXPECT_EQ_WAIT(4U, candidates_.size(), 2000);
364
EXPECT_EQ(3U, ports_.size());
365
EXPECT_EQ_WAIT(6U, candidates_.size(), 1500);
366
EXPECT_EQ(4U, ports_.size());
367
EXPECT_EQ_WAIT(7U, candidates_.size(), 2000);
368
EXPECT_EQ(4U, ports_.size());
369
EXPECT_TRUE(candidate_allocation_done_);
370
// TODO - Extend this to verify ICE restart.
373
TEST_F(PortAllocatorTest, TestBasicMuxFeatures) {
374
allocator().set_flags(cricket::PORTALLOCATOR_ENABLE_BUNDLE);
375
// Session ID - session1.
376
talk_base::scoped_ptr<cricket::PortAllocatorSession> session1(
377
CreateSession("session1", "rtp", "audio"));
378
talk_base::scoped_ptr<cricket::PortAllocatorSession> session2(
379
CreateSession("session1", "rtcp", "audio"));
380
// We know that PortAllocator is creating a proxy session when bundle flag
381
// is enabled, it's safe to type cast session objects.
382
cricket::PortAllocatorSessionProxy* proxy1 =
383
static_cast<cricket::PortAllocatorSessionProxy*>(session1.get());
384
ASSERT_TRUE(proxy1 != NULL);
385
cricket::PortAllocatorSessionProxy* proxy2 =
386
static_cast<cricket::PortAllocatorSessionProxy*>(session2.get());
387
ASSERT_TRUE(proxy2 != NULL);
388
EXPECT_EQ(proxy1->impl(), proxy2->impl());
389
AddInterface(kClientAddr);
390
session1->GetInitialPorts();
391
session2->GetInitialPorts();
392
// Each session should receive two proxy ports of local and stun.
393
ASSERT_EQ_WAIT(4U, ports_.size(), 1000);
394
EXPECT_EQ(4U, candidates_.size());
395
EXPECT_PRED5(CheckCandidate, candidates_[0],
396
"rtp", "local", "udp", kClientAddr);
397
EXPECT_PRED5(CheckCandidate, candidates_[1],
398
"rtcp", "local", "udp", kClientAddr);
399
EXPECT_PRED5(CheckCandidate, candidates_[2],
400
"rtp", "stun", "udp", kClientAddr);
402
EXPECT_PRED5(CheckCandidate, candidates_[3],
403
"rtcp", "stun", "udp", kClientAddr);
404
talk_base::scoped_ptr<cricket::PortAllocatorSession> session3(
405
CreateSession("session1", "video_rtp", "video"));
406
// ListenToEvents(session3.get());
407
session3->GetInitialPorts();
408
// Since real ports and sessions are already allocated and signal sent, no
409
// new ports will be allocated when new proxy session created.
410
talk_base::Thread::Current()->ProcessMessages(1000);
411
EXPECT_NE(6U, ports_.size());
412
// Creating a PortAllocatorSession with different session name from above.
413
// In this case proxy PAS should have a different PAS.
414
// Session ID - session2.
415
talk_base::scoped_ptr<cricket::PortAllocatorSession> session4(
416
CreateSession("session2", "video_rtp", "video"));
417
cricket::PortAllocatorSessionProxy* proxy4 =
418
static_cast<cricket::PortAllocatorSessionProxy*>(session4.get());
419
EXPECT_NE(proxy4->impl(), proxy1->impl());
422
// Test that the httpportallocator correctly maintains its lists of stun and
423
// relay servers, by never allowing an empty list.
424
TEST(HttpPortAllocatorTest, TestHttpPortAllocatorHostLists) {
425
talk_base::FakeNetworkManager network_manager;
426
cricket::HttpPortAllocator alloc(&network_manager, "unit test agent");
427
EXPECT_EQ(1U, alloc.relay_hosts().size());
428
EXPECT_EQ(1U, alloc.stun_hosts().size());
430
std::vector<std::string> relay_servers;
431
std::vector<talk_base::SocketAddress> stun_servers;
433
alloc.SetRelayHosts(relay_servers);
434
alloc.SetStunHosts(stun_servers);
435
EXPECT_EQ(1U, alloc.relay_hosts().size());
436
EXPECT_EQ(1U, alloc.stun_hosts().size());
438
relay_servers.push_back("1.unittest.corp.google.com");
439
relay_servers.push_back("2.unittest.corp.google.com");
440
stun_servers.push_back(
441
talk_base::SocketAddress("1.unittest.corp.google.com", 0));
442
stun_servers.push_back(
443
talk_base::SocketAddress("2.unittest.corp.google.com", 0));
444
alloc.SetRelayHosts(relay_servers);
445
alloc.SetStunHosts(stun_servers);
446
EXPECT_EQ(2U, alloc.relay_hosts().size());
447
EXPECT_EQ(2U, alloc.stun_hosts().size());