blob: 8574af3a74e9f4bcf8f334513cb2b2759e7e3a1a [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
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
kwiberg3ec46792016-04-27 07:22:53 -070011#include <memory>
12
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000013#include "webrtc/p2p/base/basicpacketsocketfactory.h"
14#include "webrtc/p2p/base/relayport.h"
15#include "webrtc/p2p/base/relayserver.h"
16#include "webrtc/base/gunit.h"
17#include "webrtc/base/helpers.h"
18#include "webrtc/base/logging.h"
19#include "webrtc/base/physicalsocketserver.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000020#include "webrtc/base/socketadapters.h"
21#include "webrtc/base/socketaddress.h"
22#include "webrtc/base/ssladapter.h"
23#include "webrtc/base/thread.h"
24#include "webrtc/base/virtualsocketserver.h"
25
26using rtc::SocketAddress;
27
28static const SocketAddress kLocalAddress = SocketAddress("192.168.1.2", 0);
29static const SocketAddress kRelayUdpAddr = SocketAddress("99.99.99.1", 5000);
30static const SocketAddress kRelayTcpAddr = SocketAddress("99.99.99.2", 5001);
31static const SocketAddress kRelaySslAddr = SocketAddress("99.99.99.3", 443);
32static const SocketAddress kRelayExtAddr = SocketAddress("99.99.99.3", 5002);
33
34static const int kTimeoutMs = 1000;
35static const int kMaxTimeoutMs = 5000;
36
37// Tests connecting a RelayPort to a fake relay server
38// (cricket::RelayServer) using all currently available protocols. The
39// network layer is faked out by using a VirtualSocketServer for
40// creating sockets. The test will monitor the current state of the
41// RelayPort and created sockets by listening for signals such as,
42// SignalConnectFailure, SignalConnectTimeout, SignalSocketClosed and
43// SignalReadPacket.
44class RelayPortTest : public testing::Test,
45 public sigslot::has_slots<> {
46 public:
47 RelayPortTest()
48 : main_(rtc::Thread::Current()),
49 physical_socket_server_(new rtc::PhysicalSocketServer),
50 virtual_socket_server_(new rtc::VirtualSocketServer(
51 physical_socket_server_.get())),
52 ss_scope_(virtual_socket_server_.get()),
53 network_("unittest", "unittest", rtc::IPAddress(INADDR_ANY), 32),
54 socket_factory_(rtc::Thread::Current()),
55 username_(rtc::CreateRandomString(16)),
56 password_(rtc::CreateRandomString(16)),
57 relay_port_(cricket::RelayPort::Create(main_, &socket_factory_,
58 &network_,
59 kLocalAddress.ipaddr(),
60 0, 0, username_, password_)),
61 relay_server_(new cricket::RelayServer(main_)) {
62 }
63
64 void OnReadPacket(rtc::AsyncPacketSocket* socket,
65 const char* data, size_t size,
66 const rtc::SocketAddress& remote_addr,
67 const rtc::PacketTime& packet_time) {
68 received_packet_count_[socket]++;
69 }
70
71 void OnConnectFailure(const cricket::ProtocolAddress* addr) {
72 failed_connections_.push_back(*addr);
73 }
74
75 void OnSoftTimeout(const cricket::ProtocolAddress* addr) {
76 soft_timedout_connections_.push_back(*addr);
77 }
78
79 protected:
80 virtual void SetUp() {
81 // The relay server needs an external socket to work properly.
82 rtc::AsyncUDPSocket* ext_socket =
83 CreateAsyncUdpSocket(kRelayExtAddr);
84 relay_server_->AddExternalSocket(ext_socket);
85
86 // Listen for failures.
87 relay_port_->SignalConnectFailure.
88 connect(this, &RelayPortTest::OnConnectFailure);
89
90 // Listen for soft timeouts.
91 relay_port_->SignalSoftTimeout.
92 connect(this, &RelayPortTest::OnSoftTimeout);
93 }
94
95 // Udp has the highest 'goodness' value of the three different
96 // protocols used for connecting to the relay server. As soon as
97 // PrepareAddress is called, the RelayPort will start trying to
98 // connect to the given UDP address. As soon as a response to the
99 // sent STUN allocate request message has been received, the
100 // RelayPort will consider the connection to be complete and will
101 // abort any other connection attempts.
102 void TestConnectUdp() {
103 // Add a UDP socket to the relay server.
104 rtc::AsyncUDPSocket* internal_udp_socket =
105 CreateAsyncUdpSocket(kRelayUdpAddr);
106 rtc::AsyncSocket* server_socket = CreateServerSocket(kRelayTcpAddr);
107
108 relay_server_->AddInternalSocket(internal_udp_socket);
109 relay_server_->AddInternalServerSocket(server_socket, cricket::PROTO_TCP);
110
111 // Now add our relay addresses to the relay port and let it start.
112 relay_port_->AddServerAddress(
113 cricket::ProtocolAddress(kRelayUdpAddr, cricket::PROTO_UDP));
114 relay_port_->AddServerAddress(
115 cricket::ProtocolAddress(kRelayTcpAddr, cricket::PROTO_TCP));
116 relay_port_->PrepareAddress();
117
118 // Should be connected.
119 EXPECT_TRUE_WAIT(relay_port_->IsReady(), kTimeoutMs);
120
121 // Make sure that we are happy with UDP, ie. not continuing with
122 // TCP, SSLTCP, etc.
123 WAIT(relay_server_->HasConnection(kRelayTcpAddr), kTimeoutMs);
124
125 // Should have only one connection.
126 EXPECT_EQ(1, relay_server_->GetConnectionCount());
127
128 // Should be the UDP address.
129 EXPECT_TRUE(relay_server_->HasConnection(kRelayUdpAddr));
130 }
131
132 // TCP has the second best 'goodness' value, and as soon as UDP
133 // connection has failed, the RelayPort will attempt to connect via
134 // TCP. Here we add a fake UDP address together with a real TCP
135 // address to simulate an UDP failure. As soon as UDP has failed the
136 // RelayPort will try the TCP adress and succed.
137 void TestConnectTcp() {
138 // Create a fake UDP address for relay port to simulate a failure.
139 cricket::ProtocolAddress fake_protocol_address =
140 cricket::ProtocolAddress(kRelayUdpAddr, cricket::PROTO_UDP);
141
142 // Create a server socket for the RelayServer.
143 rtc::AsyncSocket* server_socket = CreateServerSocket(kRelayTcpAddr);
144 relay_server_->AddInternalServerSocket(server_socket, cricket::PROTO_TCP);
145
146 // Add server addresses to the relay port and let it start.
147 relay_port_->AddServerAddress(
148 cricket::ProtocolAddress(fake_protocol_address));
149 relay_port_->AddServerAddress(
150 cricket::ProtocolAddress(kRelayTcpAddr, cricket::PROTO_TCP));
151 relay_port_->PrepareAddress();
152
153 EXPECT_FALSE(relay_port_->IsReady());
154
deadbeef4c2db412016-05-26 14:34:09 -0700155 // Should have timed out in 200 + 200 + 400 + 800 + 1600 ms = 3200ms.
156 // Add some margin of error for slow bots.
157 // TODO(deadbeef): Use simulated clock instead of just increasing timeouts
158 // to fix flaky tests.
159 EXPECT_TRUE_WAIT(HasFailed(&fake_protocol_address), 5000);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000160
161 // Wait until relayport is ready.
162 EXPECT_TRUE_WAIT(relay_port_->IsReady(), kMaxTimeoutMs);
163
164 // Should have only one connection.
165 EXPECT_EQ(1, relay_server_->GetConnectionCount());
166
167 // Should be the TCP address.
168 EXPECT_TRUE(relay_server_->HasConnection(kRelayTcpAddr));
169 }
170
171 void TestConnectSslTcp() {
172 // Create a fake TCP address for relay port to simulate a failure.
173 // We skip UDP here since transition from UDP to TCP has been
174 // tested above.
175 cricket::ProtocolAddress fake_protocol_address =
176 cricket::ProtocolAddress(kRelayTcpAddr, cricket::PROTO_TCP);
177
178 // Create a ssl server socket for the RelayServer.
179 rtc::AsyncSocket* ssl_server_socket =
180 CreateServerSocket(kRelaySslAddr);
181 relay_server_->AddInternalServerSocket(ssl_server_socket,
182 cricket::PROTO_SSLTCP);
183
184 // Create a tcp server socket that listens on the fake address so
185 // the relay port can attempt to connect to it.
kwiberg3ec46792016-04-27 07:22:53 -0700186 std::unique_ptr<rtc::AsyncSocket> tcp_server_socket(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000187 CreateServerSocket(kRelayTcpAddr));
188
189 // Add server addresses to the relay port and let it start.
190 relay_port_->AddServerAddress(fake_protocol_address);
191 relay_port_->AddServerAddress(
192 cricket::ProtocolAddress(kRelaySslAddr, cricket::PROTO_SSLTCP));
193 relay_port_->PrepareAddress();
194 EXPECT_FALSE(relay_port_->IsReady());
195
196 // Should have timed out in 3000 ms(relayport.cc, kSoftConnectTimeoutMs).
197 EXPECT_TRUE_WAIT_MARGIN(HasTimedOut(&fake_protocol_address), 3000, 100);
198
199 // Wait until relayport is ready.
200 EXPECT_TRUE_WAIT(relay_port_->IsReady(), kMaxTimeoutMs);
201
202 // Should have only one connection.
203 EXPECT_EQ(1, relay_server_->GetConnectionCount());
204
205 // Should be the SSLTCP address.
206 EXPECT_TRUE(relay_server_->HasConnection(kRelaySslAddr));
207 }
208
209 private:
210 rtc::AsyncUDPSocket* CreateAsyncUdpSocket(const SocketAddress addr) {
211 rtc::AsyncSocket* socket =
212 virtual_socket_server_->CreateAsyncSocket(SOCK_DGRAM);
213 rtc::AsyncUDPSocket* packet_socket =
214 rtc::AsyncUDPSocket::Create(socket, addr);
215 EXPECT_TRUE(packet_socket != NULL);
216 packet_socket->SignalReadPacket.connect(this, &RelayPortTest::OnReadPacket);
217 return packet_socket;
218 }
219
220 rtc::AsyncSocket* CreateServerSocket(const SocketAddress addr) {
221 rtc::AsyncSocket* socket =
222 virtual_socket_server_->CreateAsyncSocket(SOCK_STREAM);
223 EXPECT_GE(socket->Bind(addr), 0);
224 EXPECT_GE(socket->Listen(5), 0);
225 return socket;
226 }
227
228 bool HasFailed(cricket::ProtocolAddress* addr) {
229 for (size_t i = 0; i < failed_connections_.size(); i++) {
230 if (failed_connections_[i].address == addr->address &&
231 failed_connections_[i].proto == addr->proto) {
232 return true;
233 }
234 }
235 return false;
236 }
237
238 bool HasTimedOut(cricket::ProtocolAddress* addr) {
239 for (size_t i = 0; i < soft_timedout_connections_.size(); i++) {
240 if (soft_timedout_connections_[i].address == addr->address &&
241 soft_timedout_connections_[i].proto == addr->proto) {
242 return true;
243 }
244 }
245 return false;
246 }
247
248 typedef std::map<rtc::AsyncPacketSocket*, int> PacketMap;
249
250 rtc::Thread* main_;
kwiberg3ec46792016-04-27 07:22:53 -0700251 std::unique_ptr<rtc::PhysicalSocketServer> physical_socket_server_;
252 std::unique_ptr<rtc::VirtualSocketServer> virtual_socket_server_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000253 rtc::SocketServerScope ss_scope_;
254 rtc::Network network_;
255 rtc::BasicPacketSocketFactory socket_factory_;
256 std::string username_;
257 std::string password_;
kwiberg3ec46792016-04-27 07:22:53 -0700258 std::unique_ptr<cricket::RelayPort> relay_port_;
259 std::unique_ptr<cricket::RelayServer> relay_server_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000260 std::vector<cricket::ProtocolAddress> failed_connections_;
261 std::vector<cricket::ProtocolAddress> soft_timedout_connections_;
262 PacketMap received_packet_count_;
263};
264
265TEST_F(RelayPortTest, ConnectUdp) {
266 TestConnectUdp();
267}
268
269TEST_F(RelayPortTest, ConnectTcp) {
270 TestConnectTcp();
271}
272
273TEST_F(RelayPortTest, ConnectSslTcp) {
274 TestConnectSslTcp();
275}