1 /*
2 * Copyright 2016 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 "p2p/base/tcp_port.h"
12
13 #include <list>
14 #include <memory>
15 #include <vector>
16
17 #include "p2p/base/basic_packet_socket_factory.h"
18 #include "p2p/base/p2p_constants.h"
19 #include "p2p/base/transport_description.h"
20 #include "rtc_base/gunit.h"
21 #include "rtc_base/helpers.h"
22 #include "rtc_base/ip_address.h"
23 #include "rtc_base/third_party/sigslot/sigslot.h"
24 #include "rtc_base/thread.h"
25 #include "rtc_base/time_utils.h"
26 #include "rtc_base/virtual_socket_server.h"
27 #include "test/gtest.h"
28 #include "test/scoped_key_value_config.h"
29
30 using cricket::Connection;
31 using cricket::ICE_PWD_LENGTH;
32 using cricket::ICE_UFRAG_LENGTH;
33 using cricket::Port;
34 using cricket::TCPPort;
35 using rtc::SocketAddress;
36
37 static int kTimeout = 1000;
38 static const SocketAddress kLocalAddr("11.11.11.11", 0);
39 static const SocketAddress kLocalIPv6Addr("2401:fa00:4:1000:be30:5bff:fee5:c3",
40 0);
41 static const SocketAddress kAlternateLocalAddr("1.2.3.4", 0);
42 static const SocketAddress kRemoteAddr("22.22.22.22", 0);
43 static const SocketAddress kRemoteIPv6Addr("2401:fa00:4:1000:be30:5bff:fee5:c4",
44 0);
45
46 constexpr uint64_t kTiebreakerDefault = 44444;
47
48 class ConnectionObserver : public sigslot::has_slots<> {
49 public:
ConnectionObserver(Connection * conn)50 explicit ConnectionObserver(Connection* conn) : conn_(conn) {
51 conn->SignalDestroyed.connect(this, &ConnectionObserver::OnDestroyed);
52 }
53
~ConnectionObserver()54 ~ConnectionObserver() {
55 if (!connection_destroyed_) {
56 RTC_DCHECK(conn_);
57 conn_->SignalDestroyed.disconnect(this);
58 }
59 }
60
connection_destroyed()61 bool connection_destroyed() { return connection_destroyed_; }
62
63 private:
OnDestroyed(Connection *)64 void OnDestroyed(Connection*) { connection_destroyed_ = true; }
65
66 Connection* const conn_;
67 bool connection_destroyed_ = false;
68 };
69
70 class TCPPortTest : public ::testing::Test, public sigslot::has_slots<> {
71 public:
TCPPortTest()72 TCPPortTest()
73 : ss_(new rtc::VirtualSocketServer()),
74 main_(ss_.get()),
75 socket_factory_(ss_.get()),
76 username_(rtc::CreateRandomString(ICE_UFRAG_LENGTH)),
77 password_(rtc::CreateRandomString(ICE_PWD_LENGTH)) {}
78
MakeNetwork(const SocketAddress & addr)79 rtc::Network* MakeNetwork(const SocketAddress& addr) {
80 networks_.emplace_back("unittest", "unittest", addr.ipaddr(), 32);
81 networks_.back().AddIP(addr.ipaddr());
82 return &networks_.back();
83 }
84
CreateTCPPort(const SocketAddress & addr)85 std::unique_ptr<TCPPort> CreateTCPPort(const SocketAddress& addr) {
86 auto port = std::unique_ptr<TCPPort>(
87 TCPPort::Create(&main_, &socket_factory_, MakeNetwork(addr), 0, 0,
88 username_, password_, true, &field_trials_));
89 port->SetIceTiebreaker(kTiebreakerDefault);
90 return port;
91 }
92
CreateTCPPort(const rtc::Network * network)93 std::unique_ptr<TCPPort> CreateTCPPort(const rtc::Network* network) {
94 auto port = std::unique_ptr<TCPPort>(
95 TCPPort::Create(&main_, &socket_factory_, network, 0, 0, username_,
96 password_, true, &field_trials_));
97 port->SetIceTiebreaker(kTiebreakerDefault);
98 return port;
99 }
100
101 protected:
102 // When a "create port" helper method is called with an IP, we create a
103 // Network with that IP and add it to this list. Using a list instead of a
104 // vector so that when it grows, pointers aren't invalidated.
105 std::list<rtc::Network> networks_;
106 std::unique_ptr<rtc::VirtualSocketServer> ss_;
107 rtc::AutoSocketServerThread main_;
108 rtc::BasicPacketSocketFactory socket_factory_;
109 std::string username_;
110 std::string password_;
111 webrtc::test::ScopedKeyValueConfig field_trials_;
112 };
113
TEST_F(TCPPortTest,TestTCPPortWithLocalhostAddress)114 TEST_F(TCPPortTest, TestTCPPortWithLocalhostAddress) {
115 SocketAddress local_address("127.0.0.1", 0);
116 // After calling this, when TCPPort attempts to get a socket bound to
117 // kLocalAddr, it will end up using localhost instead.
118 ss_->SetAlternativeLocalAddress(kLocalAddr.ipaddr(), local_address.ipaddr());
119 auto local_port = CreateTCPPort(kLocalAddr);
120 auto remote_port = CreateTCPPort(kRemoteAddr);
121 local_port->PrepareAddress();
122 remote_port->PrepareAddress();
123 Connection* conn = local_port->CreateConnection(remote_port->Candidates()[0],
124 Port::ORIGIN_MESSAGE);
125 EXPECT_TRUE_WAIT(conn->connected(), kTimeout);
126 // Verify that the socket actually used localhost, otherwise this test isn't
127 // doing what it meant to.
128 ASSERT_EQ(local_address.ipaddr(),
129 local_port->Candidates()[0].address().ipaddr());
130 }
131
132 // If the address the socket ends up bound to does not match any address of the
133 // TCPPort's Network, then the socket should be discarded and no candidates
134 // should be signaled. In the context of ICE, where one TCPPort is created for
135 // each Network, when this happens it's likely that the unexpected address is
136 // associated with some other Network, which another TCPPort is already
137 // covering.
TEST_F(TCPPortTest,TCPPortDiscardedIfBoundAddressDoesNotMatchNetwork)138 TEST_F(TCPPortTest, TCPPortDiscardedIfBoundAddressDoesNotMatchNetwork) {
139 // Sockets bound to kLocalAddr will actually end up with kAlternateLocalAddr.
140 ss_->SetAlternativeLocalAddress(kLocalAddr.ipaddr(),
141 kAlternateLocalAddr.ipaddr());
142
143 // Create ports (local_port is the one whose IP will end up reassigned).
144 auto local_port = CreateTCPPort(kLocalAddr);
145 auto remote_port = CreateTCPPort(kRemoteAddr);
146 local_port->PrepareAddress();
147 remote_port->PrepareAddress();
148
149 // Tell port to create a connection; it should be destroyed when it's
150 // realized that it's using an unexpected address.
151 Connection* conn = local_port->CreateConnection(remote_port->Candidates()[0],
152 Port::ORIGIN_MESSAGE);
153 ConnectionObserver observer(conn);
154 EXPECT_TRUE_WAIT(observer.connection_destroyed(), kTimeout);
155 }
156
157 // A caveat for the above logic: if the socket ends up bound to one of the IPs
158 // associated with the Network, just not the "best" one, this is ok.
TEST_F(TCPPortTest,TCPPortNotDiscardedIfNotBoundToBestIP)159 TEST_F(TCPPortTest, TCPPortNotDiscardedIfNotBoundToBestIP) {
160 // Sockets bound to kLocalAddr will actually end up with kAlternateLocalAddr.
161 ss_->SetAlternativeLocalAddress(kLocalAddr.ipaddr(),
162 kAlternateLocalAddr.ipaddr());
163
164 // Set up a network with kLocalAddr1 as the "best" IP, and kAlternateLocalAddr
165 // as an alternate.
166 rtc::Network* network = MakeNetwork(kLocalAddr);
167 network->AddIP(kAlternateLocalAddr.ipaddr());
168 ASSERT_EQ(kLocalAddr.ipaddr(), network->GetBestIP());
169
170 // Create ports (using our special 2-IP Network for local_port).
171 auto local_port = CreateTCPPort(network);
172 auto remote_port = CreateTCPPort(kRemoteAddr);
173 local_port->PrepareAddress();
174 remote_port->PrepareAddress();
175
176 // Expect connection to succeed.
177 Connection* conn = local_port->CreateConnection(remote_port->Candidates()[0],
178 Port::ORIGIN_MESSAGE);
179 EXPECT_TRUE_WAIT(conn->connected(), kTimeout);
180
181 // Verify that the socket actually used the alternate address, otherwise this
182 // test isn't doing what it meant to.
183 ASSERT_EQ(kAlternateLocalAddr.ipaddr(),
184 local_port->Candidates()[0].address().ipaddr());
185 }
186
187 // Regression test for crbug.com/webrtc/8972, caused by buggy comparison
188 // between rtc::IPAddress and rtc::InterfaceAddress.
TEST_F(TCPPortTest,TCPPortNotDiscardedIfBoundToTemporaryIP)189 TEST_F(TCPPortTest, TCPPortNotDiscardedIfBoundToTemporaryIP) {
190 networks_.emplace_back("unittest", "unittest", kLocalIPv6Addr.ipaddr(), 32);
191 networks_.back().AddIP(rtc::InterfaceAddress(
192 kLocalIPv6Addr.ipaddr(), rtc::IPV6_ADDRESS_FLAG_TEMPORARY));
193
194 auto local_port = CreateTCPPort(&networks_.back());
195 auto remote_port = CreateTCPPort(kRemoteIPv6Addr);
196 local_port->PrepareAddress();
197 remote_port->PrepareAddress();
198
199 // Connection should succeed if the port isn't discarded.
200 Connection* conn = local_port->CreateConnection(remote_port->Candidates()[0],
201 Port::ORIGIN_MESSAGE);
202 ASSERT_NE(nullptr, conn);
203 EXPECT_TRUE_WAIT(conn->connected(), kTimeout);
204 }
205
206 class SentPacketCounter : public sigslot::has_slots<> {
207 public:
SentPacketCounter(TCPPort * p)208 explicit SentPacketCounter(TCPPort* p) {
209 p->SignalSentPacket.connect(this, &SentPacketCounter::OnSentPacket);
210 }
211
sent_packets() const212 int sent_packets() const { return sent_packets_; }
213
214 private:
OnSentPacket(const rtc::SentPacket &)215 void OnSentPacket(const rtc::SentPacket&) { ++sent_packets_; }
216
217 int sent_packets_ = 0;
218 };
219
220 // Test that SignalSentPacket is fired when a packet is successfully sent, for
221 // both TCP client and server sockets.
TEST_F(TCPPortTest,SignalSentPacket)222 TEST_F(TCPPortTest, SignalSentPacket) {
223 std::unique_ptr<TCPPort> client(CreateTCPPort(kLocalAddr));
224 std::unique_ptr<TCPPort> server(CreateTCPPort(kRemoteAddr));
225 client->SetIceRole(cricket::ICEROLE_CONTROLLING);
226 server->SetIceRole(cricket::ICEROLE_CONTROLLED);
227 client->PrepareAddress();
228 server->PrepareAddress();
229
230 Connection* client_conn =
231 client->CreateConnection(server->Candidates()[0], Port::ORIGIN_MESSAGE);
232 ASSERT_NE(nullptr, client_conn);
233 ASSERT_TRUE_WAIT(client_conn->connected(), kTimeout);
234
235 // Need to get the port of the actual outgoing socket, not the server socket..
236 cricket::Candidate client_candidate = client->Candidates()[0];
237 client_candidate.set_address(static_cast<cricket::TCPConnection*>(client_conn)
238 ->socket()
239 ->GetLocalAddress());
240 Connection* server_conn =
241 server->CreateConnection(client_candidate, Port::ORIGIN_THIS_PORT);
242 ASSERT_NE(nullptr, server_conn);
243 ASSERT_TRUE_WAIT(server_conn->connected(), kTimeout);
244
245 client_conn->Ping(rtc::TimeMillis());
246 server_conn->Ping(rtc::TimeMillis());
247 ASSERT_TRUE_WAIT(client_conn->writable(), kTimeout);
248 ASSERT_TRUE_WAIT(server_conn->writable(), kTimeout);
249
250 SentPacketCounter client_counter(client.get());
251 SentPacketCounter server_counter(server.get());
252 static const char kData[] = "hello";
253 for (int i = 0; i < 10; ++i) {
254 client_conn->Send(&kData, sizeof(kData), rtc::PacketOptions());
255 server_conn->Send(&kData, sizeof(kData), rtc::PacketOptions());
256 }
257 EXPECT_EQ_WAIT(10, client_counter.sent_packets(), kTimeout);
258 EXPECT_EQ_WAIT(10, server_counter.sent_packets(), kTimeout);
259 }
260