blob: a5d919a678236ab462cdba0ffae062cd8830e200 [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"
Edward Lemurc20978e2017-07-06 19:44:34 +020016#include "webrtc/rtc_base/gunit.h"
17#include "webrtc/rtc_base/helpers.h"
18#include "webrtc/rtc_base/logging.h"
19#include "webrtc/rtc_base/socketadapters.h"
20#include "webrtc/rtc_base/socketaddress.h"
21#include "webrtc/rtc_base/ssladapter.h"
22#include "webrtc/rtc_base/thread.h"
23#include "webrtc/rtc_base/virtualsocketserver.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000024
25using rtc::SocketAddress;
26
27static const SocketAddress kLocalAddress = SocketAddress("192.168.1.2", 0);
28static const SocketAddress kRelayUdpAddr = SocketAddress("99.99.99.1", 5000);
29static const SocketAddress kRelayTcpAddr = SocketAddress("99.99.99.2", 5001);
30static const SocketAddress kRelaySslAddr = SocketAddress("99.99.99.3", 443);
31static const SocketAddress kRelayExtAddr = SocketAddress("99.99.99.3", 5002);
32
33static const int kTimeoutMs = 1000;
34static const int kMaxTimeoutMs = 5000;
35
36// Tests connecting a RelayPort to a fake relay server
37// (cricket::RelayServer) using all currently available protocols. The
38// network layer is faked out by using a VirtualSocketServer for
39// creating sockets. The test will monitor the current state of the
40// RelayPort and created sockets by listening for signals such as,
41// SignalConnectFailure, SignalConnectTimeout, SignalSocketClosed and
42// SignalReadPacket.
43class RelayPortTest : public testing::Test,
44 public sigslot::has_slots<> {
45 public:
46 RelayPortTest()
deadbeef98e186c2017-05-16 18:00:06 -070047 : virtual_socket_server_(new rtc::VirtualSocketServer()),
nisse7eaa4ea2017-05-08 05:25:41 -070048 main_(virtual_socket_server_.get()),
deadbeef5c3c1042017-08-04 15:01:57 -070049 network_("unittest", "unittest", kLocalAddress.ipaddr(), 32),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000050 socket_factory_(rtc::Thread::Current()),
51 username_(rtc::CreateRandomString(16)),
52 password_(rtc::CreateRandomString(16)),
deadbeef98e186c2017-05-16 18:00:06 -070053 relay_port_(cricket::RelayPort::Create(&main_,
54 &socket_factory_,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000055 &network_,
deadbeef98e186c2017-05-16 18:00:06 -070056 0,
57 0,
58 username_,
59 password_)),
deadbeef5c3c1042017-08-04 15:01:57 -070060 relay_server_(new cricket::RelayServer(&main_)) {
61 network_.AddIP(kLocalAddress.ipaddr());
62 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000063
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
kwiberg3ec46792016-04-27 07:22:53 -0700250 std::unique_ptr<rtc::VirtualSocketServer> virtual_socket_server_;
nisse7eaa4ea2017-05-08 05:25:41 -0700251 rtc::AutoSocketServerThread main_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000252 rtc::Network network_;
253 rtc::BasicPacketSocketFactory socket_factory_;
254 std::string username_;
255 std::string password_;
kwiberg3ec46792016-04-27 07:22:53 -0700256 std::unique_ptr<cricket::RelayPort> relay_port_;
257 std::unique_ptr<cricket::RelayServer> relay_server_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000258 std::vector<cricket::ProtocolAddress> failed_connections_;
259 std::vector<cricket::ProtocolAddress> soft_timedout_connections_;
260 PacketMap received_packet_count_;
261};
262
263TEST_F(RelayPortTest, ConnectUdp) {
264 TestConnectUdp();
265}
266
267TEST_F(RelayPortTest, ConnectTcp) {
268 TestConnectTcp();
269}
270
271TEST_F(RelayPortTest, ConnectSslTcp) {
272 TestConnectSslTcp();
273}