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.
5 #include "remoting/protocol/quic_channel.h"
7 #include "base/callback_helpers.h"
8 #include "net/base/io_buffer.h"
9 #include "net/base/net_errors.h"
14 static const size_t kNamePrefixLength
= 1;
15 static const size_t kMaxNameLength
= 255;
17 QuicChannel::QuicChannel(net::QuicP2PStream
* stream
,
18 const base::Closure
& on_destroyed_callback
)
19 : stream_(stream
), on_destroyed_callback_(on_destroyed_callback
) {
21 stream_
->SetDelegate(this);
24 QuicChannel::~QuicChannel() {
25 // Don't call the read callback when destroying the stream.
26 read_callback_
.Reset();
28 on_destroyed_callback_
.Run();
30 // The callback must destroy the stream which must result in OnClose().
34 int QuicChannel::Read(const scoped_refptr
<net::IOBuffer
>& buffer
,
36 const net::CompletionCallback
& callback
) {
37 DCHECK(read_callback_
.is_null());
39 if (error_
!= net::OK
)
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
;
49 int result
= std::min(buffer_len
, data_received_
.total_bytes());
50 data_received_
.CopyTo(buffer
->data(), result
);
51 data_received_
.CropFront(result
);
55 int QuicChannel::Write(const scoped_refptr
<net::IOBuffer
>& buffer
,
57 const net::CompletionCallback
& callback
) {
58 if (error_
!= net::OK
)
61 return stream_
->Write(base::StringPiece(buffer
->data(), buffer_len
),
65 void QuicChannel::SetName(const std::string
& name
) {
66 DCHECK(name_
.empty());
71 void QuicChannel::OnDataReceived(const char* data
, int length
) {
72 if (read_callback_
.is_null()) {
73 data_received_
.AppendCopyOf(data
, length
);
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;
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
);
86 base::ResetAndReturn(&read_callback_
).Run(bytes_to_read
);
89 void QuicChannel::OnClose(net::QuicErrorCode error
) {
90 error_
= (error
== net::QUIC_NO_ERROR
) ? net::ERR_CONNECTION_CLOSED
91 : net::ERR_QUIC_PROTOCOL_ERROR
;
93 if (!read_callback_
.is_null()) {
94 base::ResetAndReturn(&read_callback_
).Run(error_
);
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
);
106 // Send the name to the host.
107 stream_
->WriteHeader(
108 std::string(kNamePrefixLength
, static_cast<char>(name
.size())) + name
);
111 QuicClientChannel::~QuicClientChannel() {}
113 QuicServerChannel::QuicServerChannel(
114 net::QuicP2PStream
* stream
,
115 const base::Closure
& on_destroyed_callback
)
116 : QuicChannel(stream
, on_destroyed_callback
) {}
118 void QuicServerChannel::ReceiveName(
119 const base::Closure
& name_received_callback
) {
120 name_received_callback_
= name_received_callback
;
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
);
132 QuicServerChannel::~QuicServerChannel() {}
134 void QuicServerChannel::OnNameSizeReadResult(int result
) {
136 base::ResetAndReturn(&name_received_callback_
).Run();
140 DCHECK_EQ(result
, static_cast<int>(kNamePrefixLength
));
141 name_length_
= *reinterpret_cast<uint8_t*>(name_read_buffer_
->data());
143 new net::DrainableIOBuffer(new net::IOBuffer(name_length_
), name_length_
);
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)));
153 name_read_buffer_
->DidConsume(result
);
157 if (result
< 0 && result
!= net::ERR_IO_PENDING
) {
158 // Failed to read name for the stream.
159 base::ResetAndReturn(&name_received_callback_
).Run();
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();
171 void QuicServerChannel::OnNameReadResult(int result
) {
173 name_read_buffer_
->DidConsume(result
);
175 ReadNameLoop(result
);
178 } // namespace protocol
179 } // namespace remoting