| 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 21 matching lines...) Expand all Loading... |
| 32 HttpAuthCache* auth_cache, | 32 HttpAuthCache* auth_cache, |
| 33 HttpAuthHandlerFactory* auth_handler_factory) | 33 HttpAuthHandlerFactory* auth_handler_factory) |
| 34 : next_state_(STATE_DISCONNECTED), | 34 : next_state_(STATE_DISCONNECTED), |
| 35 spdy_stream_(spdy_stream), | 35 spdy_stream_(spdy_stream), |
| 36 endpoint_(endpoint), | 36 endpoint_(endpoint), |
| 37 auth_( | 37 auth_( |
| 38 new HttpAuthController(HttpAuth::AUTH_PROXY, | 38 new HttpAuthController(HttpAuth::AUTH_PROXY, |
| 39 GURL("https://" + proxy_server.ToString()), | 39 GURL("https://" + proxy_server.ToString()), |
| 40 auth_cache, | 40 auth_cache, |
| 41 auth_handler_factory)), | 41 auth_handler_factory)), |
| 42 user_buffer_(NULL), | 42 user_buffer_len_(0), |
| 43 write_buffer_len_(0), | 43 write_buffer_len_(0), |
| 44 write_bytes_outstanding_(0), | 44 write_bytes_outstanding_(0), |
| 45 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 45 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| 46 net_log_(BoundNetLog::Make(spdy_stream->net_log().net_log(), | 46 net_log_(BoundNetLog::Make(spdy_stream->net_log().net_log(), |
| 47 NetLog::SOURCE_PROXY_CLIENT_SOCKET)) { | 47 NetLog::SOURCE_PROXY_CLIENT_SOCKET)) { |
| 48 request_.method = "CONNECT"; | 48 request_.method = "CONNECT"; |
| 49 request_.url = url; | 49 request_.url = url; |
| 50 if (!user_agent.empty()) | 50 if (!user_agent.empty()) |
| 51 request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, | 51 request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, |
| 52 user_agent); | 52 user_agent); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 DCHECK_EQ(STATE_DISCONNECTED, next_state_); | 120 DCHECK_EQ(STATE_DISCONNECTED, next_state_); |
| 121 next_state_ = STATE_GENERATE_AUTH_TOKEN; | 121 next_state_ = STATE_GENERATE_AUTH_TOKEN; |
| 122 | 122 |
| 123 int rv = DoLoop(OK); | 123 int rv = DoLoop(OK); |
| 124 if (rv == ERR_IO_PENDING) | 124 if (rv == ERR_IO_PENDING) |
| 125 read_callback_ = callback; | 125 read_callback_ = callback; |
| 126 return rv; | 126 return rv; |
| 127 } | 127 } |
| 128 | 128 |
| 129 void SpdyProxyClientSocket::Disconnect() { | 129 void SpdyProxyClientSocket::Disconnect() { |
| 130 read_buffer_.clear(); | 130 read_buffer_queue_.Clear(); |
| 131 user_buffer_ = NULL; | 131 user_buffer_ = NULL; |
| 132 user_buffer_len_ = 0; |
| 132 read_callback_.Reset(); | 133 read_callback_.Reset(); |
| 133 | 134 |
| 134 write_buffer_len_ = 0; | 135 write_buffer_len_ = 0; |
| 135 write_bytes_outstanding_ = 0; | 136 write_bytes_outstanding_ = 0; |
| 136 write_callback_.Reset(); | 137 write_callback_.Reset(); |
| 137 | 138 |
| 138 next_state_ = STATE_DISCONNECTED; | 139 next_state_ = STATE_DISCONNECTED; |
| 139 | 140 |
| 140 if (spdy_stream_) { | 141 if (spdy_stream_) { |
| 141 // This will cause OnClose to be invoked, which takes care of | 142 // This will cause OnClose to be invoked, which takes care of |
| 142 // cleaning up all the internal state. | 143 // cleaning up all the internal state. |
| 143 spdy_stream_->Cancel(); | 144 spdy_stream_->Cancel(); |
| 144 DCHECK(!spdy_stream_.get()); | 145 DCHECK(!spdy_stream_.get()); |
| 145 } | 146 } |
| 146 } | 147 } |
| 147 | 148 |
| 148 bool SpdyProxyClientSocket::IsConnected() const { | 149 bool SpdyProxyClientSocket::IsConnected() const { |
| 149 return next_state_ == STATE_OPEN; | 150 return next_state_ == STATE_OPEN; |
| 150 } | 151 } |
| 151 | 152 |
| 152 bool SpdyProxyClientSocket::IsConnectedAndIdle() const { | 153 bool SpdyProxyClientSocket::IsConnectedAndIdle() const { |
| 153 return IsConnected() && read_buffer_.empty() && spdy_stream_->is_idle(); | 154 return IsConnected() && read_buffer_queue_.IsEmpty() && |
| 155 spdy_stream_->is_idle(); |
| 154 } | 156 } |
| 155 | 157 |
| 156 const BoundNetLog& SpdyProxyClientSocket::NetLog() const { | 158 const BoundNetLog& SpdyProxyClientSocket::NetLog() const { |
| 157 return net_log_; | 159 return net_log_; |
| 158 } | 160 } |
| 159 | 161 |
| 160 void SpdyProxyClientSocket::SetSubresourceSpeculation() { | 162 void SpdyProxyClientSocket::SetSubresourceSpeculation() { |
| 161 // TODO(rch): what should this implementation be? | 163 // TODO(rch): what should this implementation be? |
| 162 } | 164 } |
| 163 | 165 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 189 } | 191 } |
| 190 | 192 |
| 191 int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, | 193 int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, |
| 192 const CompletionCallback& callback) { | 194 const CompletionCallback& callback) { |
| 193 DCHECK(read_callback_.is_null()); | 195 DCHECK(read_callback_.is_null()); |
| 194 DCHECK(!user_buffer_); | 196 DCHECK(!user_buffer_); |
| 195 | 197 |
| 196 if (next_state_ == STATE_DISCONNECTED) | 198 if (next_state_ == STATE_DISCONNECTED) |
| 197 return ERR_SOCKET_NOT_CONNECTED; | 199 return ERR_SOCKET_NOT_CONNECTED; |
| 198 | 200 |
| 199 if (next_state_ == STATE_CLOSED && read_buffer_.empty()) { | 201 if (next_state_ == STATE_CLOSED && read_buffer_queue_.IsEmpty()) { |
| 200 return 0; | 202 return 0; |
| 201 } | 203 } |
| 202 | 204 |
| 203 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); | 205 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); |
| 204 DCHECK(buf); | 206 DCHECK(buf); |
| 205 user_buffer_ = new DrainableIOBuffer(buf, buf_len); | 207 size_t result = PopulateUserReadBuffer(buf->data(), buf_len); |
| 206 int result = PopulateUserReadBuffer(); | |
| 207 if (result == 0) { | 208 if (result == 0) { |
| 209 user_buffer_ = buf; |
| 210 user_buffer_len_ = static_cast<size_t>(buf_len); |
| 208 DCHECK(!callback.is_null()); | 211 DCHECK(!callback.is_null()); |
| 209 read_callback_ = callback; | 212 read_callback_ = callback; |
| 210 return ERR_IO_PENDING; | 213 return ERR_IO_PENDING; |
| 211 } | 214 } |
| 212 user_buffer_ = NULL; | 215 user_buffer_ = NULL; |
| 213 return result; | 216 return result; |
| 214 } | 217 } |
| 215 | 218 |
| 216 int SpdyProxyClientSocket::PopulateUserReadBuffer() { | 219 size_t SpdyProxyClientSocket::PopulateUserReadBuffer(char* data, size_t len) { |
| 217 if (!user_buffer_) | 220 size_t bytes_consumed = read_buffer_queue_.Dequeue(data, len); |
| 218 return ERR_IO_PENDING; | |
| 219 | 221 |
| 220 int bytes_read = 0; | 222 if (bytes_consumed > 0 && spdy_stream_) |
| 221 while (!read_buffer_.empty() && user_buffer_->BytesRemaining() > 0) { | 223 spdy_stream_->IncreaseRecvWindowSize(bytes_consumed); |
| 222 scoped_refptr<DrainableIOBuffer> data = read_buffer_.front(); | |
| 223 const int bytes_to_copy = std::min(user_buffer_->BytesRemaining(), | |
| 224 data->BytesRemaining()); | |
| 225 memcpy(user_buffer_->data(), data->data(), bytes_to_copy); | |
| 226 user_buffer_->DidConsume(bytes_to_copy); | |
| 227 bytes_read += bytes_to_copy; | |
| 228 if (data->BytesRemaining() == bytes_to_copy) { | |
| 229 // Consumed all data from this buffer | |
| 230 read_buffer_.pop_front(); | |
| 231 } else { | |
| 232 data->DidConsume(bytes_to_copy); | |
| 233 } | |
| 234 } | |
| 235 | 224 |
| 236 if (bytes_read > 0 && spdy_stream_) | 225 return bytes_consumed; |
| 237 spdy_stream_->IncreaseRecvWindowSize(bytes_read); | |
| 238 | |
| 239 return user_buffer_->BytesConsumed(); | |
| 240 } | 226 } |
| 241 | 227 |
| 242 int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, | 228 int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, |
| 243 const CompletionCallback& callback) { | 229 const CompletionCallback& callback) { |
| 244 DCHECK(write_callback_.is_null()); | 230 DCHECK(write_callback_.is_null()); |
| 245 if (next_state_ != STATE_OPEN) | 231 if (next_state_ != STATE_OPEN) |
| 246 return ERR_SOCKET_NOT_CONNECTED; | 232 return ERR_SOCKET_NOT_CONNECTED; |
| 247 | 233 |
| 248 DCHECK(spdy_stream_); | 234 DCHECK(spdy_stream_); |
| 249 write_bytes_outstanding_= buf_len; | 235 write_bytes_outstanding_= buf_len; |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 | 505 |
| 520 OnIOComplete(status); | 506 OnIOComplete(status); |
| 521 return OK; | 507 return OK; |
| 522 } | 508 } |
| 523 | 509 |
| 524 void SpdyProxyClientSocket::OnHeadersSent() { | 510 void SpdyProxyClientSocket::OnHeadersSent() { |
| 525 // Proxy client sockets don't send any HEADERS frame. | 511 // Proxy client sockets don't send any HEADERS frame. |
| 526 NOTREACHED(); | 512 NOTREACHED(); |
| 527 } | 513 } |
| 528 | 514 |
| 529 // Called when data is received. | 515 // Called when data is received or on EOF (if |buffer| is NULL). |
| 530 int SpdyProxyClientSocket::OnDataReceived(const char* data, int length) { | 516 int SpdyProxyClientSocket::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { |
| 531 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, | 517 if (buffer) { |
| 532 length, data); | 518 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, |
| 533 if (length > 0) { | 519 buffer->GetRemainingSize(), |
| 534 // Save the received data. | 520 buffer->GetRemainingData()); |
| 535 scoped_refptr<IOBuffer> io_buffer(new IOBuffer(length)); | 521 read_buffer_queue_.Enqueue(buffer.Pass()); |
| 536 memcpy(io_buffer->data(), data, length); | 522 } else { |
| 537 read_buffer_.push_back( | 523 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, 0, NULL); |
| 538 make_scoped_refptr(new DrainableIOBuffer(io_buffer, length))); | |
| 539 } | 524 } |
| 540 | 525 |
| 541 if (!read_callback_.is_null()) { | 526 if (!read_callback_.is_null()) { |
| 542 int rv = PopulateUserReadBuffer(); | 527 int rv = PopulateUserReadBuffer(user_buffer_->data(), user_buffer_len_); |
| 543 CompletionCallback c = read_callback_; | 528 CompletionCallback c = read_callback_; |
| 544 read_callback_.Reset(); | 529 read_callback_.Reset(); |
| 545 user_buffer_ = NULL; | 530 user_buffer_ = NULL; |
| 531 user_buffer_len_ = 0; |
| 546 c.Run(rv); | 532 c.Run(rv); |
| 547 } | 533 } |
| 548 return OK; | 534 return OK; |
| 549 } | 535 } |
| 550 | 536 |
| 551 void SpdyProxyClientSocket::OnDataSent(size_t bytes_sent) { | 537 void SpdyProxyClientSocket::OnDataSent(size_t bytes_sent) { |
| 552 DCHECK(!write_callback_.is_null()); | 538 DCHECK(!write_callback_.is_null()); |
| 553 | 539 |
| 554 DCHECK_LE(static_cast<int>(bytes_sent), write_bytes_outstanding_); | 540 DCHECK_LE(static_cast<int>(bytes_sent), write_bytes_outstanding_); |
| 555 write_bytes_outstanding_ -= static_cast<int>(bytes_sent); | 541 write_bytes_outstanding_ -= static_cast<int>(bytes_sent); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 584 | 570 |
| 585 // If we're in the middle of connecting, we need to make sure | 571 // If we're in the middle of connecting, we need to make sure |
| 586 // we invoke the connect callback. | 572 // we invoke the connect callback. |
| 587 if (connecting) { | 573 if (connecting) { |
| 588 DCHECK(!read_callback_.is_null()); | 574 DCHECK(!read_callback_.is_null()); |
| 589 CompletionCallback read_callback = read_callback_; | 575 CompletionCallback read_callback = read_callback_; |
| 590 read_callback_.Reset(); | 576 read_callback_.Reset(); |
| 591 read_callback.Run(status); | 577 read_callback.Run(status); |
| 592 } else if (!read_callback_.is_null()) { | 578 } else if (!read_callback_.is_null()) { |
| 593 // If we have a read_callback_, the we need to make sure we call it back. | 579 // If we have a read_callback_, the we need to make sure we call it back. |
| 594 OnDataReceived(NULL, 0); | 580 OnDataReceived(scoped_ptr<SpdyBuffer>()); |
| 595 } | 581 } |
| 596 // This may have been deleted by read_callback_, so check first. | 582 // This may have been deleted by read_callback_, so check first. |
| 597 if (weak_ptr && !write_callback.is_null()) | 583 if (weak_ptr && !write_callback.is_null()) |
| 598 write_callback.Run(ERR_CONNECTION_CLOSED); | 584 write_callback.Run(ERR_CONNECTION_CLOSED); |
| 599 } | 585 } |
| 600 | 586 |
| 601 } // namespace net | 587 } // namespace net |
| OLD | NEW |