blob: 2c90639775dbb84ffe5a6377d6c83ff9ef09c494 [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"
sergeyuaa22c082015-07-20 19:41:139#include "net/base/io_buffer.h"
[email protected]c3af26f332010-10-06 22:46:0010#include "net/base/net_errors.h"
sergeyuaa22c082015-07-20 19:41:1311#include "net/socket/socket.h"
[email protected]a2b2cfc2017-12-06 09:06:0812#include "net/traffic_annotation/network_traffic_annotation.h"
[email protected]c3af26f332010-10-06 22:46:0013
14namespace remoting {
15
sergeyuaa22c082015-07-20 19:41:1316namespace {
17
18int WriteNetSocket(net::Socket* socket,
19 const scoped_refptr<net::IOBuffer>& buf,
20 int buf_len,
[email protected]a2b2cfc2017-12-06 09:06:0821 const net::CompletionCallback& callback,
22 const net::NetworkTrafficAnnotationTag& traffic_annotation) {
23 return socket->Write(buf.get(), buf_len, callback, traffic_annotation);
sergeyuaa22c082015-07-20 19:41:1324}
25
26} // namespace
27
28struct BufferedSocketWriter::PendingPacket {
29 PendingPacket(scoped_refptr<net::DrainableIOBuffer> data,
[email protected]1029a002017-12-18 17:52:0030 const base::Closure& done_task,
31 const net::NetworkTrafficAnnotationTag& traffic_annotation)
[email protected]27626e62012-08-01 01:48:0232 : data(data),
[email protected]1029a002017-12-18 17:52:0033 done_task(done_task),
34 traffic_annotation(traffic_annotation) {}
[email protected]5bc71832010-12-09 01:34:0835
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]1029a002017-12-18 17:52:0038 net::NetworkTrafficAnnotationTag traffic_annotation;
[email protected]5bc71832010-12-09 01:34:0839};
40
sergeyuaa22c082015-07-20 19:41:1341// static
dcheng0765c492016-04-06 22:41:5342std::unique_ptr<BufferedSocketWriter> BufferedSocketWriter::CreateForSocket(
sergeyuaa22c082015-07-20 19:41:1343 net::Socket* socket,
44 const WriteFailedCallback& write_failed_callback) {
dcheng0765c492016-04-06 22:41:5345 std::unique_ptr<BufferedSocketWriter> result(new BufferedSocketWriter());
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
Jinho Bang138fde32018-01-18 23:13:4275 queue_.push_back(std::make_unique<PendingPacket>(
[email protected]1029a002017-12-18 17:52:0076 new net::DrainableIOBuffer(data.get(), data->size()), done_task,
77 traffic_annotation));
[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()) {
sergeyuaa22c082015-07-20 19:41:1388 int result = write_callback_.Run(
89 queue_.front()->data.get(), queue_.front()->data->BytesRemaining(),
90 base::Bind(&BufferedSocketWriter::OnWritten,
[email protected]a2b2cfc2017-12-06 09:06:0891 weak_factory_.GetWeakPtr()),
[email protected]1029a002017-12-18 17:52:0092 queue_.front()->traffic_annotation);
sergeyuaa22c082015-07-20 19:41:1393 HandleWriteResult(result);
[email protected]27626e62012-08-01 01:48:0294 }
95}
96
sergeyuaa22c082015-07-20 19:41:1397void BufferedSocketWriter::HandleWriteResult(int result) {
[email protected]27626e62012-08-01 01:48:0298 if (result < 0) {
99 if (result == net::ERR_IO_PENDING) {
100 write_pending_ = true;
[email protected]c3af26f332010-10-06 22:46:00101 } else {
sergeyuc3497fc2016-01-14 06:53:01102 closed_ = true;
sergeyuaa22c082015-07-20 19:41:13103 write_callback_.Reset();
sergeyuc3497fc2016-01-14 06:53:01104 if (!write_failed_callback_.is_null())
105 base::ResetAndReturn(&write_failed_callback_).Run(result);
[email protected]27626e62012-08-01 01:48:02106 }
107 return;
108 }
109
sergeyuaa22c082015-07-20 19:41:13110 DCHECK(!queue_.empty());
[email protected]27626e62012-08-01 01:48:02111
sergeyuaa22c082015-07-20 19:41:13112 queue_.front()->data->DidConsume(result);
113
114 if (queue_.front()->data->BytesRemaining() == 0) {
115 base::Closure done_task = queue_.front()->done_task;
sergeyuaa22c082015-07-20 19:41:13116 queue_.pop_front();
117
118 if (!done_task.is_null())
119 done_task.Run();
120 }
[email protected]c3af26f332010-10-06 22:46:00121}
122
sergeyuaa22c082015-07-20 19:41:13123void BufferedSocketWriter::OnWritten(int result) {
124 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]27626e62012-08-01 01:48:02125 DCHECK(write_pending_);
[email protected]c3af26f332010-10-06 22:46:00126 write_pending_ = false;
127
sergeyuaa22c082015-07-20 19:41:13128 base::WeakPtr<BufferedSocketWriter> self = weak_factory_.GetWeakPtr();
129 HandleWriteResult(result);
130 if (self)
[email protected]27626e62012-08-01 01:48:02131 DoWrite();
[email protected]c3af26f332010-10-06 22:46:00132}
133
[email protected]c3af26f332010-10-06 22:46:00134} // namespace remoting