blob: b2dec655d1cdb8d9b65e2b67754929545d7dc10b [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,
Brad Lassey3a814172018-04-26 03:30:2121 net::CompletionOnceCallback callback,
[email protected]a2b2cfc2017-12-06 09:06:0822 const net::NetworkTrafficAnnotationTag& traffic_annotation) {
Brad Lassey3a814172018-04-26 03:30:2123 return socket->Write(buf.get(), buf_len, std::move(callback),
24 traffic_annotation);
sergeyuaa22c082015-07-20 19:41:1325}
26
27} // namespace
28
29struct BufferedSocketWriter::PendingPacket {
30 PendingPacket(scoped_refptr<net::DrainableIOBuffer> data,
[email protected]1029a002017-12-18 17:52:0031 const base::Closure& done_task,
32 const net::NetworkTrafficAnnotationTag& traffic_annotation)
[email protected]27626e62012-08-01 01:48:0233 : data(data),
[email protected]1029a002017-12-18 17:52:0034 done_task(done_task),
35 traffic_annotation(traffic_annotation) {}
[email protected]5bc71832010-12-09 01:34:0836
sergeyuaa22c082015-07-20 19:41:1337 scoped_refptr<net::DrainableIOBuffer> data;
[email protected]27626e62012-08-01 01:48:0238 base::Closure done_task;
[email protected]1029a002017-12-18 17:52:0039 net::NetworkTrafficAnnotationTag traffic_annotation;
[email protected]5bc71832010-12-09 01:34:0840};
41
sergeyuaa22c082015-07-20 19:41:1342// static
dcheng0765c492016-04-06 22:41:5343std::unique_ptr<BufferedSocketWriter> BufferedSocketWriter::CreateForSocket(
sergeyuaa22c082015-07-20 19:41:1344 net::Socket* socket,
45 const WriteFailedCallback& write_failed_callback) {
Victor Costancd439782018-08-30 07:27:5746 std::unique_ptr<BufferedSocketWriter> result =
47 std::make_unique<BufferedSocketWriter>();
sergeyuc3497fc2016-01-14 06:53:0148 result->Start(base::Bind(&WriteNetSocket, socket), write_failed_callback);
sergeyu42ad7c02015-12-24 00:20:5149 return result;
[email protected]c3af26f332010-10-06 22:46:0050}
51
sergeyu42ad7c02015-12-24 00:20:5152BufferedSocketWriter::BufferedSocketWriter() : weak_factory_(this) {}
[email protected]c3af26f332010-10-06 22:46:0053
joedow6daaab3e2017-05-10 22:30:3754BufferedSocketWriter::~BufferedSocketWriter() {
55 DCHECK(thread_checker_.CalledOnValidThread());
56}
sergeyuaa22c082015-07-20 19:41:1357
sergeyuc3497fc2016-01-14 06:53:0158void BufferedSocketWriter::Start(
sergeyuaa22c082015-07-20 19:41:1359 const WriteCallback& write_callback,
60 const WriteFailedCallback& write_failed_callback) {
61 write_callback_ = write_callback;
62 write_failed_callback_ = write_failed_callback;
sergeyuc3497fc2016-01-14 06:53:0163 DoWrite();
sergeyuaa22c082015-07-20 19:41:1364}
65
sergeyu7e2c7b22015-07-30 23:58:2966void BufferedSocketWriter::Write(
Victor Costancd439782018-08-30 07:27:5767 scoped_refptr<net::IOBufferWithSize> data,
[email protected]f94cd9702017-12-07 06:09:4068 const base::Closure& done_task,
69 const net::NetworkTrafficAnnotationTag& traffic_annotation) {
sergeyuaa22c082015-07-20 19:41:1370 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]27626e62012-08-01 01:48:0271 DCHECK(data.get());
[email protected]a3464dca2012-05-24 01:27:0972
sergeyuaa22c082015-07-20 19:41:1373 // Don't write after error.
sergeyuc3497fc2016-01-14 06:53:0174 if (closed_)
sergeyu7e2c7b22015-07-30 23:58:2975 return;
[email protected]a3464dca2012-05-24 01:27:0976
Victor Costancd439782018-08-30 07:27:5777 int data_size = data->size();
Jinho Bang138fde32018-01-18 23:13:4278 queue_.push_back(std::make_unique<PendingPacket>(
Victor Costancd439782018-08-30 07:27:5779 base::MakeRefCounted<net::DrainableIOBuffer>(std::move(data), data_size),
80 done_task, traffic_annotation));
[email protected]a3464dca2012-05-24 01:27:0981
82 DoWrite();
[email protected]c3af26f332010-10-06 22:46:0083}
84
sergeyuaa22c082015-07-20 19:41:1385void BufferedSocketWriter::DoWrite() {
86 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]c3af26f332010-10-06 22:46:0087
sergeyuaa22c082015-07-20 19:41:1388 base::WeakPtr<BufferedSocketWriter> self = weak_factory_.GetWeakPtr();
sergeyuc3497fc2016-01-14 06:53:0189 while (self && !write_pending_ && !write_callback_.is_null() &&
90 !queue_.empty()) {
sergeyuaa22c082015-07-20 19:41:1391 int result = write_callback_.Run(
92 queue_.front()->data.get(), queue_.front()->data->BytesRemaining(),
93 base::Bind(&BufferedSocketWriter::OnWritten,
[email protected]a2b2cfc2017-12-06 09:06:0894 weak_factory_.GetWeakPtr()),
[email protected]1029a002017-12-18 17:52:0095 queue_.front()->traffic_annotation);
sergeyuaa22c082015-07-20 19:41:1396 HandleWriteResult(result);
[email protected]27626e62012-08-01 01:48:0297 }
98}
99
sergeyuaa22c082015-07-20 19:41:13100void BufferedSocketWriter::HandleWriteResult(int result) {
[email protected]27626e62012-08-01 01:48:02101 if (result < 0) {
102 if (result == net::ERR_IO_PENDING) {
103 write_pending_ = true;
[email protected]c3af26f332010-10-06 22:46:00104 } else {
sergeyuc3497fc2016-01-14 06:53:01105 closed_ = true;
sergeyuaa22c082015-07-20 19:41:13106 write_callback_.Reset();
sergeyuc3497fc2016-01-14 06:53:01107 if (!write_failed_callback_.is_null())
Brad Lassey3a814172018-04-26 03:30:21108 std::move(write_failed_callback_).Run(result);
[email protected]27626e62012-08-01 01:48:02109 }
110 return;
111 }
112
sergeyuaa22c082015-07-20 19:41:13113 DCHECK(!queue_.empty());
[email protected]27626e62012-08-01 01:48:02114
sergeyuaa22c082015-07-20 19:41:13115 queue_.front()->data->DidConsume(result);
116
117 if (queue_.front()->data->BytesRemaining() == 0) {
118 base::Closure done_task = queue_.front()->done_task;
sergeyuaa22c082015-07-20 19:41:13119 queue_.pop_front();
120
121 if (!done_task.is_null())
122 done_task.Run();
123 }
[email protected]c3af26f332010-10-06 22:46:00124}
125
sergeyuaa22c082015-07-20 19:41:13126void BufferedSocketWriter::OnWritten(int result) {
127 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]27626e62012-08-01 01:48:02128 DCHECK(write_pending_);
[email protected]c3af26f332010-10-06 22:46:00129 write_pending_ = false;
130
sergeyuaa22c082015-07-20 19:41:13131 base::WeakPtr<BufferedSocketWriter> self = weak_factory_.GetWeakPtr();
132 HandleWriteResult(result);
133 if (self)
[email protected]27626e62012-08-01 01:48:02134 DoWrite();
[email protected]c3af26f332010-10-06 22:46:00135}
136
[email protected]c3af26f332010-10-06 22:46:00137} // namespace remoting