blob: db96be54ced6292e6f1c4332f4cdea090475e30d [file] [log] [blame]
sergeyu031ce3b32015-07-06 19:00:461// Copyright 2015 The Chromium Authors. All rights reserved.
[email protected]db6609b82011-04-22 01:30:512// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
sergeyu031ce3b32015-07-06 19:00:465#include "remoting/protocol/pseudotcp_adapter.h"
[email protected]db6609b82011-04-22 01:30:516
fdoray2ad58be2016-06-22 20:36:167#include <utility>
[email protected]db6609b82011-04-22 01:30:518#include <vector>
9
[email protected]31a7eef72011-11-12 21:18:1610#include "base/bind.h"
11#include "base/bind_helpers.h"
[email protected]3f197732011-11-17 20:08:5612#include "base/compiler_specific.h"
Brett Wilson55ff1475e2017-09-26 00:28:4813#include "base/containers/circular_deque.h"
fdorayb0bfadc2016-06-06 18:06:5214#include "base/location.h"
dcheng0765c492016-04-06 22:41:5315#include "base/memory/ptr_util.h"
Alexander Timin4f9c35c2018-11-01 20:15:2016#include "base/message_loop/message_loop.h"
fdoray2ad58be2016-06-22 20:36:1617#include "base/run_loop.h"
Gabriel Charette5ff87ce2017-05-16 18:03:4518#include "base/single_thread_task_runner.h"
fdorayb0bfadc2016-06-06 18:06:5219#include "base/threading/thread_task_runner_handle.h"
[email protected]e86b28f2011-07-29 22:21:0720#include "jingle/glue/thread_wrapper.h"
[email protected]db6609b82011-04-22 01:30:5121#include "net/base/io_buffer.h"
22#include "net/base/net_errors.h"
23#include "net/base/test_completion_callback.h"
[email protected]f94cd9702017-12-07 06:09:4024#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
sergeyuaa22c082015-07-20 19:41:1325#include "remoting/protocol/p2p_datagram_socket.h"
26#include "remoting/protocol/p2p_stream_socket.h"
[email protected]db6609b82011-04-22 01:30:5127#include "testing/gmock/include/gmock/gmock.h"
28#include "testing/gtest/include/gtest/gtest.h"
29
sergeyu031ce3b32015-07-06 19:00:4630namespace remoting {
31namespace protocol {
[email protected]db6609b82011-04-22 01:30:5132
33namespace {
34
[email protected]db6609b82011-04-22 01:30:5135const int kMessageSize = 1024;
36const int kMessages = 100;
37const int kTestDataSize = kMessages * kMessageSize;
38
[email protected]bbb8ba02011-08-23 01:29:2539class RateLimiter {
40 public:
Chris Watkins6fe52aa2017-11-28 03:24:0541 virtual ~RateLimiter() = default;
42 ;
[email protected]bbb8ba02011-08-23 01:29:2543 // Returns true if the new packet needs to be dropped, false otherwise.
44 virtual bool DropNextPacket() = 0;
45};
46
47class LeakyBucket : public RateLimiter {
48 public:
49 // |rate| is in drops per second.
50 LeakyBucket(double volume, double rate)
51 : volume_(volume),
52 rate_(rate),
53 level_(0.0),
charliea3be839702015-01-26 17:35:4154 last_update_(base::TimeTicks::Now()) {
[email protected]bbb8ba02011-08-23 01:29:2555 }
56
Chris Watkins6fe52aa2017-11-28 03:24:0557 ~LeakyBucket() override = default;
[email protected]bbb8ba02011-08-23 01:29:2558
dcheng5364bdee2014-10-22 23:38:3159 bool DropNextPacket() override {
charliea3be839702015-01-26 17:35:4160 base::TimeTicks now = base::TimeTicks::Now();
[email protected]bbb8ba02011-08-23 01:29:2561 double interval = (now - last_update_).InSecondsF();
62 last_update_ = now;
63 level_ = level_ + 1.0 - interval * rate_;
64 if (level_ > volume_) {
65 level_ = volume_;
66 return true;
67 } else if (level_ < 0.0) {
68 level_ = 0.0;
69 }
70 return false;
71 }
72
73 private:
74 double volume_;
75 double rate_;
76 double level_;
77 base::TimeTicks last_update_;
78};
79
sergeyuaa22c082015-07-20 19:41:1380class FakeSocket : public P2PDatagramSocket {
[email protected]db6609b82011-04-22 01:30:5181 public:
82 FakeSocket()
[email protected]83039bb2011-12-09 18:43:5583 : rate_limiter_(NULL),
[email protected]bbb8ba02011-08-23 01:29:2584 latency_ms_(0) {
[email protected]db6609b82011-04-22 01:30:5185 }
Chris Watkins6fe52aa2017-11-28 03:24:0586 ~FakeSocket() override = default;
[email protected]db6609b82011-04-22 01:30:5187
88 void AppendInputPacket(const std::vector<char>& data) {
[email protected]bbb8ba02011-08-23 01:29:2589 if (rate_limiter_ && rate_limiter_->DropNextPacket())
[email protected]db6609b82011-04-22 01:30:5190 return; // Lose the packet.
91
[email protected]83039bb2011-12-09 18:43:5592 if (!read_callback_.is_null()) {
[email protected]db6609b82011-04-22 01:30:5193 int size = std::min(read_buffer_size_, static_cast<int>(data.size()));
94 memcpy(read_buffer_->data(), &data[0], data.size());
[email protected]83039bb2011-12-09 18:43:5595 net::CompletionCallback cb = read_callback_;
96 read_callback_.Reset();
97 read_buffer_ = NULL;
98 cb.Run(size);
[email protected]db6609b82011-04-22 01:30:5199 } else {
100 incoming_packets_.push_back(data);
101 }
102 }
103
104 void Connect(FakeSocket* peer_socket) {
105 peer_socket_ = peer_socket;
106 }
107
[email protected]bbb8ba02011-08-23 01:29:25108 void set_rate_limiter(RateLimiter* rate_limiter) {
109 rate_limiter_ = rate_limiter;
110 };
111
112 void set_latency(int latency_ms) { latency_ms_ = latency_ms; };
[email protected]db6609b82011-04-22 01:30:51113
sergeyuaa22c082015-07-20 19:41:13114 // P2PDatagramSocket interface.
115 int Recv(const scoped_refptr<net::IOBuffer>& buf, int buf_len,
dcheng5364bdee2014-10-22 23:38:31116 const net::CompletionCallback& callback) override {
[email protected]83039bb2011-12-09 18:43:55117 CHECK(read_callback_.is_null());
[email protected]db6609b82011-04-22 01:30:51118 CHECK(buf);
119
120 if (incoming_packets_.size() > 0) {
121 scoped_refptr<net::IOBuffer> buffer(buf);
122 int size = std::min(
123 static_cast<int>(incoming_packets_.front().size()), buf_len);
124 memcpy(buffer->data(), &*incoming_packets_.front().begin(), size);
125 incoming_packets_.pop_front();
126 return size;
127 } else {
128 read_callback_ = callback;
129 read_buffer_ = buf;
130 read_buffer_size_ = buf_len;
131 return net::ERR_IO_PENDING;
132 }
133 }
134
sergeyuaa22c082015-07-20 19:41:13135 int Send(const scoped_refptr<net::IOBuffer>& buf, int buf_len,
136 const net::CompletionCallback& callback) override {
[email protected]db6609b82011-04-22 01:30:51137 DCHECK(buf);
138 if (peer_socket_) {
fdorayb0bfadc2016-06-06 18:06:52139 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
[email protected]31a7eef72011-11-12 21:18:16140 FROM_HERE,
141 base::Bind(&FakeSocket::AppendInputPacket,
142 base::Unretained(peer_socket_),
143 std::vector<char>(buf->data(), buf->data() + buf_len)),
[email protected]1e2076be2012-03-05 01:16:33144 base::TimeDelta::FromMilliseconds(latency_ms_));
[email protected]db6609b82011-04-22 01:30:51145 }
146
147 return buf_len;
148 }
149
[email protected]db6609b82011-04-22 01:30:51150 private:
151 scoped_refptr<net::IOBuffer> read_buffer_;
152 int read_buffer_size_;
[email protected]3f55aa12011-12-07 02:03:33153 net::CompletionCallback read_callback_;
[email protected]db6609b82011-04-22 01:30:51154
Brett Wilson55ff1475e2017-09-26 00:28:48155 base::circular_deque<std::vector<char>> incoming_packets_;
[email protected]db6609b82011-04-22 01:30:51156
157 FakeSocket* peer_socket_;
[email protected]bbb8ba02011-08-23 01:29:25158 RateLimiter* rate_limiter_;
159 int latency_ms_;
[email protected]db6609b82011-04-22 01:30:51160};
161
162class TCPChannelTester : public base::RefCountedThreadSafe<TCPChannelTester> {
163 public:
fdoray2ad58be2016-06-22 20:36:16164 TCPChannelTester(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
sergeyuaa22c082015-07-20 19:41:13165 P2PStreamSocket* client_socket,
166 P2PStreamSocket* host_socket)
fdoray2ad58be2016-06-22 20:36:16167 : task_runner_(std::move(task_runner)),
[email protected]db6609b82011-04-22 01:30:51168 host_socket_(host_socket),
169 client_socket_(client_socket),
170 done_(false),
[email protected]db6609b82011-04-22 01:30:51171 write_errors_(0),
[email protected]b231184d2013-04-27 07:51:55172 read_errors_(0) {}
[email protected]db6609b82011-04-22 01:30:51173
[email protected]db6609b82011-04-22 01:30:51174 void Start() {
fdoray2ad58be2016-06-22 20:36:16175 task_runner_->PostTask(FROM_HERE,
176 base::Bind(&TCPChannelTester::DoStart, this));
[email protected]db6609b82011-04-22 01:30:51177 }
178
179 void CheckResults() {
180 EXPECT_EQ(0, write_errors_);
181 EXPECT_EQ(0, read_errors_);
182
183 ASSERT_EQ(kTestDataSize + kMessageSize, input_buffer_->capacity());
184
185 output_buffer_->SetOffset(0);
186 ASSERT_EQ(kTestDataSize, output_buffer_->size());
187
188 EXPECT_EQ(0, memcmp(output_buffer_->data(),
189 input_buffer_->StartOfBuffer(), kTestDataSize));
190 }
191
192 protected:
Chris Watkins6fe52aa2017-11-28 03:24:05193 virtual ~TCPChannelTester() = default;
[email protected]60e60dd2012-04-28 08:16:04194
[email protected]db6609b82011-04-22 01:30:51195 void Done() {
196 done_ = true;
Gabriel Charetteea918012018-05-16 11:53:44197 task_runner_->PostTask(
198 FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
[email protected]db6609b82011-04-22 01:30:51199 }
200
201 void DoStart() {
202 InitBuffers();
203 DoRead();
204 DoWrite();
205 }
206
207 void InitBuffers() {
Victor Costancd439782018-08-30 07:27:57208 output_buffer_ = base::MakeRefCounted<net::DrainableIOBuffer>(
209 base::MakeRefCounted<net::IOBuffer>(kTestDataSize), kTestDataSize);
[email protected]db6609b82011-04-22 01:30:51210 memset(output_buffer_->data(), 123, kTestDataSize);
211
Victor Costan8a7a19a2018-09-10 21:57:16212 input_buffer_ = base::MakeRefCounted<net::GrowableIOBuffer>();
[email protected]db6609b82011-04-22 01:30:51213 // Always keep kMessageSize bytes available at the end of the input buffer.
214 input_buffer_->SetCapacity(kMessageSize);
215 }
216
217 void DoWrite() {
218 int result = 1;
219 while (result > 0) {
220 if (output_buffer_->BytesRemaining() == 0)
221 break;
222
223 int bytes_to_write = std::min(output_buffer_->BytesRemaining(),
224 kMessageSize);
[email protected]83039bb2011-12-09 18:43:55225 result = client_socket_->Write(
[email protected]f94cd9702017-12-07 06:09:40226 output_buffer_.get(), bytes_to_write,
227 base::Bind(&TCPChannelTester::OnWritten, base::Unretained(this)),
228 TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db6609b82011-04-22 01:30:51229 HandleWriteResult(result);
230 }
231 }
232
233 void OnWritten(int result) {
234 HandleWriteResult(result);
235 DoWrite();
236 }
237
238 void HandleWriteResult(int result) {
239 if (result <= 0 && result != net::ERR_IO_PENDING) {
240 LOG(ERROR) << "Received error " << result << " when trying to write";
241 write_errors_++;
242 Done();
243 } else if (result > 0) {
244 output_buffer_->DidConsume(result);
245 }
246 }
247
248 void DoRead() {
249 int result = 1;
250 while (result > 0) {
251 input_buffer_->set_offset(input_buffer_->capacity() - kMessageSize);
252
[email protected]f9d8a772013-06-01 04:33:17253 result = host_socket_->Read(
254 input_buffer_.get(),
255 kMessageSize,
256 base::Bind(&TCPChannelTester::OnRead, base::Unretained(this)));
[email protected]db6609b82011-04-22 01:30:51257 HandleReadResult(result);
258 };
259 }
260
261 void OnRead(int result) {
262 HandleReadResult(result);
263 DoRead();
264 }
265
266 void HandleReadResult(int result) {
267 if (result <= 0 && result != net::ERR_IO_PENDING) {
268 if (!done_) {
269 LOG(ERROR) << "Received error " << result << " when trying to read";
270 read_errors_++;
271 Done();
272 }
273 } else if (result > 0) {
274 // Allocate memory for the next read.
275 input_buffer_->SetCapacity(input_buffer_->capacity() + result);
276 if (input_buffer_->capacity() == kTestDataSize + kMessageSize)
277 Done();
278 }
279 }
280
281 private:
[email protected]60e60dd2012-04-28 08:16:04282 friend class base::RefCountedThreadSafe<TCPChannelTester>;
283
fdoray2ad58be2016-06-22 20:36:16284 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
sergeyuaa22c082015-07-20 19:41:13285 P2PStreamSocket* host_socket_;
286 P2PStreamSocket* client_socket_;
[email protected]db6609b82011-04-22 01:30:51287 bool done_;
288
289 scoped_refptr<net::DrainableIOBuffer> output_buffer_;
290 scoped_refptr<net::GrowableIOBuffer> input_buffer_;
291
[email protected]db6609b82011-04-22 01:30:51292 int write_errors_;
293 int read_errors_;
294};
295
[email protected]36cf5102011-05-27 01:43:57296class PseudoTcpAdapterTest : public testing::Test {
[email protected]db6609b82011-04-22 01:30:51297 protected:
dchenga4ebdc482014-12-22 23:11:30298 void SetUp() override {
sergeyu031ce3b32015-07-06 19:00:46299 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
[email protected]e86b28f2011-07-29 22:21:07300
[email protected]db6609b82011-04-22 01:30:51301 host_socket_ = new FakeSocket();
302 client_socket_ = new FakeSocket();
303
304 host_socket_->Connect(client_socket_);
305 client_socket_->Connect(host_socket_);
306
dcheng0765c492016-04-06 22:41:53307 host_pseudotcp_.reset(new PseudoTcpAdapter(base::WrapUnique(host_socket_)));
sergeyu031ce3b32015-07-06 19:00:46308 client_pseudotcp_.reset(
dcheng0765c492016-04-06 22:41:53309 new PseudoTcpAdapter(base::WrapUnique(client_socket_)));
[email protected]db6609b82011-04-22 01:30:51310 }
311
312 FakeSocket* host_socket_;
313 FakeSocket* client_socket_;
314
dcheng0765c492016-04-06 22:41:53315 std::unique_ptr<PseudoTcpAdapter> host_pseudotcp_;
316 std::unique_ptr<PseudoTcpAdapter> client_pseudotcp_;
[email protected]b231184d2013-04-27 07:51:55317 base::MessageLoop message_loop_;
[email protected]db6609b82011-04-22 01:30:51318};
319
[email protected]36cf5102011-05-27 01:43:57320TEST_F(PseudoTcpAdapterTest, DataTransfer) {
[email protected]83039bb2011-12-09 18:43:55321 net::TestCompletionCallback host_connect_cb;
322 net::TestCompletionCallback client_connect_cb;
[email protected]db6609b82011-04-22 01:30:51323
[email protected]83039bb2011-12-09 18:43:55324 int rv1 = host_pseudotcp_->Connect(host_connect_cb.callback());
325 int rv2 = client_pseudotcp_->Connect(client_connect_cb.callback());
[email protected]886ae9f2011-07-05 17:37:04326
327 if (rv1 == net::ERR_IO_PENDING)
328 rv1 = host_connect_cb.WaitForResult();
329 if (rv2 == net::ERR_IO_PENDING)
330 rv2 = client_connect_cb.WaitForResult();
331 ASSERT_EQ(net::OK, rv1);
332 ASSERT_EQ(net::OK, rv2);
[email protected]db6609b82011-04-22 01:30:51333
334 scoped_refptr<TCPChannelTester> tester =
fdoray2ad58be2016-06-22 20:36:16335 new TCPChannelTester(base::ThreadTaskRunnerHandle::Get(),
336 host_pseudotcp_.get(), client_pseudotcp_.get());
[email protected]db6609b82011-04-22 01:30:51337
338 tester->Start();
fdoray2ad58be2016-06-22 20:36:16339 base::RunLoop().Run();
[email protected]db6609b82011-04-22 01:30:51340 tester->CheckResults();
341}
342
[email protected]bbb8ba02011-08-23 01:29:25343TEST_F(PseudoTcpAdapterTest, LimitedChannel) {
344 const int kLatencyMs = 20;
345 const int kPacketsPerSecond = 400;
346 const int kBurstPackets = 10;
347
348 LeakyBucket host_limiter(kBurstPackets, kPacketsPerSecond);
349 host_socket_->set_latency(kLatencyMs);
350 host_socket_->set_rate_limiter(&host_limiter);
351
352 LeakyBucket client_limiter(kBurstPackets, kPacketsPerSecond);
353 host_socket_->set_latency(kLatencyMs);
354 client_socket_->set_rate_limiter(&client_limiter);
[email protected]db6609b82011-04-22 01:30:51355
[email protected]83039bb2011-12-09 18:43:55356 net::TestCompletionCallback host_connect_cb;
357 net::TestCompletionCallback client_connect_cb;
[email protected]db6609b82011-04-22 01:30:51358
[email protected]83039bb2011-12-09 18:43:55359 int rv1 = host_pseudotcp_->Connect(host_connect_cb.callback());
360 int rv2 = client_pseudotcp_->Connect(client_connect_cb.callback());
[email protected]886ae9f2011-07-05 17:37:04361
362 if (rv1 == net::ERR_IO_PENDING)
363 rv1 = host_connect_cb.WaitForResult();
364 if (rv2 == net::ERR_IO_PENDING)
365 rv2 = client_connect_cb.WaitForResult();
366 ASSERT_EQ(net::OK, rv1);
367 ASSERT_EQ(net::OK, rv2);
[email protected]db6609b82011-04-22 01:30:51368
369 scoped_refptr<TCPChannelTester> tester =
fdoray2ad58be2016-06-22 20:36:16370 new TCPChannelTester(base::ThreadTaskRunnerHandle::Get(),
371 host_pseudotcp_.get(), client_pseudotcp_.get());
[email protected]db6609b82011-04-22 01:30:51372
373 tester->Start();
fdoray2ad58be2016-06-22 20:36:16374 base::RunLoop().Run();
[email protected]db6609b82011-04-22 01:30:51375 tester->CheckResults();
376}
377
[email protected]6b302a862011-05-25 04:23:29378class DeleteOnConnected {
379 public:
fdoray2ad58be2016-06-22 20:36:16380 DeleteOnConnected(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
dcheng0765c492016-04-06 22:41:53381 std::unique_ptr<PseudoTcpAdapter>* adapter)
fdoray2ad58be2016-06-22 20:36:16382 : task_runner_(std::move(task_runner)), adapter_(adapter) {}
[email protected]6b302a862011-05-25 04:23:29383 void OnConnected(int error) {
384 adapter_->reset();
Gabriel Charetteea918012018-05-16 11:53:44385 task_runner_->PostTask(
386 FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
[email protected]6b302a862011-05-25 04:23:29387 }
fdoray2ad58be2016-06-22 20:36:16388 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
dcheng0765c492016-04-06 22:41:53389 std::unique_ptr<PseudoTcpAdapter>* adapter_;
[email protected]6b302a862011-05-25 04:23:29390};
391
[email protected]36cf5102011-05-27 01:43:57392TEST_F(PseudoTcpAdapterTest, DeleteOnConnected) {
[email protected]6b302a862011-05-25 04:23:29393 // This test verifies that deleting the adapter mid-callback doesn't lead
394 // to deleted structures being touched as the stack unrolls, so the failure
395 // mode is a crash rather than a normal test failure.
[email protected]83039bb2011-12-09 18:43:55396 net::TestCompletionCallback client_connect_cb;
fdoray2ad58be2016-06-22 20:36:16397 DeleteOnConnected host_delete(base::ThreadTaskRunnerHandle::Get(),
398 &host_pseudotcp_);
[email protected]6b302a862011-05-25 04:23:29399
[email protected]83039bb2011-12-09 18:43:55400 host_pseudotcp_->Connect(base::Bind(&DeleteOnConnected::OnConnected,
401 base::Unretained(&host_delete)));
402 client_pseudotcp_->Connect(client_connect_cb.callback());
fdoray2ad58be2016-06-22 20:36:16403 base::RunLoop().Run();
[email protected]6b302a862011-05-25 04:23:29404
405 ASSERT_EQ(NULL, host_pseudotcp_.get());
406}
407
[email protected]46934c02012-04-06 02:56:39408// Verify that we can send/receive data with the write-waits-for-send
409// flag set.
410TEST_F(PseudoTcpAdapterTest, WriteWaitsForSendLetsDataThrough) {
411 net::TestCompletionCallback host_connect_cb;
412 net::TestCompletionCallback client_connect_cb;
413
414 host_pseudotcp_->SetWriteWaitsForSend(true);
415 client_pseudotcp_->SetWriteWaitsForSend(true);
416
417 // Disable Nagle's algorithm because the test is slow when it is
418 // enabled.
419 host_pseudotcp_->SetNoDelay(true);
420
421 int rv1 = host_pseudotcp_->Connect(host_connect_cb.callback());
422 int rv2 = client_pseudotcp_->Connect(client_connect_cb.callback());
423
424 if (rv1 == net::ERR_IO_PENDING)
425 rv1 = host_connect_cb.WaitForResult();
426 if (rv2 == net::ERR_IO_PENDING)
427 rv2 = client_connect_cb.WaitForResult();
428 ASSERT_EQ(net::OK, rv1);
429 ASSERT_EQ(net::OK, rv2);
430
431 scoped_refptr<TCPChannelTester> tester =
fdoray2ad58be2016-06-22 20:36:16432 new TCPChannelTester(base::ThreadTaskRunnerHandle::Get(),
433 host_pseudotcp_.get(), client_pseudotcp_.get());
[email protected]46934c02012-04-06 02:56:39434
435 tester->Start();
fdoray2ad58be2016-06-22 20:36:16436 base::RunLoop().Run();
[email protected]46934c02012-04-06 02:56:39437 tester->CheckResults();
438}
439
[email protected]db6609b82011-04-22 01:30:51440} // namespace
441
sergeyu031ce3b32015-07-06 19:00:46442} // namespace protocol
443} // namespace remoting