| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 const std::string& user_agent, | 26 const std::string& user_agent, |
| 27 const HostPortPair& endpoint, | 27 const HostPortPair& endpoint, |
| 28 const GURL& url, | 28 const GURL& url, |
| 29 const HostPortPair& proxy_server, | 29 const HostPortPair& proxy_server, |
| 30 HttpAuthCache* auth_cache, | 30 HttpAuthCache* auth_cache, |
| 31 HttpAuthHandlerFactory* auth_handler_factory) | 31 HttpAuthHandlerFactory* auth_handler_factory) |
| 32 : ALLOW_THIS_IN_INITIALIZER_LIST( | 32 : ALLOW_THIS_IN_INITIALIZER_LIST( |
| 33 io_callback_(this, &SpdyProxyClientSocket::OnIOComplete)), | 33 io_callback_(this, &SpdyProxyClientSocket::OnIOComplete)), |
| 34 next_state_(STATE_DISCONNECTED), | 34 next_state_(STATE_DISCONNECTED), |
| 35 spdy_stream_(spdy_stream), | 35 spdy_stream_(spdy_stream), |
| 36 old_read_callback_(NULL), | |
| 37 write_callback_(NULL), | |
| 38 endpoint_(endpoint), | 36 endpoint_(endpoint), |
| 39 auth_( | 37 auth_( |
| 40 new HttpAuthController(HttpAuth::AUTH_PROXY, | 38 new HttpAuthController(HttpAuth::AUTH_PROXY, |
| 41 GURL("https://" + proxy_server.ToString()), | 39 GURL("https://" + proxy_server.ToString()), |
| 42 auth_cache, | 40 auth_cache, |
| 43 auth_handler_factory)), | 41 auth_handler_factory)), |
| 44 user_buffer_(NULL), | 42 user_buffer_(NULL), |
| 45 write_buffer_len_(0), | 43 write_buffer_len_(0), |
| 46 write_bytes_outstanding_(0), | 44 write_bytes_outstanding_(0), |
| 47 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 45 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 // Sends a SYN_STREAM frame to the proxy with a CONNECT request | 82 // Sends a SYN_STREAM frame to the proxy with a CONNECT request |
| 85 // for the specified endpoint. Waits for the server to send back | 83 // for the specified endpoint. Waits for the server to send back |
| 86 // a SYN_REPLY frame. OK will be returned if the status is 200. | 84 // a SYN_REPLY frame. OK will be returned if the status is 200. |
| 87 // ERR_TUNNEL_CONNECTION_FAILED will be returned for any other status. | 85 // ERR_TUNNEL_CONNECTION_FAILED will be returned for any other status. |
| 88 // In any of these cases, Read() may be called to retrieve the HTTP | 86 // In any of these cases, Read() may be called to retrieve the HTTP |
| 89 // response body. Any other return values should be considered fatal. | 87 // response body. Any other return values should be considered fatal. |
| 90 // TODO(rch): handle 407 proxy auth requested correctly, perhaps | 88 // TODO(rch): handle 407 proxy auth requested correctly, perhaps |
| 91 // by creating a new stream for the subsequent request. | 89 // by creating a new stream for the subsequent request. |
| 92 // TODO(rch): create a more appropriate error code to disambiguate | 90 // TODO(rch): create a more appropriate error code to disambiguate |
| 93 // the HTTPS Proxy tunnel failure from an HTTP Proxy tunnel failure. | 91 // the HTTPS Proxy tunnel failure from an HTTP Proxy tunnel failure. |
| 94 int SpdyProxyClientSocket::Connect(OldCompletionCallback* callback) { | 92 int SpdyProxyClientSocket::Connect(const CompletionCallback& callback) { |
| 95 DCHECK(!old_read_callback_ && read_callback_.is_null()); | 93 DCHECK(read_callback_.is_null()); |
| 96 if (next_state_ == STATE_OPEN) | 94 if (next_state_ == STATE_OPEN) |
| 97 return OK; | 95 return OK; |
| 98 | 96 |
| 99 DCHECK_EQ(STATE_DISCONNECTED, next_state_); | |
| 100 next_state_ = STATE_GENERATE_AUTH_TOKEN; | |
| 101 | |
| 102 int rv = DoLoop(OK); | |
| 103 if (rv == ERR_IO_PENDING) | |
| 104 old_read_callback_ = callback; | |
| 105 return rv; | |
| 106 } | |
| 107 int SpdyProxyClientSocket::Connect(const CompletionCallback& callback) { | |
| 108 DCHECK(!old_read_callback_ && read_callback_.is_null()); | |
| 109 if (next_state_ == STATE_OPEN) | |
| 110 return OK; | |
| 111 | |
| 112 DCHECK_EQ(STATE_DISCONNECTED, next_state_); | 97 DCHECK_EQ(STATE_DISCONNECTED, next_state_); |
| 113 next_state_ = STATE_GENERATE_AUTH_TOKEN; | 98 next_state_ = STATE_GENERATE_AUTH_TOKEN; |
| 114 | 99 |
| 115 int rv = DoLoop(OK); | 100 int rv = DoLoop(OK); |
| 116 if (rv == ERR_IO_PENDING) | 101 if (rv == ERR_IO_PENDING) |
| 117 read_callback_ = callback; | 102 read_callback_ = callback; |
| 118 return rv; | 103 return rv; |
| 119 } | 104 } |
| 120 | 105 |
| 121 void SpdyProxyClientSocket::Disconnect() { | 106 void SpdyProxyClientSocket::Disconnect() { |
| 122 read_buffer_.clear(); | 107 read_buffer_.clear(); |
| 123 user_buffer_ = NULL; | 108 user_buffer_ = NULL; |
| 124 old_read_callback_ = NULL; | |
| 125 read_callback_.Reset(); | 109 read_callback_.Reset(); |
| 126 | 110 |
| 127 write_buffer_len_ = 0; | 111 write_buffer_len_ = 0; |
| 128 write_bytes_outstanding_ = 0; | 112 write_bytes_outstanding_ = 0; |
| 129 write_callback_ = NULL; | 113 write_callback_.Reset(); |
| 130 | 114 |
| 131 next_state_ = STATE_DISCONNECTED; | 115 next_state_ = STATE_DISCONNECTED; |
| 132 | 116 |
| 133 if (spdy_stream_) | 117 if (spdy_stream_) |
| 134 // This will cause OnClose to be invoked, which takes care of | 118 // This will cause OnClose to be invoked, which takes care of |
| 135 // cleaning up all the internal state. | 119 // cleaning up all the internal state. |
| 136 spdy_stream_->Cancel(); | 120 spdy_stream_->Cancel(); |
| 137 } | 121 } |
| 138 | 122 |
| 139 bool SpdyProxyClientSocket::IsConnected() const { | 123 bool SpdyProxyClientSocket::IsConnected() const { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 166 | 150 |
| 167 int64 SpdyProxyClientSocket::NumBytesRead() const { | 151 int64 SpdyProxyClientSocket::NumBytesRead() const { |
| 168 return -1; | 152 return -1; |
| 169 } | 153 } |
| 170 | 154 |
| 171 base::TimeDelta SpdyProxyClientSocket::GetConnectTimeMicros() const { | 155 base::TimeDelta SpdyProxyClientSocket::GetConnectTimeMicros() const { |
| 172 return base::TimeDelta::FromMicroseconds(-1); | 156 return base::TimeDelta::FromMicroseconds(-1); |
| 173 } | 157 } |
| 174 | 158 |
| 175 int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, | 159 int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, |
| 176 OldCompletionCallback* callback) { | 160 const CompletionCallback& callback) { |
| 177 DCHECK(!old_read_callback_ && read_callback_.is_null()); | 161 DCHECK(read_callback_.is_null()); |
| 178 DCHECK(!user_buffer_); | 162 DCHECK(!user_buffer_); |
| 179 | 163 |
| 180 if (next_state_ == STATE_DISCONNECTED) | 164 if (next_state_ == STATE_DISCONNECTED) |
| 181 return ERR_SOCKET_NOT_CONNECTED; | |
| 182 | |
| 183 if (next_state_ == STATE_CLOSED && read_buffer_.empty()) { | |
| 184 return 0; | |
| 185 } | |
| 186 | |
| 187 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); | |
| 188 DCHECK(buf); | |
| 189 user_buffer_ = new DrainableIOBuffer(buf, buf_len); | |
| 190 int result = PopulateUserReadBuffer(); | |
| 191 if (result == 0) { | |
| 192 DCHECK(callback); | |
| 193 old_read_callback_ = callback; | |
| 194 return ERR_IO_PENDING; | |
| 195 } | |
| 196 user_buffer_ = NULL; | |
| 197 return result; | |
| 198 } | |
| 199 int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, | |
| 200 const CompletionCallback& callback) { | |
| 201 DCHECK(!old_read_callback_ && read_callback_.is_null()); | |
| 202 DCHECK(!user_buffer_); | |
| 203 | |
| 204 if (next_state_ == STATE_DISCONNECTED) | |
| 205 return ERR_SOCKET_NOT_CONNECTED; | 165 return ERR_SOCKET_NOT_CONNECTED; |
| 206 | 166 |
| 207 if (next_state_ == STATE_CLOSED && read_buffer_.empty()) { | 167 if (next_state_ == STATE_CLOSED && read_buffer_.empty()) { |
| 208 return 0; | 168 return 0; |
| 209 } | 169 } |
| 210 | 170 |
| 211 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); | 171 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); |
| 212 DCHECK(buf); | 172 DCHECK(buf); |
| 213 user_buffer_ = new DrainableIOBuffer(buf, buf_len); | 173 user_buffer_ = new DrainableIOBuffer(buf, buf_len); |
| 214 int result = PopulateUserReadBuffer(); | 174 int result = PopulateUserReadBuffer(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 236 read_buffer_.pop_front(); | 196 read_buffer_.pop_front(); |
| 237 } else { | 197 } else { |
| 238 data->DidConsume(bytes_to_copy); | 198 data->DidConsume(bytes_to_copy); |
| 239 } | 199 } |
| 240 } | 200 } |
| 241 | 201 |
| 242 return user_buffer_->BytesConsumed(); | 202 return user_buffer_->BytesConsumed(); |
| 243 } | 203 } |
| 244 | 204 |
| 245 int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, | 205 int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, |
| 246 OldCompletionCallback* callback) { | 206 const CompletionCallback& callback) { |
| 247 DCHECK(!write_callback_); | 207 DCHECK(write_callback_.is_null()); |
| 248 if (next_state_ != STATE_OPEN) | 208 if (next_state_ != STATE_OPEN) |
| 249 return ERR_SOCKET_NOT_CONNECTED; | 209 return ERR_SOCKET_NOT_CONNECTED; |
| 250 | 210 |
| 251 DCHECK(spdy_stream_); | 211 DCHECK(spdy_stream_); |
| 252 write_bytes_outstanding_= buf_len; | 212 write_bytes_outstanding_= buf_len; |
| 253 if (buf_len <= kMaxSpdyFrameChunkSize) { | 213 if (buf_len <= kMaxSpdyFrameChunkSize) { |
| 254 int rv = spdy_stream_->WriteStreamData(buf, buf_len, spdy::DATA_FLAG_NONE); | 214 int rv = spdy_stream_->WriteStreamData(buf, buf_len, spdy::DATA_FLAG_NONE); |
| 255 if (rv == ERR_IO_PENDING) { | 215 if (rv == ERR_IO_PENDING) { |
| 256 write_callback_ = callback; | 216 write_callback_ = callback; |
| 257 write_buffer_len_ = buf_len; | 217 write_buffer_len_ = buf_len; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 int SpdyProxyClientSocket::GetLocalAddress(IPEndPoint* address) const { | 262 int SpdyProxyClientSocket::GetLocalAddress(IPEndPoint* address) const { |
| 303 if (!IsConnected()) | 263 if (!IsConnected()) |
| 304 return ERR_SOCKET_NOT_CONNECTED; | 264 return ERR_SOCKET_NOT_CONNECTED; |
| 305 return spdy_stream_->GetLocalAddress(address); | 265 return spdy_stream_->GetLocalAddress(address); |
| 306 } | 266 } |
| 307 | 267 |
| 308 void SpdyProxyClientSocket::OnIOComplete(int result) { | 268 void SpdyProxyClientSocket::OnIOComplete(int result) { |
| 309 DCHECK_NE(STATE_DISCONNECTED, next_state_); | 269 DCHECK_NE(STATE_DISCONNECTED, next_state_); |
| 310 int rv = DoLoop(result); | 270 int rv = DoLoop(result); |
| 311 if (rv != ERR_IO_PENDING) { | 271 if (rv != ERR_IO_PENDING) { |
| 312 if (old_read_callback_) { | 272 CompletionCallback c = read_callback_; |
| 313 OldCompletionCallback* c = old_read_callback_; | 273 read_callback_.Reset(); |
| 314 old_read_callback_ = NULL; | 274 c.Run(rv); |
| 315 c->Run(rv); | |
| 316 } else { | |
| 317 CompletionCallback c = read_callback_; | |
| 318 read_callback_.Reset(); | |
| 319 c.Run(rv); | |
| 320 } | |
| 321 } | 275 } |
| 322 } | 276 } |
| 323 | 277 |
| 324 int SpdyProxyClientSocket::DoLoop(int last_io_result) { | 278 int SpdyProxyClientSocket::DoLoop(int last_io_result) { |
| 325 DCHECK_NE(next_state_, STATE_DISCONNECTED); | 279 DCHECK_NE(next_state_, STATE_DISCONNECTED); |
| 326 int rv = last_io_result; | 280 int rv = last_io_result; |
| 327 do { | 281 do { |
| 328 State state = next_state_; | 282 State state = next_state_; |
| 329 next_state_ = STATE_DISCONNECTED; | 283 next_state_ = STATE_DISCONNECTED; |
| 330 switch (state) { | 284 switch (state) { |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 // Called when data is received. | 463 // Called when data is received. |
| 510 void SpdyProxyClientSocket::OnDataReceived(const char* data, int length) { | 464 void SpdyProxyClientSocket::OnDataReceived(const char* data, int length) { |
| 511 if (length > 0) { | 465 if (length > 0) { |
| 512 // Save the received data. | 466 // Save the received data. |
| 513 scoped_refptr<IOBuffer> io_buffer(new IOBuffer(length)); | 467 scoped_refptr<IOBuffer> io_buffer(new IOBuffer(length)); |
| 514 memcpy(io_buffer->data(), data, length); | 468 memcpy(io_buffer->data(), data, length); |
| 515 read_buffer_.push_back( | 469 read_buffer_.push_back( |
| 516 make_scoped_refptr(new DrainableIOBuffer(io_buffer, length))); | 470 make_scoped_refptr(new DrainableIOBuffer(io_buffer, length))); |
| 517 } | 471 } |
| 518 | 472 |
| 519 if (old_read_callback_) { | 473 if (!read_callback_.is_null()) { |
| 520 int rv = PopulateUserReadBuffer(); | |
| 521 OldCompletionCallback* c = old_read_callback_; | |
| 522 old_read_callback_ = NULL; | |
| 523 user_buffer_ = NULL; | |
| 524 c->Run(rv); | |
| 525 } else if (!read_callback_.is_null()) { | |
| 526 int rv = PopulateUserReadBuffer(); | 474 int rv = PopulateUserReadBuffer(); |
| 527 CompletionCallback c = read_callback_; | 475 CompletionCallback c = read_callback_; |
| 528 read_callback_.Reset(); | 476 read_callback_.Reset(); |
| 529 user_buffer_ = NULL; | 477 user_buffer_ = NULL; |
| 530 c.Run(rv); | 478 c.Run(rv); |
| 531 } | 479 } |
| 532 } | 480 } |
| 533 | 481 |
| 534 void SpdyProxyClientSocket::OnDataSent(int length) { | 482 void SpdyProxyClientSocket::OnDataSent(int length) { |
| 535 DCHECK(write_callback_); | 483 DCHECK(!write_callback_.is_null()); |
| 536 | 484 |
| 537 write_bytes_outstanding_ -= length; | 485 write_bytes_outstanding_ -= length; |
| 538 | 486 |
| 539 DCHECK_GE(write_bytes_outstanding_, 0); | 487 DCHECK_GE(write_bytes_outstanding_, 0); |
| 540 | 488 |
| 541 if (write_bytes_outstanding_ == 0) { | 489 if (write_bytes_outstanding_ == 0) { |
| 542 int rv = write_buffer_len_; | 490 int rv = write_buffer_len_; |
| 543 write_buffer_len_ = 0; | 491 write_buffer_len_ = 0; |
| 544 write_bytes_outstanding_ = 0; | 492 write_bytes_outstanding_ = 0; |
| 545 OldCompletionCallback* c = write_callback_; | 493 CompletionCallback c = write_callback_; |
| 546 write_callback_ = NULL; | 494 write_callback_.Reset(); |
| 547 c->Run(rv); | 495 c.Run(rv); |
| 548 } | 496 } |
| 549 } | 497 } |
| 550 | 498 |
| 551 void SpdyProxyClientSocket::OnClose(int status) { | 499 void SpdyProxyClientSocket::OnClose(int status) { |
| 552 DCHECK(spdy_stream_); | 500 DCHECK(spdy_stream_); |
| 553 was_ever_used_ = spdy_stream_->WasEverUsed(); | 501 was_ever_used_ = spdy_stream_->WasEverUsed(); |
| 554 spdy_stream_ = NULL; | 502 spdy_stream_ = NULL; |
| 555 | 503 |
| 556 bool connecting = next_state_ != STATE_DISCONNECTED && | 504 bool connecting = next_state_ != STATE_DISCONNECTED && |
| 557 next_state_ < STATE_OPEN; | 505 next_state_ < STATE_OPEN; |
| 558 if (next_state_ == STATE_OPEN) | 506 if (next_state_ == STATE_OPEN) |
| 559 next_state_ = STATE_CLOSED; | 507 next_state_ = STATE_CLOSED; |
| 560 else | 508 else |
| 561 next_state_ = STATE_DISCONNECTED; | 509 next_state_ = STATE_DISCONNECTED; |
| 562 | 510 |
| 563 base::WeakPtr<SpdyProxyClientSocket> weak_ptr = weak_factory_.GetWeakPtr(); | 511 base::WeakPtr<SpdyProxyClientSocket> weak_ptr = weak_factory_.GetWeakPtr(); |
| 564 OldCompletionCallback* write_callback = write_callback_; | 512 CompletionCallback write_callback = write_callback_; |
| 565 write_callback_ = NULL; | 513 write_callback_.Reset(); |
| 566 write_buffer_len_ = 0; | 514 write_buffer_len_ = 0; |
| 567 write_bytes_outstanding_ = 0; | 515 write_bytes_outstanding_ = 0; |
| 568 | 516 |
| 569 // If we're in the middle of connecting, we need to make sure | 517 // If we're in the middle of connecting, we need to make sure |
| 570 // we invoke the connect callback. | 518 // we invoke the connect callback. |
| 571 if (connecting) { | 519 if (connecting) { |
| 572 DCHECK(old_read_callback_ || !read_callback_.is_null()); | 520 DCHECK(!read_callback_.is_null()); |
| 573 if (old_read_callback_) { | 521 CompletionCallback read_callback = read_callback_; |
| 574 OldCompletionCallback* read_callback = old_read_callback_; | 522 read_callback_.Reset(); |
| 575 old_read_callback_ = NULL; | 523 read_callback.Run(status); |
| 576 read_callback->Run(status); | 524 } else if (!read_callback_.is_null()) { |
| 577 } else { | |
| 578 CompletionCallback read_callback = read_callback_; | |
| 579 read_callback_.Reset(); | |
| 580 read_callback.Run(status); | |
| 581 } | |
| 582 } else if (old_read_callback_ || !read_callback_.is_null()) { | |
| 583 // If we have a read_callback_, the we need to make sure we call it back. | 525 // If we have a read_callback_, the we need to make sure we call it back. |
| 584 OnDataReceived(NULL, 0); | 526 OnDataReceived(NULL, 0); |
| 585 } | 527 } |
| 586 // This may have been deleted by read_callback_, so check first. | 528 // This may have been deleted by read_callback_, so check first. |
| 587 if (weak_ptr && write_callback) | 529 if (weak_ptr && !write_callback.is_null()) |
| 588 write_callback->Run(ERR_CONNECTION_CLOSED); | 530 write_callback.Run(ERR_CONNECTION_CLOSED); |
| 589 } | 531 } |
| 590 | 532 |
| 591 void SpdyProxyClientSocket::set_chunk_callback(ChunkCallback* /*callback*/) { | 533 void SpdyProxyClientSocket::set_chunk_callback(ChunkCallback* /*callback*/) { |
| 592 } | 534 } |
| 593 | 535 |
| 594 } // namespace net | 536 } // namespace net |
| OLD | NEW |