OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/spdy_proxy_client_socket.h" | 5 #include "net/spdy/spdy_proxy_client_socket.h" |
6 | 6 |
7 #include <algorithm> // min | 7 #include <algorithm> // min |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 user_agent); | 49 user_agent); |
50 spdy_stream_->SetDelegate(this); | 50 spdy_stream_->SetDelegate(this); |
51 was_ever_used_ = spdy_stream_->WasEverUsed(); | 51 was_ever_used_ = spdy_stream_->WasEverUsed(); |
52 } | 52 } |
53 | 53 |
54 SpdyProxyClientSocket::~SpdyProxyClientSocket() { | 54 SpdyProxyClientSocket::~SpdyProxyClientSocket() { |
55 Disconnect(); | 55 Disconnect(); |
56 } | 56 } |
57 | 57 |
58 const HttpResponseInfo* SpdyProxyClientSocket::GetConnectResponseInfo() const { | 58 const HttpResponseInfo* SpdyProxyClientSocket::GetConnectResponseInfo() const { |
59 return response_.headers ? &response_ : NULL; | 59 return response_.headers.get() ? &response_ : NULL; |
60 } | 60 } |
61 | 61 |
62 const scoped_refptr<HttpAuthController>& | 62 const scoped_refptr<HttpAuthController>& |
63 SpdyProxyClientSocket::GetAuthController() const { | 63 SpdyProxyClientSocket::GetAuthController() const { |
64 return auth_; | 64 return auth_; |
65 } | 65 } |
66 | 66 |
67 int SpdyProxyClientSocket::RestartWithAuth(const CompletionCallback& callback) { | 67 int SpdyProxyClientSocket::RestartWithAuth(const CompletionCallback& callback) { |
68 // A SPDY Stream can only handle a single request, so the underlying | 68 // A SPDY Stream can only handle a single request, so the underlying |
69 // stream may not be reused and a new SpdyProxyClientSocket must be | 69 // stream may not be reused and a new SpdyProxyClientSocket must be |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 read_buffer_.clear(); | 119 read_buffer_.clear(); |
120 user_buffer_ = NULL; | 120 user_buffer_ = NULL; |
121 read_callback_.Reset(); | 121 read_callback_.Reset(); |
122 | 122 |
123 write_buffer_len_ = 0; | 123 write_buffer_len_ = 0; |
124 write_bytes_outstanding_ = 0; | 124 write_bytes_outstanding_ = 0; |
125 write_callback_.Reset(); | 125 write_callback_.Reset(); |
126 | 126 |
127 next_state_ = STATE_DISCONNECTED; | 127 next_state_ = STATE_DISCONNECTED; |
128 | 128 |
129 if (spdy_stream_) | 129 if (spdy_stream_.get()) |
130 // This will cause OnClose to be invoked, which takes care of | 130 // This will cause OnClose to be invoked, which takes care of |
131 // cleaning up all the internal state. | 131 // cleaning up all the internal state. |
132 spdy_stream_->Cancel(); | 132 spdy_stream_->Cancel(); |
133 } | 133 } |
134 | 134 |
135 bool SpdyProxyClientSocket::IsConnected() const { | 135 bool SpdyProxyClientSocket::IsConnected() const { |
136 return next_state_ == STATE_OPEN; | 136 return next_state_ == STATE_OPEN; |
137 } | 137 } |
138 | 138 |
139 bool SpdyProxyClientSocket::IsConnectedAndIdle() const { | 139 bool SpdyProxyClientSocket::IsConnectedAndIdle() const { |
140 return IsConnected() && read_buffer_.empty() && spdy_stream_->is_idle(); | 140 return IsConnected() && read_buffer_.empty() && spdy_stream_->is_idle(); |
141 } | 141 } |
142 | 142 |
143 const BoundNetLog& SpdyProxyClientSocket::NetLog() const { | 143 const BoundNetLog& SpdyProxyClientSocket::NetLog() const { |
144 return net_log_; | 144 return net_log_; |
145 } | 145 } |
146 | 146 |
147 void SpdyProxyClientSocket::SetSubresourceSpeculation() { | 147 void SpdyProxyClientSocket::SetSubresourceSpeculation() { |
148 // TODO(rch): what should this implementation be? | 148 // TODO(rch): what should this implementation be? |
149 } | 149 } |
150 | 150 |
151 void SpdyProxyClientSocket::SetOmniboxSpeculation() { | 151 void SpdyProxyClientSocket::SetOmniboxSpeculation() { |
152 // TODO(rch): what should this implementation be? | 152 // TODO(rch): what should this implementation be? |
153 } | 153 } |
154 | 154 |
155 bool SpdyProxyClientSocket::WasEverUsed() const { | 155 bool SpdyProxyClientSocket::WasEverUsed() const { |
156 return was_ever_used_ || (spdy_stream_ && spdy_stream_->WasEverUsed()); | 156 return was_ever_used_ || (spdy_stream_.get() && spdy_stream_->WasEverUsed()); |
157 } | 157 } |
158 | 158 |
159 bool SpdyProxyClientSocket::UsingTCPFastOpen() const { | 159 bool SpdyProxyClientSocket::UsingTCPFastOpen() const { |
160 return false; | 160 return false; |
161 } | 161 } |
162 | 162 |
163 int64 SpdyProxyClientSocket::NumBytesRead() const { | 163 int64 SpdyProxyClientSocket::NumBytesRead() const { |
164 return -1; | 164 return -1; |
165 } | 165 } |
166 | 166 |
(...skipping 12 matching lines...) Expand all Loading... |
179 bool SpdyProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) { | 179 bool SpdyProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) { |
180 bool was_npn_negotiated; | 180 bool was_npn_negotiated; |
181 NextProto protocol_negotiated; | 181 NextProto protocol_negotiated; |
182 return spdy_stream_->GetSSLInfo(ssl_info, &was_npn_negotiated, | 182 return spdy_stream_->GetSSLInfo(ssl_info, &was_npn_negotiated, |
183 &protocol_negotiated); | 183 &protocol_negotiated); |
184 } | 184 } |
185 | 185 |
186 int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, | 186 int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, |
187 const CompletionCallback& callback) { | 187 const CompletionCallback& callback) { |
188 DCHECK(read_callback_.is_null()); | 188 DCHECK(read_callback_.is_null()); |
189 DCHECK(!user_buffer_); | 189 DCHECK(!user_buffer_.get()); |
190 | 190 |
191 if (next_state_ == STATE_DISCONNECTED) | 191 if (next_state_ == STATE_DISCONNECTED) |
192 return ERR_SOCKET_NOT_CONNECTED; | 192 return ERR_SOCKET_NOT_CONNECTED; |
193 | 193 |
194 if (next_state_ == STATE_CLOSED && read_buffer_.empty()) { | 194 if (next_state_ == STATE_CLOSED && read_buffer_.empty()) { |
195 return 0; | 195 return 0; |
196 } | 196 } |
197 | 197 |
198 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); | 198 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); |
199 DCHECK(buf); | 199 DCHECK(buf); |
200 user_buffer_ = new DrainableIOBuffer(buf, buf_len); | 200 user_buffer_ = new DrainableIOBuffer(buf, buf_len); |
201 int result = PopulateUserReadBuffer(); | 201 int result = PopulateUserReadBuffer(); |
202 if (result == 0) { | 202 if (result == 0) { |
203 DCHECK(!callback.is_null()); | 203 DCHECK(!callback.is_null()); |
204 read_callback_ = callback; | 204 read_callback_ = callback; |
205 return ERR_IO_PENDING; | 205 return ERR_IO_PENDING; |
206 } | 206 } |
207 user_buffer_ = NULL; | 207 user_buffer_ = NULL; |
208 return result; | 208 return result; |
209 } | 209 } |
210 | 210 |
211 int SpdyProxyClientSocket::PopulateUserReadBuffer() { | 211 int SpdyProxyClientSocket::PopulateUserReadBuffer() { |
212 if (!user_buffer_) | 212 if (!user_buffer_.get()) |
213 return ERR_IO_PENDING; | 213 return ERR_IO_PENDING; |
214 | 214 |
215 int bytes_read = 0; | 215 int bytes_read = 0; |
216 while (!read_buffer_.empty() && user_buffer_->BytesRemaining() > 0) { | 216 while (!read_buffer_.empty() && user_buffer_->BytesRemaining() > 0) { |
217 scoped_refptr<DrainableIOBuffer> data = read_buffer_.front(); | 217 scoped_refptr<DrainableIOBuffer> data = read_buffer_.front(); |
218 const int bytes_to_copy = std::min(user_buffer_->BytesRemaining(), | 218 const int bytes_to_copy = std::min(user_buffer_->BytesRemaining(), |
219 data->BytesRemaining()); | 219 data->BytesRemaining()); |
220 memcpy(user_buffer_->data(), data->data(), bytes_to_copy); | 220 memcpy(user_buffer_->data(), data->data(), bytes_to_copy); |
221 user_buffer_->DidConsume(bytes_to_copy); | 221 user_buffer_->DidConsume(bytes_to_copy); |
222 bytes_read += bytes_to_copy; | 222 bytes_read += bytes_to_copy; |
223 if (data->BytesRemaining() == bytes_to_copy) { | 223 if (data->BytesRemaining() == bytes_to_copy) { |
224 // Consumed all data from this buffer | 224 // Consumed all data from this buffer |
225 read_buffer_.pop_front(); | 225 read_buffer_.pop_front(); |
226 } else { | 226 } else { |
227 data->DidConsume(bytes_to_copy); | 227 data->DidConsume(bytes_to_copy); |
228 } | 228 } |
229 } | 229 } |
230 | 230 |
231 if (bytes_read > 0 && spdy_stream_) | 231 if (bytes_read > 0 && spdy_stream_.get()) |
232 spdy_stream_->IncreaseRecvWindowSize(bytes_read); | 232 spdy_stream_->IncreaseRecvWindowSize(bytes_read); |
233 | 233 |
234 return user_buffer_->BytesConsumed(); | 234 return user_buffer_->BytesConsumed(); |
235 } | 235 } |
236 | 236 |
237 int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, | 237 int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, |
238 const CompletionCallback& callback) { | 238 const CompletionCallback& callback) { |
239 DCHECK(write_callback_.is_null()); | 239 DCHECK(write_callback_.is_null()); |
240 if (next_state_ != STATE_OPEN) | 240 if (next_state_ != STATE_OPEN) |
241 return ERR_SOCKET_NOT_CONNECTED; | 241 return ERR_SOCKET_NOT_CONNECTED; |
242 | 242 |
243 DCHECK(spdy_stream_); | 243 DCHECK(spdy_stream_); |
244 write_bytes_outstanding_= buf_len; | 244 write_bytes_outstanding_= buf_len; |
245 if (buf_len <= kMaxSpdyFrameChunkSize) { | 245 if (buf_len <= kMaxSpdyFrameChunkSize) { |
246 int rv = spdy_stream_->WriteStreamData(buf, buf_len, DATA_FLAG_NONE); | 246 int rv = spdy_stream_->WriteStreamData(buf, buf_len, DATA_FLAG_NONE); |
247 if (rv == ERR_IO_PENDING) { | 247 if (rv == ERR_IO_PENDING) { |
248 write_callback_ = callback; | 248 write_callback_ = callback; |
249 write_buffer_len_ = buf_len; | 249 write_buffer_len_ = buf_len; |
250 } | 250 } |
251 return rv; | 251 return rv; |
252 } | 252 } |
253 | 253 |
254 // Since a SPDY Data frame can only include kMaxSpdyFrameChunkSize bytes | 254 // Since a SPDY Data frame can only include kMaxSpdyFrameChunkSize bytes |
255 // we need to send multiple data frames | 255 // we need to send multiple data frames |
256 for (int i = 0; i < buf_len; i += kMaxSpdyFrameChunkSize) { | 256 for (int i = 0; i < buf_len; i += kMaxSpdyFrameChunkSize) { |
257 int len = std::min(kMaxSpdyFrameChunkSize, buf_len - i); | 257 int len = std::min(kMaxSpdyFrameChunkSize, buf_len - i); |
258 scoped_refptr<DrainableIOBuffer> iobuf(new DrainableIOBuffer(buf, i + len)); | 258 scoped_refptr<DrainableIOBuffer> iobuf(new DrainableIOBuffer(buf, i + len)); |
259 iobuf->SetOffset(i); | 259 iobuf->SetOffset(i); |
260 int rv = spdy_stream_->WriteStreamData(iobuf, len, DATA_FLAG_NONE); | 260 int rv = spdy_stream_->WriteStreamData(iobuf.get(), len, DATA_FLAG_NONE); |
261 if (rv > 0) { | 261 if (rv > 0) { |
262 write_bytes_outstanding_ -= rv; | 262 write_bytes_outstanding_ -= rv; |
263 } else if (rv != ERR_IO_PENDING) { | 263 } else if (rv != ERR_IO_PENDING) { |
264 return rv; | 264 return rv; |
265 } | 265 } |
266 } | 266 } |
267 if (write_bytes_outstanding_ > 0) { | 267 if (write_bytes_outstanding_ > 0) { |
268 write_callback_ = callback; | 268 write_callback_ = callback; |
269 write_buffer_len_ = buf_len; | 269 write_buffer_len_ = buf_len; |
270 return ERR_IO_PENDING; | 270 return ERR_IO_PENDING; |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 return OK; | 436 return OK; |
437 | 437 |
438 case 302: // Found / Moved Temporarily | 438 case 302: // Found / Moved Temporarily |
439 // Try to return a sanitized response so we can follow auth redirects. | 439 // Try to return a sanitized response so we can follow auth redirects. |
440 // If we can't, fail the tunnel connection. | 440 // If we can't, fail the tunnel connection. |
441 if (SanitizeProxyRedirect(&response_, request_.url)) { | 441 if (SanitizeProxyRedirect(&response_, request_.url)) { |
442 // Immediately hand off our SpdyStream to a newly created | 442 // Immediately hand off our SpdyStream to a newly created |
443 // SpdyHttpStream so that any subsequent SpdyFrames are processed in | 443 // SpdyHttpStream so that any subsequent SpdyFrames are processed in |
444 // the context of the HttpStream, not the socket. | 444 // the context of the HttpStream, not the socket. |
445 DCHECK(spdy_stream_); | 445 DCHECK(spdy_stream_); |
446 SpdyStream* stream = spdy_stream_; | 446 SpdyStream* stream = spdy_stream_.get(); |
447 spdy_stream_ = NULL; | 447 spdy_stream_ = NULL; |
448 response_stream_.reset(new SpdyHttpStream(NULL, false)); | 448 response_stream_.reset(new SpdyHttpStream(NULL, false)); |
449 response_stream_->InitializeWithExistingStream(stream); | 449 response_stream_->InitializeWithExistingStream(stream); |
450 next_state_ = STATE_DISCONNECTED; | 450 next_state_ = STATE_DISCONNECTED; |
451 return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; | 451 return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; |
452 } else { | 452 } else { |
453 LogBlockedTunnelResponse(); | 453 LogBlockedTunnelResponse(); |
454 return ERR_TUNNEL_CONNECTION_FAILED; | 454 return ERR_TUNNEL_CONNECTION_FAILED; |
455 } | 455 } |
456 | 456 |
457 case 407: // Proxy Authentication Required | 457 case 407: // Proxy Authentication Required |
458 next_state_ = STATE_OPEN; | 458 next_state_ = STATE_OPEN; |
459 return HandleProxyAuthChallenge(auth_, &response_, net_log_); | 459 return HandleProxyAuthChallenge(auth_.get(), &response_, net_log_); |
460 | 460 |
461 default: | 461 default: |
462 // Ignore response to avoid letting the proxy impersonate the target | 462 // Ignore response to avoid letting the proxy impersonate the target |
463 // server. (See http://crbug.com/137891.) | 463 // server. (See http://crbug.com/137891.) |
464 LogBlockedTunnelResponse(); | 464 LogBlockedTunnelResponse(); |
465 return ERR_TUNNEL_CONNECTION_FAILED; | 465 return ERR_TUNNEL_CONNECTION_FAILED; |
466 } | 466 } |
467 } | 467 } |
468 | 468 |
469 // SpdyStream::Delegate methods: | 469 // SpdyStream::Delegate methods: |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 NOTREACHED(); | 517 NOTREACHED(); |
518 } | 518 } |
519 | 519 |
520 // Called when data is received. | 520 // Called when data is received. |
521 int SpdyProxyClientSocket::OnDataReceived(const char* data, int length) { | 521 int SpdyProxyClientSocket::OnDataReceived(const char* data, int length) { |
522 if (length > 0) { | 522 if (length > 0) { |
523 // Save the received data. | 523 // Save the received data. |
524 scoped_refptr<IOBuffer> io_buffer(new IOBuffer(length)); | 524 scoped_refptr<IOBuffer> io_buffer(new IOBuffer(length)); |
525 memcpy(io_buffer->data(), data, length); | 525 memcpy(io_buffer->data(), data, length); |
526 read_buffer_.push_back( | 526 read_buffer_.push_back( |
527 make_scoped_refptr(new DrainableIOBuffer(io_buffer, length))); | 527 make_scoped_refptr(new DrainableIOBuffer(io_buffer.get(), length))); |
528 } | 528 } |
529 | 529 |
530 if (!read_callback_.is_null()) { | 530 if (!read_callback_.is_null()) { |
531 int rv = PopulateUserReadBuffer(); | 531 int rv = PopulateUserReadBuffer(); |
532 CompletionCallback c = read_callback_; | 532 CompletionCallback c = read_callback_; |
533 read_callback_.Reset(); | 533 read_callback_.Reset(); |
534 user_buffer_ = NULL; | 534 user_buffer_ = NULL; |
535 c.Run(rv); | 535 c.Run(rv); |
536 } | 536 } |
537 return OK; | 537 return OK; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 } else if (!read_callback_.is_null()) { | 582 } else if (!read_callback_.is_null()) { |
583 // If we have a read_callback_, the we need to make sure we call it back. | 583 // If we have a read_callback_, the we need to make sure we call it back. |
584 OnDataReceived(NULL, 0); | 584 OnDataReceived(NULL, 0); |
585 } | 585 } |
586 // This may have been deleted by read_callback_, so check first. | 586 // This may have been deleted by read_callback_, so check first. |
587 if (weak_ptr && !write_callback.is_null()) | 587 if (weak_ptr && !write_callback.is_null()) |
588 write_callback.Run(ERR_CONNECTION_CLOSED); | 588 write_callback.Run(ERR_CONNECTION_CLOSED); |
589 } | 589 } |
590 | 590 |
591 } // namespace net | 591 } // namespace net |
OLD | NEW |