blob: eff20f0092d3607d204c8f748178a3d704154c2c [file] [log] [blame]
[email protected]21160f02013-09-01 23:04:271// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/socket/tcp_socket.h"
6
tbansal7b403bcc2016-04-13 22:33:217#include <stddef.h>
[email protected]c9080d82013-09-15 15:14:168#include <string.h>
[email protected]21160f02013-09-01 23:04:279
danakj655b66c2016-04-16 00:51:3810#include <memory>
[email protected]c9080d82013-09-15 15:14:1611#include <string>
12#include <vector>
13
[email protected]c9080d82013-09-15 15:14:1614#include "base/memory/ref_counted.h"
tbansal7b403bcc2016-04-13 22:33:2115#include "base/time/time.h"
Paul Jensen0f49dec2017-12-12 23:39:5816#include "build/build_config.h"
[email protected]21160f02013-09-01 23:04:2717#include "net/base/address_list.h"
[email protected]c9080d82013-09-15 15:14:1618#include "net/base/io_buffer.h"
[email protected]21160f02013-09-01 23:04:2719#include "net/base/ip_endpoint.h"
20#include "net/base/net_errors.h"
tfarina3d87d7cd2016-01-13 02:26:5921#include "net/base/sockaddr_storage.h"
[email protected]21160f02013-09-01 23:04:2722#include "net/base/test_completion_callback.h"
mikecironef22f9812016-10-04 03:40:1923#include "net/log/net_log_source.h"
tbansalca83c002016-04-28 20:56:2824#include "net/socket/socket_performance_watcher.h"
Paul Jensen0f49dec2017-12-12 23:39:5825#include "net/socket/socket_test_util.h"
[email protected]21160f02013-09-01 23:04:2726#include "net/socket/tcp_client_socket.h"
Paul Jensen0f49dec2017-12-12 23:39:5827#include "net/test/embedded_test_server/embedded_test_server.h"
robpercival214763f2016-07-01 23:27:0128#include "net/test/gtest_util.h"
[email protected]690bbea2017-12-08 09:05:4629#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
robpercival214763f2016-07-01 23:27:0130#include "testing/gmock/include/gmock/gmock.h"
[email protected]21160f02013-09-01 23:04:2731#include "testing/gtest/include/gtest/gtest.h"
32#include "testing/platform_test.h"
33
Sergey Ulanov7cbcbc52017-07-26 18:29:1334using net::test::IsError;
robpercival214763f2016-07-01 23:27:0135using net::test::IsOk;
36
[email protected]21160f02013-09-01 23:04:2737namespace net {
38
39namespace {
tbansal7b403bcc2016-04-13 22:33:2140
Matt Menkee06732012018-04-06 21:41:2441// IOBuffer with the ability to invoke a callback when destroyed. Useful for
42// checking for leaks.
43class IOBufferWithDestructionCallback : public IOBufferWithSize {
44 public:
45 explicit IOBufferWithDestructionCallback(base::OnceClosure on_destroy_closure)
46 : IOBufferWithSize(1024),
47 on_destroy_closure_(std::move(on_destroy_closure)) {
48 DCHECK(on_destroy_closure_);
49 }
50
51 protected:
52 ~IOBufferWithDestructionCallback() override {
53 std::move(on_destroy_closure_).Run();
54 }
55
56 base::OnceClosure on_destroy_closure_;
57};
58
tbansal7b403bcc2016-04-13 22:33:2159class TestSocketPerformanceWatcher : public SocketPerformanceWatcher {
60 public:
61 explicit TestSocketPerformanceWatcher(bool should_notify_updated_rtt)
62 : should_notify_updated_rtt_(should_notify_updated_rtt),
63 connection_changed_count_(0u),
64 rtt_notification_count_(0u) {}
Chris Watkins7a41d3552017-12-01 02:13:2765 ~TestSocketPerformanceWatcher() override = default;
tbansal7b403bcc2016-04-13 22:33:2166
67 bool ShouldNotifyUpdatedRTT() const override {
68 return should_notify_updated_rtt_;
69 }
70
71 void OnUpdatedRTTAvailable(const base::TimeDelta& rtt) override {
72 rtt_notification_count_++;
73 }
74
75 void OnConnectionChanged() override { connection_changed_count_++; }
76
77 size_t rtt_notification_count() const { return rtt_notification_count_; }
78
79 size_t connection_changed_count() const { return connection_changed_count_; }
80
81 private:
82 const bool should_notify_updated_rtt_;
83 size_t connection_changed_count_;
84 size_t rtt_notification_count_;
85
86 DISALLOW_COPY_AND_ASSIGN(TestSocketPerformanceWatcher);
87};
88
[email protected]21160f02013-09-01 23:04:2789const int kListenBacklog = 5;
90
91class TCPSocketTest : public PlatformTest {
92 protected:
Sergey Ulanov7cbcbc52017-07-26 18:29:1393 TCPSocketTest() : socket_(nullptr, nullptr, NetLogSource()) {}
[email protected]21160f02013-09-01 23:04:2794
95 void SetUpListenIPv4() {
robpercival214763f2016-07-01 23:27:0196 ASSERT_THAT(socket_.Open(ADDRESS_FAMILY_IPV4), IsOk());
97 ASSERT_THAT(socket_.Bind(IPEndPoint(IPAddress::IPv4Localhost(), 0)),
98 IsOk());
99 ASSERT_THAT(socket_.Listen(kListenBacklog), IsOk());
100 ASSERT_THAT(socket_.GetLocalAddress(&local_address_), IsOk());
[email protected]21160f02013-09-01 23:04:27101 }
102
103 void SetUpListenIPv6(bool* success) {
104 *success = false;
[email protected]21160f02013-09-01 23:04:27105
[email protected]c9080d82013-09-15 15:14:16106 if (socket_.Open(ADDRESS_FAMILY_IPV6) != OK ||
martijna2e83bd2016-03-18 13:10:45107 socket_.Bind(IPEndPoint(IPAddress::IPv6Localhost(), 0)) != OK ||
[email protected]21160f02013-09-01 23:04:27108 socket_.Listen(kListenBacklog) != OK) {
109 LOG(ERROR) << "Failed to listen on ::1 - probably because IPv6 is "
110 "disabled. Skipping the test";
111 return;
112 }
robpercival214763f2016-07-01 23:27:01113 ASSERT_THAT(socket_.GetLocalAddress(&local_address_), IsOk());
[email protected]21160f02013-09-01 23:04:27114 *success = true;
115 }
116
[email protected]ef2f0022014-04-29 10:24:35117 void TestAcceptAsync() {
118 TestCompletionCallback accept_callback;
danakj655b66c2016-04-16 00:51:38119 std::unique_ptr<TCPSocket> accepted_socket;
[email protected]ef2f0022014-04-29 10:24:35120 IPEndPoint accepted_address;
Sergey Ulanov7cbcbc52017-07-26 18:29:13121 ASSERT_THAT(socket_.Accept(&accepted_socket, &accepted_address,
122 accept_callback.callback()),
123 IsError(ERR_IO_PENDING));
[email protected]ef2f0022014-04-29 10:24:35124
125 TestCompletionCallback connect_callback;
Sergey Ulanov7cbcbc52017-07-26 18:29:13126 TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
mikecironef22f9812016-10-04 03:40:19127 NetLogSource());
Sergey Ulanov7cbcbc52017-07-26 18:29:13128 int connect_result = connecting_socket.Connect(connect_callback.callback());
129 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
[email protected]ef2f0022014-04-29 10:24:35130
robpercival214763f2016-07-01 23:27:01131 EXPECT_THAT(accept_callback.WaitForResult(), IsOk());
[email protected]ef2f0022014-04-29 10:24:35132
133 EXPECT_TRUE(accepted_socket.get());
134
135 // Both sockets should be on the loopback network interface.
136 EXPECT_EQ(accepted_address.address(), local_address_.address());
137 }
138
tbansal7b403bcc2016-04-13 22:33:21139#if defined(TCP_INFO) || defined(OS_LINUX)
140 // Tests that notifications to Socket Performance Watcher (SPW) are delivered
tbansal180587c2017-02-16 15:13:23141 // correctly. |should_notify_updated_rtt| is true if the SPW is interested in
142 // receiving RTT notifications. |num_messages| is the number of messages that
143 // are written/read by the sockets. |expect_connection_changed_count| is the
144 // expected number of connection change notifications received by the SPW.
145 // |expect_rtt_notification_count| is the expected number of RTT
146 // notifications received by the SPW. This test works by writing
147 // |num_messages| to the socket. A different socket (with a SPW attached to
148 // it) reads the messages.
149 void TestSPWNotifications(bool should_notify_updated_rtt,
tbansal7b403bcc2016-04-13 22:33:21150 size_t num_messages,
151 size_t expect_connection_changed_count,
152 size_t expect_rtt_notification_count) {
153 ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
154
tbansal7b403bcc2016-04-13 22:33:21155 TestCompletionCallback connect_callback;
156
danakj655b66c2016-04-16 00:51:38157 std::unique_ptr<TestSocketPerformanceWatcher> watcher(
tbansal7b403bcc2016-04-13 22:33:21158 new TestSocketPerformanceWatcher(should_notify_updated_rtt));
159 TestSocketPerformanceWatcher* watcher_ptr = watcher.get();
160
Sergey Ulanov7cbcbc52017-07-26 18:29:13161 TCPSocket connecting_socket(std::move(watcher), nullptr, NetLogSource());
tbansal7b403bcc2016-04-13 22:33:21162
163 int result = connecting_socket.Open(ADDRESS_FAMILY_IPV4);
robpercival214763f2016-07-01 23:27:01164 ASSERT_THAT(result, IsOk());
Sergey Ulanov7cbcbc52017-07-26 18:29:13165 int connect_result =
166 connecting_socket.Connect(local_address_, connect_callback.callback());
tbansal7b403bcc2016-04-13 22:33:21167
168 TestCompletionCallback accept_callback;
danakj655b66c2016-04-16 00:51:38169 std::unique_ptr<TCPSocket> accepted_socket;
tbansal7b403bcc2016-04-13 22:33:21170 IPEndPoint accepted_address;
171 result = socket_.Accept(&accepted_socket, &accepted_address,
172 accept_callback.callback());
robpercival214763f2016-07-01 23:27:01173 ASSERT_THAT(accept_callback.GetResult(result), IsOk());
tbansal7b403bcc2016-04-13 22:33:21174
175 ASSERT_TRUE(accepted_socket.get());
176
177 // Both sockets should be on the loopback network interface.
178 EXPECT_EQ(accepted_address.address(), local_address_.address());
179
Sergey Ulanov7cbcbc52017-07-26 18:29:13180 ASSERT_THAT(connect_callback.GetResult(connect_result), IsOk());
tbansal7b403bcc2016-04-13 22:33:21181
182 for (size_t i = 0; i < num_messages; ++i) {
tbansal7b403bcc2016-04-13 22:33:21183 // Use a 1 byte message so that the watcher is notified at most once per
184 // message.
185 const std::string message("t");
186
187 scoped_refptr<IOBufferWithSize> write_buffer(
188 new IOBufferWithSize(message.size()));
189 memmove(write_buffer->data(), message.data(), message.size());
190
191 TestCompletionCallback write_callback;
192 int write_result = accepted_socket->Write(
[email protected]690bbea2017-12-08 09:05:46193 write_buffer.get(), write_buffer->size(), write_callback.callback(),
194 TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal7b403bcc2016-04-13 22:33:21195
196 scoped_refptr<IOBufferWithSize> read_buffer(
197 new IOBufferWithSize(message.size()));
198 TestCompletionCallback read_callback;
199 int read_result = connecting_socket.Read(
200 read_buffer.get(), read_buffer->size(), read_callback.callback());
201
202 ASSERT_EQ(1, write_callback.GetResult(write_result));
203 ASSERT_EQ(1, read_callback.GetResult(read_result));
204 }
205 EXPECT_EQ(expect_connection_changed_count,
206 watcher_ptr->connection_changed_count());
207 EXPECT_EQ(expect_rtt_notification_count,
208 watcher_ptr->rtt_notification_count());
209 }
210#endif // defined(TCP_INFO) || defined(OS_LINUX)
211
[email protected]21160f02013-09-01 23:04:27212 AddressList local_address_list() const {
213 return AddressList(local_address_);
214 }
215
216 TCPSocket socket_;
217 IPEndPoint local_address_;
218};
219
220// Test listening and accepting with a socket bound to an IPv4 address.
221TEST_F(TCPSocketTest, Accept) {
222 ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
223
224 TestCompletionCallback connect_callback;
225 // TODO(yzshen): Switch to use TCPSocket when it supports client socket
226 // operations.
Sergey Ulanov7cbcbc52017-07-26 18:29:13227 TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
mikecironef22f9812016-10-04 03:40:19228 NetLogSource());
Sergey Ulanov7cbcbc52017-07-26 18:29:13229 int connect_result = connecting_socket.Connect(connect_callback.callback());
[email protected]21160f02013-09-01 23:04:27230
231 TestCompletionCallback accept_callback;
danakj655b66c2016-04-16 00:51:38232 std::unique_ptr<TCPSocket> accepted_socket;
[email protected]21160f02013-09-01 23:04:27233 IPEndPoint accepted_address;
234 int result = socket_.Accept(&accepted_socket, &accepted_address,
235 accept_callback.callback());
Sergey Ulanov7cbcbc52017-07-26 18:29:13236 ASSERT_THAT(accept_callback.GetResult(result), IsOk());
[email protected]21160f02013-09-01 23:04:27237
238 EXPECT_TRUE(accepted_socket.get());
239
240 // Both sockets should be on the loopback network interface.
241 EXPECT_EQ(accepted_address.address(), local_address_.address());
242
Sergey Ulanov7cbcbc52017-07-26 18:29:13243 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
[email protected]21160f02013-09-01 23:04:27244}
245
246// Test Accept() callback.
247TEST_F(TCPSocketTest, AcceptAsync) {
248 ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
[email protected]ef2f0022014-04-29 10:24:35249 TestAcceptAsync();
[email protected]21160f02013-09-01 23:04:27250}
251
rvera26f0a1392017-05-02 22:25:44252// Test AdoptConnectedSocket()
253TEST_F(TCPSocketTest, AdoptConnectedSocket) {
Sergey Ulanov7cbcbc52017-07-26 18:29:13254 TCPSocket accepting_socket(nullptr, nullptr, NetLogSource());
rvera26f0a1392017-05-02 22:25:44255 ASSERT_THAT(accepting_socket.Open(ADDRESS_FAMILY_IPV4), IsOk());
256 ASSERT_THAT(accepting_socket.Bind(IPEndPoint(IPAddress::IPv4Localhost(), 0)),
257 IsOk());
258 ASSERT_THAT(accepting_socket.GetLocalAddress(&local_address_), IsOk());
259 ASSERT_THAT(accepting_socket.Listen(kListenBacklog), IsOk());
260
261 TestCompletionCallback connect_callback;
262 // TODO(yzshen): Switch to use TCPSocket when it supports client socket
263 // operations.
Sergey Ulanov7cbcbc52017-07-26 18:29:13264 TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
rvera26f0a1392017-05-02 22:25:44265 NetLogSource());
Sergey Ulanov7cbcbc52017-07-26 18:29:13266 int connect_result = connecting_socket.Connect(connect_callback.callback());
rvera26f0a1392017-05-02 22:25:44267
268 TestCompletionCallback accept_callback;
269 std::unique_ptr<TCPSocket> accepted_socket;
270 IPEndPoint accepted_address;
271 int result = accepting_socket.Accept(&accepted_socket, &accepted_address,
272 accept_callback.callback());
Sergey Ulanov7cbcbc52017-07-26 18:29:13273 ASSERT_THAT(accept_callback.GetResult(result), IsOk());
rvera26f0a1392017-05-02 22:25:44274
275 SocketDescriptor accepted_descriptor =
276 accepted_socket->ReleaseSocketDescriptorForTesting();
277
278 ASSERT_THAT(
279 socket_.AdoptConnectedSocket(accepted_descriptor, accepted_address),
280 IsOk());
281
282 // socket_ should now have the local address.
283 IPEndPoint adopted_address;
284 ASSERT_THAT(socket_.GetLocalAddress(&adopted_address), IsOk());
285 EXPECT_EQ(local_address_.address(), adopted_address.address());
286
Sergey Ulanov7cbcbc52017-07-26 18:29:13287 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
rvera26f0a1392017-05-02 22:25:44288}
289
290// Test Accept() for AdoptUnconnectedSocket.
291TEST_F(TCPSocketTest, AcceptForAdoptedUnconnectedSocket) {
292 SocketDescriptor existing_socket =
293 CreatePlatformSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
294 ASSERT_THAT(socket_.AdoptUnconnectedSocket(existing_socket), IsOk());
[email protected]ef2f0022014-04-29 10:24:35295
martijna2e83bd2016-03-18 13:10:45296 IPEndPoint address(IPAddress::IPv4Localhost(), 0);
[email protected]ef2f0022014-04-29 10:24:35297 SockaddrStorage storage;
298 ASSERT_TRUE(address.ToSockAddr(storage.addr, &storage.addr_len));
299 ASSERT_EQ(0, bind(existing_socket, storage.addr, storage.addr_len));
300
robpercival214763f2016-07-01 23:27:01301 ASSERT_THAT(socket_.Listen(kListenBacklog), IsOk());
302 ASSERT_THAT(socket_.GetLocalAddress(&local_address_), IsOk());
[email protected]ef2f0022014-04-29 10:24:35303
304 TestAcceptAsync();
305}
[email protected]ef2f0022014-04-29 10:24:35306
[email protected]21160f02013-09-01 23:04:27307// Accept two connections simultaneously.
308TEST_F(TCPSocketTest, Accept2Connections) {
309 ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
310
311 TestCompletionCallback accept_callback;
danakj655b66c2016-04-16 00:51:38312 std::unique_ptr<TCPSocket> accepted_socket;
[email protected]21160f02013-09-01 23:04:27313 IPEndPoint accepted_address;
314
Sergey Ulanov7cbcbc52017-07-26 18:29:13315 ASSERT_THAT(socket_.Accept(&accepted_socket, &accepted_address,
316 accept_callback.callback()),
317 IsError(ERR_IO_PENDING));
[email protected]21160f02013-09-01 23:04:27318
319 TestCompletionCallback connect_callback;
Sergey Ulanov7cbcbc52017-07-26 18:29:13320 TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
mikecironef22f9812016-10-04 03:40:19321 NetLogSource());
Sergey Ulanov7cbcbc52017-07-26 18:29:13322 int connect_result = connecting_socket.Connect(connect_callback.callback());
[email protected]21160f02013-09-01 23:04:27323
324 TestCompletionCallback connect_callback2;
Sergey Ulanov7cbcbc52017-07-26 18:29:13325 TCPClientSocket connecting_socket2(local_address_list(), nullptr, nullptr,
mikecironef22f9812016-10-04 03:40:19326 NetLogSource());
Sergey Ulanov7cbcbc52017-07-26 18:29:13327 int connect_result2 =
328 connecting_socket2.Connect(connect_callback2.callback());
[email protected]21160f02013-09-01 23:04:27329
robpercival214763f2016-07-01 23:27:01330 EXPECT_THAT(accept_callback.WaitForResult(), IsOk());
[email protected]21160f02013-09-01 23:04:27331
332 TestCompletionCallback accept_callback2;
danakj655b66c2016-04-16 00:51:38333 std::unique_ptr<TCPSocket> accepted_socket2;
[email protected]21160f02013-09-01 23:04:27334 IPEndPoint accepted_address2;
335
336 int result = socket_.Accept(&accepted_socket2, &accepted_address2,
337 accept_callback2.callback());
Sergey Ulanov7cbcbc52017-07-26 18:29:13338 ASSERT_THAT(accept_callback2.GetResult(result), IsOk());
[email protected]21160f02013-09-01 23:04:27339
Sergey Ulanov7cbcbc52017-07-26 18:29:13340 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
341 EXPECT_THAT(connect_callback2.GetResult(connect_result2), IsOk());
[email protected]21160f02013-09-01 23:04:27342
343 EXPECT_TRUE(accepted_socket.get());
344 EXPECT_TRUE(accepted_socket2.get());
345 EXPECT_NE(accepted_socket.get(), accepted_socket2.get());
346
347 EXPECT_EQ(accepted_address.address(), local_address_.address());
348 EXPECT_EQ(accepted_address2.address(), local_address_.address());
349}
350
351// Test listening and accepting with a socket bound to an IPv6 address.
352TEST_F(TCPSocketTest, AcceptIPv6) {
353 bool initialized = false;
354 ASSERT_NO_FATAL_FAILURE(SetUpListenIPv6(&initialized));
355 if (!initialized)
356 return;
357
358 TestCompletionCallback connect_callback;
Sergey Ulanov7cbcbc52017-07-26 18:29:13359 TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
mikecironef22f9812016-10-04 03:40:19360 NetLogSource());
Sergey Ulanov7cbcbc52017-07-26 18:29:13361 int connect_result = connecting_socket.Connect(connect_callback.callback());
[email protected]21160f02013-09-01 23:04:27362
363 TestCompletionCallback accept_callback;
danakj655b66c2016-04-16 00:51:38364 std::unique_ptr<TCPSocket> accepted_socket;
[email protected]21160f02013-09-01 23:04:27365 IPEndPoint accepted_address;
366 int result = socket_.Accept(&accepted_socket, &accepted_address,
367 accept_callback.callback());
Sergey Ulanov7cbcbc52017-07-26 18:29:13368 ASSERT_THAT(accept_callback.GetResult(result), IsOk());
[email protected]21160f02013-09-01 23:04:27369
370 EXPECT_TRUE(accepted_socket.get());
371
372 // Both sockets should be on the loopback network interface.
373 EXPECT_EQ(accepted_address.address(), local_address_.address());
374
Sergey Ulanov7cbcbc52017-07-26 18:29:13375 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
[email protected]21160f02013-09-01 23:04:27376}
377
[email protected]c9080d82013-09-15 15:14:16378TEST_F(TCPSocketTest, ReadWrite) {
379 ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
380
381 TestCompletionCallback connect_callback;
Sergey Ulanov7cbcbc52017-07-26 18:29:13382 TCPSocket connecting_socket(nullptr, nullptr, NetLogSource());
[email protected]c9080d82013-09-15 15:14:16383 int result = connecting_socket.Open(ADDRESS_FAMILY_IPV4);
robpercival214763f2016-07-01 23:27:01384 ASSERT_THAT(result, IsOk());
Sergey Ulanov7cbcbc52017-07-26 18:29:13385 int connect_result =
386 connecting_socket.Connect(local_address_, connect_callback.callback());
[email protected]c9080d82013-09-15 15:14:16387
388 TestCompletionCallback accept_callback;
danakj655b66c2016-04-16 00:51:38389 std::unique_ptr<TCPSocket> accepted_socket;
[email protected]c9080d82013-09-15 15:14:16390 IPEndPoint accepted_address;
391 result = socket_.Accept(&accepted_socket, &accepted_address,
392 accept_callback.callback());
robpercival214763f2016-07-01 23:27:01393 ASSERT_THAT(accept_callback.GetResult(result), IsOk());
[email protected]c9080d82013-09-15 15:14:16394
395 ASSERT_TRUE(accepted_socket.get());
396
397 // Both sockets should be on the loopback network interface.
398 EXPECT_EQ(accepted_address.address(), local_address_.address());
399
Sergey Ulanov7cbcbc52017-07-26 18:29:13400 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
[email protected]c9080d82013-09-15 15:14:16401
402 const std::string message("test message");
403 std::vector<char> buffer(message.size());
404
405 size_t bytes_written = 0;
406 while (bytes_written < message.size()) {
407 scoped_refptr<IOBufferWithSize> write_buffer(
408 new IOBufferWithSize(message.size() - bytes_written));
409 memmove(write_buffer->data(), message.data() + bytes_written,
410 message.size() - bytes_written);
411
412 TestCompletionCallback write_callback;
413 int write_result = accepted_socket->Write(
[email protected]690bbea2017-12-08 09:05:46414 write_buffer.get(), write_buffer->size(), write_callback.callback(),
415 TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c9080d82013-09-15 15:14:16416 write_result = write_callback.GetResult(write_result);
417 ASSERT_TRUE(write_result >= 0);
418 bytes_written += write_result;
419 ASSERT_TRUE(bytes_written <= message.size());
420 }
421
422 size_t bytes_read = 0;
423 while (bytes_read < message.size()) {
424 scoped_refptr<IOBufferWithSize> read_buffer(
425 new IOBufferWithSize(message.size() - bytes_read));
426 TestCompletionCallback read_callback;
427 int read_result = connecting_socket.Read(
428 read_buffer.get(), read_buffer->size(), read_callback.callback());
429 read_result = read_callback.GetResult(read_result);
430 ASSERT_TRUE(read_result >= 0);
431 ASSERT_TRUE(bytes_read + read_result <= message.size());
432 memmove(&buffer[bytes_read], read_buffer->data(), read_result);
433 bytes_read += read_result;
434 }
435
436 std::string received_message(buffer.begin(), buffer.end());
437 ASSERT_EQ(message, received_message);
438}
439
Matt Menkee06732012018-04-06 21:41:24440// Destroy a TCPSocket while there's a pending read, and make sure the read
441// IOBuffer that the socket was holding on to is destroyed.
442// See https://crbug.com/804868.
443TEST_F(TCPSocketTest, DestroyWithPendingRead) {
444 ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
445
446 // Create a connected socket.
447
448 TestCompletionCallback connect_callback;
449 std::unique_ptr<TCPSocket> connecting_socket =
450 std::make_unique<TCPSocket>(nullptr, nullptr, NetLogSource());
451 int result = connecting_socket->Open(ADDRESS_FAMILY_IPV4);
452 ASSERT_THAT(result, IsOk());
453 int connect_result =
454 connecting_socket->Connect(local_address_, connect_callback.callback());
455
456 TestCompletionCallback accept_callback;
457 std::unique_ptr<TCPSocket> accepted_socket;
458 IPEndPoint accepted_address;
459 result = socket_.Accept(&accepted_socket, &accepted_address,
460 accept_callback.callback());
461 ASSERT_THAT(accept_callback.GetResult(result), IsOk());
462 ASSERT_TRUE(accepted_socket.get());
463 ASSERT_THAT(connect_callback.GetResult(connect_result), IsOk());
464
465 // Try to read from the socket, but never write anything to the other end.
466 base::RunLoop run_loop;
467 scoped_refptr<IOBufferWithDestructionCallback> read_buffer(
468 base::MakeRefCounted<IOBufferWithDestructionCallback>(
469 run_loop.QuitClosure()));
470 TestCompletionCallback read_callback;
471 EXPECT_EQ(ERR_IO_PENDING,
472 connecting_socket->Read(read_buffer.get(), read_buffer->size(),
473 read_callback.callback()));
474
475 // Release the handle to the read buffer and destroy the socket. Make sure the
476 // read buffer is destroyed.
477 read_buffer = nullptr;
478 connecting_socket.reset();
479 run_loop.Run();
480}
481
482// Destroy a TCPSocket while there's a pending write, and make sure the write
483// IOBuffer that the socket was holding on to is destroyed.
484TEST_F(TCPSocketTest, DestroyWithPendingWrite) {
485 ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
486
487 // Create a connected socket.
488
489 TestCompletionCallback connect_callback;
490 std::unique_ptr<TCPSocket> connecting_socket =
491 std::make_unique<TCPSocket>(nullptr, nullptr, NetLogSource());
492 int result = connecting_socket->Open(ADDRESS_FAMILY_IPV4);
493 ASSERT_THAT(result, IsOk());
494 int connect_result =
495 connecting_socket->Connect(local_address_, connect_callback.callback());
496
497 TestCompletionCallback accept_callback;
498 std::unique_ptr<TCPSocket> accepted_socket;
499 IPEndPoint accepted_address;
500 result = socket_.Accept(&accepted_socket, &accepted_address,
501 accept_callback.callback());
502 ASSERT_THAT(accept_callback.GetResult(result), IsOk());
503 ASSERT_TRUE(accepted_socket.get());
504 ASSERT_THAT(connect_callback.GetResult(connect_result), IsOk());
505
506 // Repeatedly write to the socket until an operation does not complete
507 // synchronously.
508 base::RunLoop run_loop;
509 scoped_refptr<IOBufferWithDestructionCallback> write_buffer(
510 base::MakeRefCounted<IOBufferWithDestructionCallback>(
511 run_loop.QuitClosure()));
512 memset(write_buffer->data(), '1', write_buffer->size());
513 TestCompletionCallback write_callback;
514 while (true) {
515 int result = connecting_socket->Write(
516 write_buffer.get(), write_buffer->size(), write_callback.callback(),
517 TRAFFIC_ANNOTATION_FOR_TESTS);
518 if (result == ERR_IO_PENDING)
519 break;
520 ASSERT_LT(0, result);
521 }
522
523 // Release the handle to the read buffer and destroy the socket. Make sure the
524 // write buffer is destroyed.
525 write_buffer = nullptr;
526 connecting_socket.reset();
527 run_loop.Run();
528}
529
Helen Li2f1216f92018-05-07 23:20:38530// If a ReadIfReady is pending, it's legal to cancel it and start reading later.
531TEST_F(TCPSocketTest, CancelPendingReadIfReady) {
532 ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
533
534 // Create a connected socket.
535 TestCompletionCallback connect_callback;
536 std::unique_ptr<TCPSocket> connecting_socket =
537 std::make_unique<TCPSocket>(nullptr, nullptr, NetLogSource());
538 int result = connecting_socket->Open(ADDRESS_FAMILY_IPV4);
539 ASSERT_THAT(result, IsOk());
540 int connect_result =
541 connecting_socket->Connect(local_address_, connect_callback.callback());
542
543 TestCompletionCallback accept_callback;
544 std::unique_ptr<TCPSocket> accepted_socket;
545 IPEndPoint accepted_address;
546 result = socket_.Accept(&accepted_socket, &accepted_address,
547 accept_callback.callback());
548 ASSERT_THAT(accept_callback.GetResult(result), IsOk());
549 ASSERT_TRUE(accepted_socket.get());
550 ASSERT_THAT(connect_callback.GetResult(connect_result), IsOk());
551
552 // Try to read from the socket, but never write anything to the other end.
553 base::RunLoop run_loop;
554 scoped_refptr<IOBufferWithDestructionCallback> read_buffer(
555 base::MakeRefCounted<IOBufferWithDestructionCallback>(
556 run_loop.QuitClosure()));
557 TestCompletionCallback read_callback;
558 EXPECT_EQ(ERR_IO_PENDING, connecting_socket->ReadIfReady(
559 read_buffer.get(), read_buffer->size(),
560 read_callback.callback()));
561
562 // Now cancel the pending ReadIfReady().
563 connecting_socket->CancelReadIfReady();
564
565 // Send data to |connecting_socket|.
566 const char kMsg[] = "hello!";
567 scoped_refptr<StringIOBuffer> write_buffer =
568 base::MakeRefCounted<StringIOBuffer>(kMsg);
569
570 TestCompletionCallback write_callback;
571 int write_result = accepted_socket->Write(write_buffer.get(), strlen(kMsg),
572 write_callback.callback(),
573 TRAFFIC_ANNOTATION_FOR_TESTS);
574 const int msg_size = strlen(kMsg);
575 ASSERT_EQ(msg_size, write_result);
576
577 // Try reading again. ReadIfReady() should still succeed.
578 TestCompletionCallback read_callback2;
579 int read_result = connecting_socket->ReadIfReady(
580 read_buffer.get(), read_buffer->size(), read_callback2.callback());
581
582 ASSERT_EQ(msg_size, read_callback2.GetResult(read_result));
583 ASSERT_EQ(0, memcmp(&kMsg, read_buffer->data(), msg_size));
584}
585
tbansal7b403bcc2016-04-13 22:33:21586// These tests require kernel support for tcp_info struct, and so they are
587// enabled only on certain platforms.
588#if defined(TCP_INFO) || defined(OS_LINUX)
589// If SocketPerformanceWatcher::ShouldNotifyUpdatedRTT always returns false,
590// then the wtatcher should not receive any notifications.
591TEST_F(TCPSocketTest, SPWNotInterested) {
tbansal180587c2017-02-16 15:13:23592 TestSPWNotifications(false, 2u, 0u, 0u);
tbansal7b403bcc2016-04-13 22:33:21593}
594
595// One notification should be received when the socket connects. One
tbansal180587c2017-02-16 15:13:23596// additional notification should be received for each message read.
597TEST_F(TCPSocketTest, SPWNoAdvance) {
598 TestSPWNotifications(true, 2u, 0u, 3u);
tbansal7b403bcc2016-04-13 22:33:21599}
600#endif // defined(TCP_INFO) || defined(OS_LINUX)
601
Paul Jensen0f49dec2017-12-12 23:39:58602// On Android, where socket tagging is supported, verify that TCPSocket::Tag
603// works as expected.
604#if defined(OS_ANDROID)
605TEST_F(TCPSocketTest, Tag) {
606 // Start test server.
607 EmbeddedTestServer test_server;
608 test_server.AddDefaultHandlers(base::FilePath());
609 ASSERT_TRUE(test_server.Start());
610
611 AddressList addr_list;
612 ASSERT_TRUE(test_server.GetAddressList(&addr_list));
613 EXPECT_EQ(socket_.Open(addr_list[0].GetFamily()), OK);
614
615 // Verify TCP connect packets are tagged and counted properly.
616 int32_t tag_val1 = 0x12345678;
617 uint64_t old_traffic = GetTaggedBytes(tag_val1);
618 SocketTag tag1(SocketTag::UNSET_UID, tag_val1);
619 socket_.ApplySocketTag(tag1);
620 TestCompletionCallback connect_callback;
621 int connect_result =
622 socket_.Connect(addr_list[0], connect_callback.callback());
623 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
624 EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
625
626 // Verify socket can be retagged with a new value and the current process's
627 // UID.
628 int32_t tag_val2 = 0x87654321;
629 old_traffic = GetTaggedBytes(tag_val2);
630 SocketTag tag2(getuid(), tag_val2);
631 socket_.ApplySocketTag(tag2);
Paul Jensen8d6f87ec2018-01-13 00:46:54632 const char kRequest1[] = "GET / HTTP/1.0";
633 scoped_refptr<IOBuffer> write_buffer1(new StringIOBuffer(kRequest1));
Paul Jensen0f49dec2017-12-12 23:39:58634 TestCompletionCallback write_callback1;
635 EXPECT_EQ(
636 socket_.Write(write_buffer1.get(), strlen(kRequest1),
637 write_callback1.callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
Paul Jensen8d6f87ec2018-01-13 00:46:54638 static_cast<int>(strlen(kRequest1)));
Paul Jensen0f49dec2017-12-12 23:39:58639 EXPECT_GT(GetTaggedBytes(tag_val2), old_traffic);
640
641 // Verify socket can be retagged with a new value and the current process's
642 // UID.
643 old_traffic = GetTaggedBytes(tag_val1);
644 socket_.ApplySocketTag(tag1);
645 const char kRequest2[] = "\n\n";
Paul Jensen8d6f87ec2018-01-13 00:46:54646 scoped_refptr<IOBuffer> write_buffer2(new StringIOBuffer(kRequest2));
Paul Jensen0f49dec2017-12-12 23:39:58647 TestCompletionCallback write_callback2;
648 EXPECT_EQ(
649 socket_.Write(write_buffer2.get(), strlen(kRequest2),
650 write_callback2.callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
Paul Jensen8d6f87ec2018-01-13 00:46:54651 static_cast<int>(strlen(kRequest2)));
Paul Jensen0f49dec2017-12-12 23:39:58652 EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
653
654 socket_.Close();
655}
656
657TEST_F(TCPSocketTest, TagAfterConnect) {
658 // Start test server.
659 EmbeddedTestServer test_server;
660 test_server.AddDefaultHandlers(base::FilePath());
661 ASSERT_TRUE(test_server.Start());
662
663 AddressList addr_list;
664 ASSERT_TRUE(test_server.GetAddressList(&addr_list));
665 EXPECT_EQ(socket_.Open(addr_list[0].GetFamily()), OK);
666
667 // Connect socket.
668 TestCompletionCallback connect_callback;
669 int connect_result =
670 socket_.Connect(addr_list[0], connect_callback.callback());
671 EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
672
673 // Verify socket can be tagged with a new value and the current process's
674 // UID.
675 int32_t tag_val2 = 0x87654321;
676 uint64_t old_traffic = GetTaggedBytes(tag_val2);
677 SocketTag tag2(getuid(), tag_val2);
678 socket_.ApplySocketTag(tag2);
Paul Jensen8d6f87ec2018-01-13 00:46:54679 const char kRequest1[] = "GET / HTTP/1.0";
680 scoped_refptr<IOBuffer> write_buffer1(new StringIOBuffer(kRequest1));
Paul Jensen0f49dec2017-12-12 23:39:58681 TestCompletionCallback write_callback1;
682 EXPECT_EQ(
683 socket_.Write(write_buffer1.get(), strlen(kRequest1),
684 write_callback1.callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
Paul Jensen8d6f87ec2018-01-13 00:46:54685 static_cast<int>(strlen(kRequest1)));
Paul Jensen0f49dec2017-12-12 23:39:58686 EXPECT_GT(GetTaggedBytes(tag_val2), old_traffic);
687
688 // Verify socket can be retagged with a new value and the current process's
689 // UID.
690 int32_t tag_val1 = 0x12345678;
691 old_traffic = GetTaggedBytes(tag_val1);
692 SocketTag tag1(SocketTag::UNSET_UID, tag_val1);
693 socket_.ApplySocketTag(tag1);
694 const char kRequest2[] = "\n\n";
Paul Jensen8d6f87ec2018-01-13 00:46:54695 scoped_refptr<IOBuffer> write_buffer2(new StringIOBuffer(kRequest2));
Paul Jensen0f49dec2017-12-12 23:39:58696 TestCompletionCallback write_callback2;
697 EXPECT_EQ(
698 socket_.Write(write_buffer2.get(), strlen(kRequest2),
699 write_callback2.callback(), TRAFFIC_ANNOTATION_FOR_TESTS),
Paul Jensen8d6f87ec2018-01-13 00:46:54700 static_cast<int>(strlen(kRequest2)));
Paul Jensen0f49dec2017-12-12 23:39:58701 EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
702
703 socket_.Close();
704}
705#endif
706
[email protected]21160f02013-09-01 23:04:27707} // namespace
708} // namespace net