OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "remoting/protocol/quic_channel.h" |
| 6 |
| 7 #include "base/callback_helpers.h" |
| 8 #include "net/base/io_buffer.h" |
| 9 #include "net/base/net_errors.h" |
| 10 |
| 11 namespace remoting { |
| 12 namespace protocol { |
| 13 |
| 14 static const size_t kNamePrefixLength = 1; |
| 15 static const size_t kMaxNameLength = 255; |
| 16 |
| 17 QuicChannel::QuicChannel(net::QuicP2PStream* stream, |
| 18 const base::Closure& on_destroyed_callback) |
| 19 : stream_(stream), on_destroyed_callback_(on_destroyed_callback) { |
| 20 DCHECK(stream_); |
| 21 stream_->SetDelegate(this); |
| 22 } |
| 23 |
| 24 QuicChannel::~QuicChannel() { |
| 25 // Don't call the read callback when destroying the stream. |
| 26 read_callback_.Reset(); |
| 27 |
| 28 on_destroyed_callback_.Run(); |
| 29 |
| 30 // The callback must destroy the stream which must result in OnClose(). |
| 31 DCHECK(!stream_); |
| 32 } |
| 33 |
| 34 int QuicChannel::Read(const scoped_refptr<net::IOBuffer>& buffer, |
| 35 int buffer_len, |
| 36 const net::CompletionCallback& callback) { |
| 37 DCHECK(read_callback_.is_null()); |
| 38 |
| 39 if (error_ != net::OK) |
| 40 return error_; |
| 41 |
| 42 if (data_received_.total_bytes() == 0) { |
| 43 read_buffer_ = buffer; |
| 44 read_buffer_size_ = buffer_len; |
| 45 read_callback_ = callback; |
| 46 return net::ERR_IO_PENDING; |
| 47 } |
| 48 |
| 49 int result = std::min(buffer_len, data_received_.total_bytes()); |
| 50 data_received_.CopyTo(buffer->data(), result); |
| 51 data_received_.CropFront(result); |
| 52 return result; |
| 53 } |
| 54 |
| 55 int QuicChannel::Write(const scoped_refptr<net::IOBuffer>& buffer, |
| 56 int buffer_len, |
| 57 const net::CompletionCallback& callback) { |
| 58 if (error_ != net::OK) |
| 59 return error_; |
| 60 |
| 61 return stream_->Write(base::StringPiece(buffer->data(), buffer_len), |
| 62 callback); |
| 63 } |
| 64 |
| 65 void QuicChannel::SetName(const std::string& name) { |
| 66 DCHECK(name_.empty()); |
| 67 |
| 68 name_ = name; |
| 69 } |
| 70 |
| 71 void QuicChannel::OnDataReceived(const char* data, int length) { |
| 72 if (read_callback_.is_null()) { |
| 73 data_received_.AppendCopyOf(data, length); |
| 74 return; |
| 75 } |
| 76 |
| 77 DCHECK_EQ(data_received_.total_bytes(), 0); |
| 78 int bytes_to_read = std::min(length, read_buffer_size_); |
| 79 memcpy(read_buffer_->data(), data, bytes_to_read); |
| 80 read_buffer_ = nullptr; |
| 81 |
| 82 // Copy leftover data to |data_received_|. |
| 83 if (length > bytes_to_read) |
| 84 data_received_.AppendCopyOf(data + bytes_to_read, length - bytes_to_read); |
| 85 |
| 86 base::ResetAndReturn(&read_callback_).Run(bytes_to_read); |
| 87 } |
| 88 |
| 89 void QuicChannel::OnClose(net::QuicErrorCode error) { |
| 90 error_ = (error == net::QUIC_NO_ERROR) ? net::ERR_CONNECTION_CLOSED |
| 91 : net::ERR_QUIC_PROTOCOL_ERROR; |
| 92 stream_ = nullptr; |
| 93 if (!read_callback_.is_null()) { |
| 94 base::ResetAndReturn(&read_callback_).Run(error_); |
| 95 } |
| 96 } |
| 97 |
| 98 QuicClientChannel::QuicClientChannel(net::QuicP2PStream* stream, |
| 99 const base::Closure& on_destroyed_callback, |
| 100 const std::string& name) |
| 101 : QuicChannel(stream, on_destroyed_callback) { |
| 102 CHECK_LE(name.size(), kMaxNameLength); |
| 103 |
| 104 SetName(name); |
| 105 |
| 106 // Send the name to the host. |
| 107 stream_->WriteHeader( |
| 108 std::string(kNamePrefixLength, static_cast<char>(name.size())) + name); |
| 109 } |
| 110 |
| 111 QuicClientChannel::~QuicClientChannel() {} |
| 112 |
| 113 QuicServerChannel::QuicServerChannel( |
| 114 net::QuicP2PStream* stream, |
| 115 const base::Closure& on_destroyed_callback) |
| 116 : QuicChannel(stream, on_destroyed_callback) {} |
| 117 |
| 118 void QuicServerChannel::ReceiveName( |
| 119 const base::Closure& name_received_callback) { |
| 120 name_received_callback_ = name_received_callback; |
| 121 |
| 122 // First read 1 byte containing name length. |
| 123 name_read_buffer_ = new net::DrainableIOBuffer( |
| 124 new net::IOBuffer(kNamePrefixLength), kNamePrefixLength); |
| 125 int result = Read(name_read_buffer_, kNamePrefixLength, |
| 126 base::Bind(&QuicServerChannel::OnNameSizeReadResult, |
| 127 base::Unretained(this))); |
| 128 if (result != net::ERR_IO_PENDING) |
| 129 OnNameSizeReadResult(result); |
| 130 } |
| 131 |
| 132 QuicServerChannel::~QuicServerChannel() {} |
| 133 |
| 134 void QuicServerChannel::OnNameSizeReadResult(int result) { |
| 135 if (result < 0) { |
| 136 base::ResetAndReturn(&name_received_callback_).Run(); |
| 137 return; |
| 138 } |
| 139 |
| 140 DCHECK_EQ(result, static_cast<int>(kNamePrefixLength)); |
| 141 name_length_ = *reinterpret_cast<uint8_t*>(name_read_buffer_->data()); |
| 142 name_read_buffer_ = |
| 143 new net::DrainableIOBuffer(new net::IOBuffer(name_length_), name_length_); |
| 144 ReadNameLoop(0); |
| 145 } |
| 146 |
| 147 void QuicServerChannel::ReadNameLoop(int result) { |
| 148 while (result >= 0 && name_read_buffer_->BytesRemaining() > 0) { |
| 149 result = Read(name_read_buffer_, name_read_buffer_->BytesRemaining(), |
| 150 base::Bind(&QuicServerChannel::OnNameReadResult, |
| 151 base::Unretained(this))); |
| 152 if (result >= 0) { |
| 153 name_read_buffer_->DidConsume(result); |
| 154 } |
| 155 } |
| 156 |
| 157 if (result < 0 && result != net::ERR_IO_PENDING) { |
| 158 // Failed to read name for the stream. |
| 159 base::ResetAndReturn(&name_received_callback_).Run(); |
| 160 return; |
| 161 } |
| 162 |
| 163 if (name_read_buffer_->BytesRemaining() == 0) { |
| 164 name_read_buffer_->SetOffset(0); |
| 165 SetName(std::string(name_read_buffer_->data(), |
| 166 name_read_buffer_->data() + name_length_)); |
| 167 base::ResetAndReturn(&name_received_callback_).Run(); |
| 168 } |
| 169 } |
| 170 |
| 171 void QuicServerChannel::OnNameReadResult(int result) { |
| 172 if (result > 0) |
| 173 name_read_buffer_->DidConsume(result); |
| 174 |
| 175 ReadNameLoop(result); |
| 176 } |
| 177 |
| 178 } // namespace protocol |
| 179 } // namespace remoting |
OLD | NEW |