blob: c5a9b7b9bcbc8384a17246e584ed2d1004d3c956 [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]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,
21 const net::CompletionCallback& callback) {
22 return socket->Write(buf.get(), buf_len, callback);
23}
24
25} // namespace
26
27struct BufferedSocketWriter::PendingPacket {
28 PendingPacket(scoped_refptr<net::DrainableIOBuffer> data,
[email protected]9e2a3132011-10-07 05:07:4029 const base::Closure& done_task)
[email protected]27626e62012-08-01 01:48:0230 : data(data),
31 done_task(done_task) {
[email protected]5bc71832010-12-09 01:34:0832 }
33
sergeyuaa22c082015-07-20 19:41:1334 scoped_refptr<net::DrainableIOBuffer> data;
[email protected]27626e62012-08-01 01:48:0235 base::Closure done_task;
[email protected]5bc71832010-12-09 01:34:0836};
37
sergeyuaa22c082015-07-20 19:41:1338// static
dcheng0765c492016-04-06 22:41:5339std::unique_ptr<BufferedSocketWriter> BufferedSocketWriter::CreateForSocket(
sergeyuaa22c082015-07-20 19:41:1340 net::Socket* socket,
41 const WriteFailedCallback& write_failed_callback) {
dcheng0765c492016-04-06 22:41:5342 std::unique_ptr<BufferedSocketWriter> result(new BufferedSocketWriter());
sergeyuc3497fc2016-01-14 06:53:0143 result->Start(base::Bind(&WriteNetSocket, socket), write_failed_callback);
sergeyu42ad7c02015-12-24 00:20:5144 return result;
[email protected]c3af26f332010-10-06 22:46:0045}
46
sergeyu42ad7c02015-12-24 00:20:5147BufferedSocketWriter::BufferedSocketWriter() : weak_factory_(this) {}
[email protected]c3af26f332010-10-06 22:46:0048
joedow6daaab3e2017-05-10 22:30:3749BufferedSocketWriter::~BufferedSocketWriter() {
50 DCHECK(thread_checker_.CalledOnValidThread());
51}
sergeyuaa22c082015-07-20 19:41:1352
sergeyuc3497fc2016-01-14 06:53:0153void BufferedSocketWriter::Start(
sergeyuaa22c082015-07-20 19:41:1354 const WriteCallback& write_callback,
55 const WriteFailedCallback& write_failed_callback) {
56 write_callback_ = write_callback;
57 write_failed_callback_ = write_failed_callback;
sergeyuc3497fc2016-01-14 06:53:0158 DoWrite();
sergeyuaa22c082015-07-20 19:41:1359}
60
sergeyu7e2c7b22015-07-30 23:58:2961void BufferedSocketWriter::Write(
sergeyuaa22c082015-07-20 19:41:1362 const scoped_refptr<net::IOBufferWithSize>& data,
63 const base::Closure& done_task) {
64 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]27626e62012-08-01 01:48:0265 DCHECK(data.get());
[email protected]a3464dca2012-05-24 01:27:0966
sergeyuaa22c082015-07-20 19:41:1367 // Don't write after error.
sergeyuc3497fc2016-01-14 06:53:0168 if (closed_)
sergeyu7e2c7b22015-07-30 23:58:2969 return;
[email protected]a3464dca2012-05-24 01:27:0970
avic58e7852016-10-01 05:58:0071 queue_.push_back(base::MakeUnique<PendingPacket>(
sergeyuaa22c082015-07-20 19:41:1372 new net::DrainableIOBuffer(data.get(), data->size()), done_task));
[email protected]a3464dca2012-05-24 01:27:0973
74 DoWrite();
[email protected]c3af26f332010-10-06 22:46:0075}
76
sergeyuaa22c082015-07-20 19:41:1377void BufferedSocketWriter::DoWrite() {
78 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]c3af26f332010-10-06 22:46:0079
sergeyuaa22c082015-07-20 19:41:1380 base::WeakPtr<BufferedSocketWriter> self = weak_factory_.GetWeakPtr();
sergeyuc3497fc2016-01-14 06:53:0181 while (self && !write_pending_ && !write_callback_.is_null() &&
82 !queue_.empty()) {
sergeyuaa22c082015-07-20 19:41:1383 int result = write_callback_.Run(
84 queue_.front()->data.get(), queue_.front()->data->BytesRemaining(),
85 base::Bind(&BufferedSocketWriter::OnWritten,
86 weak_factory_.GetWeakPtr()));
87 HandleWriteResult(result);
[email protected]27626e62012-08-01 01:48:0288 }
89}
90
sergeyuaa22c082015-07-20 19:41:1391void BufferedSocketWriter::HandleWriteResult(int result) {
[email protected]27626e62012-08-01 01:48:0292 if (result < 0) {
93 if (result == net::ERR_IO_PENDING) {
94 write_pending_ = true;
[email protected]c3af26f332010-10-06 22:46:0095 } else {
sergeyuc3497fc2016-01-14 06:53:0196 closed_ = true;
sergeyuaa22c082015-07-20 19:41:1397 write_callback_.Reset();
sergeyuc3497fc2016-01-14 06:53:0198 if (!write_failed_callback_.is_null())
99 base::ResetAndReturn(&write_failed_callback_).Run(result);
[email protected]27626e62012-08-01 01:48:02100 }
101 return;
102 }
103
sergeyuaa22c082015-07-20 19:41:13104 DCHECK(!queue_.empty());
[email protected]27626e62012-08-01 01:48:02105
sergeyuaa22c082015-07-20 19:41:13106 queue_.front()->data->DidConsume(result);
107
108 if (queue_.front()->data->BytesRemaining() == 0) {
109 base::Closure done_task = queue_.front()->done_task;
sergeyuaa22c082015-07-20 19:41:13110 queue_.pop_front();
111
112 if (!done_task.is_null())
113 done_task.Run();
114 }
[email protected]c3af26f332010-10-06 22:46:00115}
116
sergeyuaa22c082015-07-20 19:41:13117void BufferedSocketWriter::OnWritten(int result) {
118 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]27626e62012-08-01 01:48:02119 DCHECK(write_pending_);
[email protected]c3af26f332010-10-06 22:46:00120 write_pending_ = false;
121
sergeyuaa22c082015-07-20 19:41:13122 base::WeakPtr<BufferedSocketWriter> self = weak_factory_.GetWeakPtr();
123 HandleWriteResult(result);
124 if (self)
[email protected]27626e62012-08-01 01:48:02125 DoWrite();
[email protected]c3af26f332010-10-06 22:46:00126}
127
[email protected]c3af26f332010-10-06 22:46:00128} // namespace remoting