blob: bb13d3666f86401a34a27e753c934453b9ba050d [file] [log] [blame]
sergeyu7c4800b82015-02-26 18:02:491// Copyright 2015 The Chromium Authors. All rights reserved.
[email protected]c3af26f332010-10-06 22:46:002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
sergeyu7c4800b82015-02-26 18:02:495#include "remoting/base/buffered_socket_writer.h"
[email protected]c3af26f332010-10-06 22:46:006
[email protected]9e2a3132011-10-07 05:07:407#include "base/bind.h"
sergeyuc3497fc2016-01-14 06:53:018#include "base/callback_helpers.h"
avic58e7852016-10-01 05:58:009#include "base/memory/ptr_util.h"
sergeyuaa22c082015-07-20 19:41:1310#include "net/base/io_buffer.h"
[email protected]c3af26f332010-10-06 22:46:0011#include "net/base/net_errors.h"
sergeyuaa22c082015-07-20 19:41:1312#include "net/socket/socket.h"
[email protected]a2b2cfc2017-12-06 09:06:0813#include "net/traffic_annotation/network_traffic_annotation.h"
[email protected]c3af26f332010-10-06 22:46:0014
15namespace remoting {
16
sergeyuaa22c082015-07-20 19:41:1317namespace {
18
19int WriteNetSocket(net::Socket* socket,
20 const scoped_refptr<net::IOBuffer>& buf,
21 int buf_len,
[email protected]a2b2cfc2017-12-06 09:06:0822 const net::CompletionCallback& callback,
23 const net::NetworkTrafficAnnotationTag& traffic_annotation) {
24 return socket->Write(buf.get(), buf_len, callback, traffic_annotation);
sergeyuaa22c082015-07-20 19:41:1325}
26
27} // namespace
28
29struct BufferedSocketWriter::PendingPacket {
30 PendingPacket(scoped_refptr<net::DrainableIOBuffer> data,
[email protected]9e2a3132011-10-07 05:07:4031 const base::Closure& done_task)
[email protected]27626e62012-08-01 01:48:0232 : data(data),
33 done_task(done_task) {
[email protected]5bc71832010-12-09 01:34:0834 }
35
sergeyuaa22c082015-07-20 19:41:1336 scoped_refptr<net::DrainableIOBuffer> data;
[email protected]27626e62012-08-01 01:48:0237 base::Closure done_task;
[email protected]5bc71832010-12-09 01:34:0838};
39
sergeyuaa22c082015-07-20 19:41:1340// static
dcheng0765c492016-04-06 22:41:5341std::unique_ptr<BufferedSocketWriter> BufferedSocketWriter::CreateForSocket(
sergeyuaa22c082015-07-20 19:41:1342 net::Socket* socket,
43 const WriteFailedCallback& write_failed_callback) {
dcheng0765c492016-04-06 22:41:5344 std::unique_ptr<BufferedSocketWriter> result(new BufferedSocketWriter());
[email protected]a2b2cfc2017-12-06 09:06:0845 // TODO(crbug.com/656607): Add proper network traffic annotation.
sergeyuc3497fc2016-01-14 06:53:0146 result->Start(base::Bind(&WriteNetSocket, socket), write_failed_callback);
sergeyu42ad7c02015-12-24 00:20:5147 return result;
[email protected]c3af26f332010-10-06 22:46:0048}
49
sergeyu42ad7c02015-12-24 00:20:5150BufferedSocketWriter::BufferedSocketWriter() : weak_factory_(this) {}
[email protected]c3af26f332010-10-06 22:46:0051
joedow6daaab3e2017-05-10 22:30:3752BufferedSocketWriter::~BufferedSocketWriter() {
53 DCHECK(thread_checker_.CalledOnValidThread());
54}
sergeyuaa22c082015-07-20 19:41:1355
sergeyuc3497fc2016-01-14 06:53:0156void BufferedSocketWriter::Start(
sergeyuaa22c082015-07-20 19:41:1357 const WriteCallback& write_callback,
58 const WriteFailedCallback& write_failed_callback) {
59 write_callback_ = write_callback;
60 write_failed_callback_ = write_failed_callback;
sergeyuc3497fc2016-01-14 06:53:0161 DoWrite();
sergeyuaa22c082015-07-20 19:41:1362}
63
sergeyu7e2c7b22015-07-30 23:58:2964void BufferedSocketWriter::Write(
sergeyuaa22c082015-07-20 19:41:1365 const scoped_refptr<net::IOBufferWithSize>& data,
[email protected]f94cd9702017-12-07 06:09:4066 const base::Closure& done_task,
67 const net::NetworkTrafficAnnotationTag& traffic_annotation) {
sergeyuaa22c082015-07-20 19:41:1368 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]27626e62012-08-01 01:48:0269 DCHECK(data.get());
[email protected]a3464dca2012-05-24 01:27:0970
sergeyuaa22c082015-07-20 19:41:1371 // Don't write after error.
sergeyuc3497fc2016-01-14 06:53:0172 if (closed_)
sergeyu7e2c7b22015-07-30 23:58:2973 return;
[email protected]a3464dca2012-05-24 01:27:0974
[email protected]f94cd9702017-12-07 06:09:4075 // TODO(crbug.com/656607): Handle traffic annotation.
avic58e7852016-10-01 05:58:0076 queue_.push_back(base::MakeUnique<PendingPacket>(
sergeyuaa22c082015-07-20 19:41:1377 new net::DrainableIOBuffer(data.get(), data->size()), done_task));
[email protected]a3464dca2012-05-24 01:27:0978
79 DoWrite();
[email protected]c3af26f332010-10-06 22:46:0080}
81
sergeyuaa22c082015-07-20 19:41:1382void BufferedSocketWriter::DoWrite() {
83 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]c3af26f332010-10-06 22:46:0084
sergeyuaa22c082015-07-20 19:41:1385 base::WeakPtr<BufferedSocketWriter> self = weak_factory_.GetWeakPtr();
sergeyuc3497fc2016-01-14 06:53:0186 while (self && !write_pending_ && !write_callback_.is_null() &&
87 !queue_.empty()) {
[email protected]a2b2cfc2017-12-06 09:06:0888 // TODO(crbug.com/656607): Add proper network traffic annotation.
sergeyuaa22c082015-07-20 19:41:1389 int result = write_callback_.Run(
90 queue_.front()->data.get(), queue_.front()->data->BytesRemaining(),
91 base::Bind(&BufferedSocketWriter::OnWritten,
[email protected]a2b2cfc2017-12-06 09:06:0892 weak_factory_.GetWeakPtr()),
93 NO_TRAFFIC_ANNOTATION_BUG_656607);
sergeyuaa22c082015-07-20 19:41:1394 HandleWriteResult(result);
[email protected]27626e62012-08-01 01:48:0295 }
96}
97
sergeyuaa22c082015-07-20 19:41:1398void BufferedSocketWriter::HandleWriteResult(int result) {
[email protected]27626e62012-08-01 01:48:0299 if (result < 0) {
100 if (result == net::ERR_IO_PENDING) {
101 write_pending_ = true;
[email protected]c3af26f332010-10-06 22:46:00102 } else {
sergeyuc3497fc2016-01-14 06:53:01103 closed_ = true;
sergeyuaa22c082015-07-20 19:41:13104 write_callback_.Reset();
sergeyuc3497fc2016-01-14 06:53:01105 if (!write_failed_callback_.is_null())
106 base::ResetAndReturn(&write_failed_callback_).Run(result);
[email protected]27626e62012-08-01 01:48:02107 }
108 return;
109 }
110
sergeyuaa22c082015-07-20 19:41:13111 DCHECK(!queue_.empty());
[email protected]27626e62012-08-01 01:48:02112
sergeyuaa22c082015-07-20 19:41:13113 queue_.front()->data->DidConsume(result);
114
115 if (queue_.front()->data->BytesRemaining() == 0) {
116 base::Closure done_task = queue_.front()->done_task;
sergeyuaa22c082015-07-20 19:41:13117 queue_.pop_front();
118
119 if (!done_task.is_null())
120 done_task.Run();
121 }
[email protected]c3af26f332010-10-06 22:46:00122}
123
sergeyuaa22c082015-07-20 19:41:13124void BufferedSocketWriter::OnWritten(int result) {
125 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]27626e62012-08-01 01:48:02126 DCHECK(write_pending_);
[email protected]c3af26f332010-10-06 22:46:00127 write_pending_ = false;
128
sergeyuaa22c082015-07-20 19:41:13129 base::WeakPtr<BufferedSocketWriter> self = weak_factory_.GetWeakPtr();
130 HandleWriteResult(result);
131 if (self)
[email protected]27626e62012-08-01 01:48:02132 DoWrite();
[email protected]c3af26f332010-10-06 22:46:00133}
134
[email protected]c3af26f332010-10-06 22:46:00135} // namespace remoting