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 |