1/*
2 *  Copyright 2009 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/p2p/base/basicpacketsocketfactory.h"
12#include "webrtc/p2p/base/stunport.h"
13#include "webrtc/p2p/base/teststunserver.h"
14#include "webrtc/base/gunit.h"
15#include "webrtc/base/helpers.h"
16#include "webrtc/base/physicalsocketserver.h"
17#include "webrtc/base/scoped_ptr.h"
18#include "webrtc/base/socketaddress.h"
19#include "webrtc/base/ssladapter.h"
20#include "webrtc/base/virtualsocketserver.h"
21
22using cricket::ServerAddresses;
23using rtc::SocketAddress;
24
25static const SocketAddress kLocalAddr("127.0.0.1", 0);
26static const SocketAddress kStunAddr1("127.0.0.1", 5000);
27static const SocketAddress kStunAddr2("127.0.0.1", 4000);
28static const SocketAddress kBadAddr("0.0.0.1", 5000);
29static const SocketAddress kStunHostnameAddr("localhost", 5000);
30static const SocketAddress kBadHostnameAddr("not-a-real-hostname", 5000);
31static const int kTimeoutMs = 10000;
32// stun prio = 100 << 24 | 30 (IPV4) << 8 | 256 - 0
33static const uint32_t kStunCandidatePriority = 1677729535;
34
35// Tests connecting a StunPort to a fake STUN server (cricket::StunServer)
36// TODO: Use a VirtualSocketServer here. We have to use a
37// PhysicalSocketServer right now since DNS is not part of SocketServer yet.
38class StunPortTest : public testing::Test,
39                     public sigslot::has_slots<> {
40 public:
41  StunPortTest()
42      : pss_(new rtc::PhysicalSocketServer),
43        ss_(new rtc::VirtualSocketServer(pss_.get())),
44        ss_scope_(ss_.get()),
45        network_("unittest", "unittest", rtc::IPAddress(INADDR_ANY), 32),
46        socket_factory_(rtc::Thread::Current()),
47        stun_server_1_(cricket::TestStunServer::Create(
48          rtc::Thread::Current(), kStunAddr1)),
49        stun_server_2_(cricket::TestStunServer::Create(
50          rtc::Thread::Current(), kStunAddr2)),
51        done_(false), error_(false), stun_keepalive_delay_(0) {
52  }
53
54  const cricket::Port* port() const { return stun_port_.get(); }
55  bool done() const { return done_; }
56  bool error() const { return error_; }
57
58  void CreateStunPort(const rtc::SocketAddress& server_addr) {
59    ServerAddresses stun_servers;
60    stun_servers.insert(server_addr);
61    CreateStunPort(stun_servers);
62  }
63
64  void CreateStunPort(const ServerAddresses& stun_servers) {
65    stun_port_.reset(cricket::StunPort::Create(
66        rtc::Thread::Current(), &socket_factory_, &network_,
67        kLocalAddr.ipaddr(), 0, 0, rtc::CreateRandomString(16),
68        rtc::CreateRandomString(22), stun_servers, std::string()));
69    stun_port_->set_stun_keepalive_delay(stun_keepalive_delay_);
70    stun_port_->SignalPortComplete.connect(this,
71        &StunPortTest::OnPortComplete);
72    stun_port_->SignalPortError.connect(this,
73        &StunPortTest::OnPortError);
74  }
75
76  void CreateSharedStunPort(const rtc::SocketAddress& server_addr) {
77    socket_.reset(socket_factory_.CreateUdpSocket(
78        rtc::SocketAddress(kLocalAddr.ipaddr(), 0), 0, 0));
79    ASSERT_TRUE(socket_ != NULL);
80    socket_->SignalReadPacket.connect(this, &StunPortTest::OnReadPacket);
81    stun_port_.reset(cricket::UDPPort::Create(
82        rtc::Thread::Current(), &socket_factory_,
83        &network_, socket_.get(),
84        rtc::CreateRandomString(16), rtc::CreateRandomString(22),
85        std::string(), false));
86    ASSERT_TRUE(stun_port_ != NULL);
87    ServerAddresses stun_servers;
88    stun_servers.insert(server_addr);
89    stun_port_->set_server_addresses(stun_servers);
90    stun_port_->SignalPortComplete.connect(this,
91        &StunPortTest::OnPortComplete);
92    stun_port_->SignalPortError.connect(this,
93        &StunPortTest::OnPortError);
94  }
95
96  void PrepareAddress() {
97    stun_port_->PrepareAddress();
98  }
99
100  void OnReadPacket(rtc::AsyncPacketSocket* socket, const char* data,
101                    size_t size, const rtc::SocketAddress& remote_addr,
102                    const rtc::PacketTime& packet_time) {
103    stun_port_->HandleIncomingPacket(
104        socket, data, size, remote_addr, rtc::PacketTime());
105  }
106
107  void SendData(const char* data, size_t len) {
108    stun_port_->HandleIncomingPacket(
109        socket_.get(), data, len, rtc::SocketAddress("22.22.22.22", 0),
110        rtc::PacketTime());
111  }
112
113 protected:
114  static void SetUpTestCase() {
115    // Ensure the RNG is inited.
116    rtc::InitRandom(NULL, 0);
117
118  }
119
120  void OnPortComplete(cricket::Port* port) {
121    ASSERT_FALSE(done_);
122    done_ = true;
123    error_ = false;
124  }
125  void OnPortError(cricket::Port* port) {
126    done_ = true;
127    error_ = true;
128  }
129  void SetKeepaliveDelay(int delay) {
130    stun_keepalive_delay_ = delay;
131  }
132
133  cricket::TestStunServer* stun_server_1() {
134    return stun_server_1_.get();
135  }
136  cricket::TestStunServer* stun_server_2() {
137    return stun_server_2_.get();
138  }
139
140 private:
141  rtc::scoped_ptr<rtc::PhysicalSocketServer> pss_;
142  rtc::scoped_ptr<rtc::VirtualSocketServer> ss_;
143  rtc::SocketServerScope ss_scope_;
144  rtc::Network network_;
145  rtc::BasicPacketSocketFactory socket_factory_;
146  rtc::scoped_ptr<cricket::UDPPort> stun_port_;
147  rtc::scoped_ptr<cricket::TestStunServer> stun_server_1_;
148  rtc::scoped_ptr<cricket::TestStunServer> stun_server_2_;
149  rtc::scoped_ptr<rtc::AsyncPacketSocket> socket_;
150  bool done_;
151  bool error_;
152  int stun_keepalive_delay_;
153};
154
155// Test that we can create a STUN port
156TEST_F(StunPortTest, TestBasic) {
157  CreateStunPort(kStunAddr1);
158  EXPECT_EQ("stun", port()->Type());
159  EXPECT_EQ(0U, port()->Candidates().size());
160}
161
162// Test that we can get an address from a STUN server.
163TEST_F(StunPortTest, TestPrepareAddress) {
164  CreateStunPort(kStunAddr1);
165  PrepareAddress();
166  EXPECT_TRUE_WAIT(done(), kTimeoutMs);
167  ASSERT_EQ(1U, port()->Candidates().size());
168  EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
169
170  // TODO: Add IPv6 tests here, once either physicalsocketserver supports
171  // IPv6, or this test is changed to use VirtualSocketServer.
172}
173
174// Test that we fail properly if we can't get an address.
175TEST_F(StunPortTest, TestPrepareAddressFail) {
176  CreateStunPort(kBadAddr);
177  PrepareAddress();
178  EXPECT_TRUE_WAIT(done(), kTimeoutMs);
179  EXPECT_TRUE(error());
180  EXPECT_EQ(0U, port()->Candidates().size());
181}
182
183// Test that we can get an address from a STUN server specified by a hostname.
184TEST_F(StunPortTest, TestPrepareAddressHostname) {
185  CreateStunPort(kStunHostnameAddr);
186  PrepareAddress();
187  EXPECT_TRUE_WAIT(done(), kTimeoutMs);
188  ASSERT_EQ(1U, port()->Candidates().size());
189  EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
190  EXPECT_EQ(kStunCandidatePriority, port()->Candidates()[0].priority());
191}
192
193// Test that we handle hostname lookup failures properly.
194TEST_F(StunPortTest, TestPrepareAddressHostnameFail) {
195  CreateStunPort(kBadHostnameAddr);
196  PrepareAddress();
197  EXPECT_TRUE_WAIT(done(), kTimeoutMs);
198  EXPECT_TRUE(error());
199  EXPECT_EQ(0U, port()->Candidates().size());
200}
201
202// This test verifies keepalive response messages don't result in
203// additional candidate generation.
204TEST_F(StunPortTest, TestKeepAliveResponse) {
205  SetKeepaliveDelay(500);  // 500ms of keepalive delay.
206  CreateStunPort(kStunHostnameAddr);
207  PrepareAddress();
208  EXPECT_TRUE_WAIT(done(), kTimeoutMs);
209  ASSERT_EQ(1U, port()->Candidates().size());
210  EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
211  // Waiting for 1 seond, which will allow us to process
212  // response for keepalive binding request. 500 ms is the keepalive delay.
213  rtc::Thread::Current()->ProcessMessages(1000);
214  ASSERT_EQ(1U, port()->Candidates().size());
215}
216
217// Test that a local candidate can be generated using a shared socket.
218TEST_F(StunPortTest, TestSharedSocketPrepareAddress) {
219  CreateSharedStunPort(kStunAddr1);
220  PrepareAddress();
221  EXPECT_TRUE_WAIT(done(), kTimeoutMs);
222  ASSERT_EQ(1U, port()->Candidates().size());
223  EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
224}
225
226// Test that we still a get a local candidate with invalid stun server hostname.
227// Also verifing that UDPPort can receive packets when stun address can't be
228// resolved.
229TEST_F(StunPortTest, TestSharedSocketPrepareAddressInvalidHostname) {
230  CreateSharedStunPort(kBadHostnameAddr);
231  PrepareAddress();
232  EXPECT_TRUE_WAIT(done(), kTimeoutMs);
233  ASSERT_EQ(1U, port()->Candidates().size());
234  EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
235
236  // Send data to port after it's ready. This is to make sure, UDP port can
237  // handle data with unresolved stun server address.
238  std::string data = "some random data, sending to cricket::Port.";
239  SendData(data.c_str(), data.length());
240  // No crash is success.
241}
242
243// Test that the same address is added only once if two STUN servers are in use.
244TEST_F(StunPortTest, TestNoDuplicatedAddressWithTwoStunServers) {
245  ServerAddresses stun_servers;
246  stun_servers.insert(kStunAddr1);
247  stun_servers.insert(kStunAddr2);
248  CreateStunPort(stun_servers);
249  EXPECT_EQ("stun", port()->Type());
250  PrepareAddress();
251  EXPECT_TRUE_WAIT(done(), kTimeoutMs);
252  EXPECT_EQ(1U, port()->Candidates().size());
253  EXPECT_EQ(port()->Candidates()[0].relay_protocol(), "");
254}
255
256// Test that candidates can be allocated for multiple STUN servers, one of which
257// is not reachable.
258TEST_F(StunPortTest, TestMultipleStunServersWithBadServer) {
259  ServerAddresses stun_servers;
260  stun_servers.insert(kStunAddr1);
261  stun_servers.insert(kBadAddr);
262  CreateStunPort(stun_servers);
263  EXPECT_EQ("stun", port()->Type());
264  PrepareAddress();
265  EXPECT_TRUE_WAIT(done(), kTimeoutMs);
266  EXPECT_EQ(1U, port()->Candidates().size());
267}
268
269// Test that two candidates are allocated if the two STUN servers return
270// different mapped addresses.
271TEST_F(StunPortTest, TestTwoCandidatesWithTwoStunServersAcrossNat) {
272  const SocketAddress kStunMappedAddr1("77.77.77.77", 0);
273  const SocketAddress kStunMappedAddr2("88.77.77.77", 0);
274  stun_server_1()->set_fake_stun_addr(kStunMappedAddr1);
275  stun_server_2()->set_fake_stun_addr(kStunMappedAddr2);
276
277  ServerAddresses stun_servers;
278  stun_servers.insert(kStunAddr1);
279  stun_servers.insert(kStunAddr2);
280  CreateStunPort(stun_servers);
281  EXPECT_EQ("stun", port()->Type());
282  PrepareAddress();
283  EXPECT_TRUE_WAIT(done(), kTimeoutMs);
284  EXPECT_EQ(2U, port()->Candidates().size());
285  EXPECT_EQ(port()->Candidates()[0].relay_protocol(), "");
286  EXPECT_EQ(port()->Candidates()[1].relay_protocol(), "");
287}
288