| 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 18 matching lines...) Expand all Loading... |
| 29 const std::string& user_agent, | 29 const std::string& user_agent, |
| 30 const HostPortPair& endpoint, | 30 const HostPortPair& endpoint, |
| 31 const GURL& url, | 31 const GURL& url, |
| 32 const HostPortPair& proxy_server, | 32 const HostPortPair& proxy_server, |
| 33 const BoundNetLog& source_net_log, | 33 const BoundNetLog& source_net_log, |
| 34 HttpAuthCache* auth_cache, | 34 HttpAuthCache* auth_cache, |
| 35 HttpAuthHandlerFactory* auth_handler_factory) | 35 HttpAuthHandlerFactory* auth_handler_factory) |
| 36 : next_state_(STATE_DISCONNECTED), | 36 : next_state_(STATE_DISCONNECTED), |
| 37 spdy_stream_(spdy_stream), | 37 spdy_stream_(spdy_stream), |
| 38 endpoint_(endpoint), | 38 endpoint_(endpoint), |
| 39 auth_( | 39 auth_(new HttpAuthController(HttpAuth::AUTH_PROXY, |
| 40 new HttpAuthController(HttpAuth::AUTH_PROXY, | 40 GURL("https://" + proxy_server.ToString()), |
| 41 GURL("https://" + proxy_server.ToString()), | 41 auth_cache, |
| 42 auth_cache, | 42 auth_handler_factory)), |
| 43 auth_handler_factory)), | |
| 44 user_buffer_len_(0), | 43 user_buffer_len_(0), |
| 45 write_buffer_len_(0), | 44 write_buffer_len_(0), |
| 46 was_ever_used_(false), | 45 was_ever_used_(false), |
| 47 redirect_has_load_timing_info_(false), | 46 redirect_has_load_timing_info_(false), |
| 48 weak_factory_(this), | 47 weak_factory_(this), |
| 49 net_log_(BoundNetLog::Make(spdy_stream->net_log().net_log(), | 48 net_log_(BoundNetLog::Make(spdy_stream->net_log().net_log(), |
| 50 NetLog::SOURCE_PROXY_CLIENT_SOCKET)) { | 49 NetLog::SOURCE_PROXY_CLIENT_SOCKET)) { |
| 51 request_.method = "CONNECT"; | 50 request_.method = "CONNECT"; |
| 52 request_.url = url; | 51 request_.url = url; |
| 53 if (!user_agent.empty()) | 52 if (!user_agent.empty()) |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 | 87 |
| 89 bool SpdyProxyClientSocket::IsUsingSpdy() const { | 88 bool SpdyProxyClientSocket::IsUsingSpdy() const { |
| 90 return true; | 89 return true; |
| 91 } | 90 } |
| 92 | 91 |
| 93 NextProto SpdyProxyClientSocket::GetProtocolNegotiated() const { | 92 NextProto SpdyProxyClientSocket::GetProtocolNegotiated() const { |
| 94 // Save the negotiated protocol | 93 // Save the negotiated protocol |
| 95 SSLInfo ssl_info; | 94 SSLInfo ssl_info; |
| 96 bool was_npn_negotiated; | 95 bool was_npn_negotiated; |
| 97 NextProto protocol_negotiated; | 96 NextProto protocol_negotiated; |
| 98 spdy_stream_->GetSSLInfo(&ssl_info, &was_npn_negotiated, | 97 spdy_stream_->GetSSLInfo( |
| 99 &protocol_negotiated); | 98 &ssl_info, &was_npn_negotiated, &protocol_negotiated); |
| 100 return protocol_negotiated; | 99 return protocol_negotiated; |
| 101 } | 100 } |
| 102 | 101 |
| 103 HttpStream* SpdyProxyClientSocket::CreateConnectResponseStream() { | 102 HttpStream* SpdyProxyClientSocket::CreateConnectResponseStream() { |
| 104 return new ProxyConnectRedirectHttpStream( | 103 return new ProxyConnectRedirectHttpStream( |
| 105 redirect_has_load_timing_info_ ? &redirect_load_timing_info_ : NULL); | 104 redirect_has_load_timing_info_ ? &redirect_load_timing_info_ : NULL); |
| 106 } | 105 } |
| 107 | 106 |
| 108 // Sends a SYN_STREAM frame to the proxy with a CONNECT request | 107 // Sends a SYN_STREAM frame to the proxy with a CONNECT request |
| 109 // for the specified endpoint. Waits for the server to send back | 108 // for the specified endpoint. Waits for the server to send back |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 DCHECK(!spdy_stream_.get()); | 146 DCHECK(!spdy_stream_.get()); |
| 148 } | 147 } |
| 149 } | 148 } |
| 150 | 149 |
| 151 bool SpdyProxyClientSocket::IsConnected() const { | 150 bool SpdyProxyClientSocket::IsConnected() const { |
| 152 return next_state_ == STATE_OPEN; | 151 return next_state_ == STATE_OPEN; |
| 153 } | 152 } |
| 154 | 153 |
| 155 bool SpdyProxyClientSocket::IsConnectedAndIdle() const { | 154 bool SpdyProxyClientSocket::IsConnectedAndIdle() const { |
| 156 return IsConnected() && read_buffer_queue_.IsEmpty() && | 155 return IsConnected() && read_buffer_queue_.IsEmpty() && |
| 157 spdy_stream_->IsOpen(); | 156 spdy_stream_->IsOpen(); |
| 158 } | 157 } |
| 159 | 158 |
| 160 const BoundNetLog& SpdyProxyClientSocket::NetLog() const { | 159 const BoundNetLog& SpdyProxyClientSocket::NetLog() const { |
| 161 return net_log_; | 160 return net_log_; |
| 162 } | 161 } |
| 163 | 162 |
| 164 void SpdyProxyClientSocket::SetSubresourceSpeculation() { | 163 void SpdyProxyClientSocket::SetSubresourceSpeculation() { |
| 165 // TODO(rch): what should this implementation be? | 164 // TODO(rch): what should this implementation be? |
| 166 } | 165 } |
| 167 | 166 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 181 return false; | 180 return false; |
| 182 } | 181 } |
| 183 | 182 |
| 184 NextProto SpdyProxyClientSocket::GetNegotiatedProtocol() const { | 183 NextProto SpdyProxyClientSocket::GetNegotiatedProtocol() const { |
| 185 return kProtoUnknown; | 184 return kProtoUnknown; |
| 186 } | 185 } |
| 187 | 186 |
| 188 bool SpdyProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) { | 187 bool SpdyProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) { |
| 189 bool was_npn_negotiated; | 188 bool was_npn_negotiated; |
| 190 NextProto protocol_negotiated; | 189 NextProto protocol_negotiated; |
| 191 return spdy_stream_->GetSSLInfo(ssl_info, &was_npn_negotiated, | 190 return spdy_stream_->GetSSLInfo( |
| 192 &protocol_negotiated); | 191 ssl_info, &was_npn_negotiated, &protocol_negotiated); |
| 193 } | 192 } |
| 194 | 193 |
| 195 int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, | 194 int SpdyProxyClientSocket::Read(IOBuffer* buf, |
| 195 int buf_len, |
| 196 const CompletionCallback& callback) { | 196 const CompletionCallback& callback) { |
| 197 DCHECK(read_callback_.is_null()); | 197 DCHECK(read_callback_.is_null()); |
| 198 DCHECK(!user_buffer_.get()); | 198 DCHECK(!user_buffer_.get()); |
| 199 | 199 |
| 200 if (next_state_ == STATE_DISCONNECTED) | 200 if (next_state_ == STATE_DISCONNECTED) |
| 201 return ERR_SOCKET_NOT_CONNECTED; | 201 return ERR_SOCKET_NOT_CONNECTED; |
| 202 | 202 |
| 203 if (next_state_ == STATE_CLOSED && read_buffer_queue_.IsEmpty()) { | 203 if (next_state_ == STATE_CLOSED && read_buffer_queue_.IsEmpty()) { |
| 204 return 0; | 204 return 0; |
| 205 } | 205 } |
| 206 | 206 |
| 207 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); | 207 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); |
| 208 DCHECK(buf); | 208 DCHECK(buf); |
| 209 size_t result = PopulateUserReadBuffer(buf->data(), buf_len); | 209 size_t result = PopulateUserReadBuffer(buf->data(), buf_len); |
| 210 if (result == 0) { | 210 if (result == 0) { |
| 211 user_buffer_ = buf; | 211 user_buffer_ = buf; |
| 212 user_buffer_len_ = static_cast<size_t>(buf_len); | 212 user_buffer_len_ = static_cast<size_t>(buf_len); |
| 213 DCHECK(!callback.is_null()); | 213 DCHECK(!callback.is_null()); |
| 214 read_callback_ = callback; | 214 read_callback_ = callback; |
| 215 return ERR_IO_PENDING; | 215 return ERR_IO_PENDING; |
| 216 } | 216 } |
| 217 user_buffer_ = NULL; | 217 user_buffer_ = NULL; |
| 218 return result; | 218 return result; |
| 219 } | 219 } |
| 220 | 220 |
| 221 size_t SpdyProxyClientSocket::PopulateUserReadBuffer(char* data, size_t len) { | 221 size_t SpdyProxyClientSocket::PopulateUserReadBuffer(char* data, size_t len) { |
| 222 return read_buffer_queue_.Dequeue(data, len); | 222 return read_buffer_queue_.Dequeue(data, len); |
| 223 } | 223 } |
| 224 | 224 |
| 225 int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, | 225 int SpdyProxyClientSocket::Write(IOBuffer* buf, |
| 226 int buf_len, |
| 226 const CompletionCallback& callback) { | 227 const CompletionCallback& callback) { |
| 227 DCHECK(write_callback_.is_null()); | 228 DCHECK(write_callback_.is_null()); |
| 228 if (next_state_ != STATE_OPEN) | 229 if (next_state_ != STATE_OPEN) |
| 229 return ERR_SOCKET_NOT_CONNECTED; | 230 return ERR_SOCKET_NOT_CONNECTED; |
| 230 | 231 |
| 231 DCHECK(spdy_stream_.get()); | 232 DCHECK(spdy_stream_.get()); |
| 232 spdy_stream_->SendData(buf, buf_len, MORE_DATA_TO_SEND); | 233 spdy_stream_->SendData(buf, buf_len, MORE_DATA_TO_SEND); |
| 233 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, | 234 net_log_.AddByteTransferEvent( |
| 234 buf_len, buf->data()); | 235 NetLog::TYPE_SOCKET_BYTES_SENT, buf_len, buf->data()); |
| 235 write_callback_ = callback; | 236 write_callback_ = callback; |
| 236 write_buffer_len_ = buf_len; | 237 write_buffer_len_ = buf_len; |
| 237 return ERR_IO_PENDING; | 238 return ERR_IO_PENDING; |
| 238 } | 239 } |
| 239 | 240 |
| 240 int SpdyProxyClientSocket::SetReceiveBufferSize(int32 size) { | 241 int SpdyProxyClientSocket::SetReceiveBufferSize(int32 size) { |
| 241 // Since this StreamSocket sits on top of a shared SpdySession, it | 242 // Since this StreamSocket sits on top of a shared SpdySession, it |
| 242 // is not safe for callers to change this underlying socket. | 243 // is not safe for callers to change this underlying socket. |
| 243 return ERR_NOT_IMPLEMENTED; | 244 return ERR_NOT_IMPLEMENTED; |
| 244 } | 245 } |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 next_state_ = STATE_SEND_REQUEST_COMPLETE; | 344 next_state_ = STATE_SEND_REQUEST_COMPLETE; |
| 344 | 345 |
| 345 // Add Proxy-Authentication header if necessary. | 346 // Add Proxy-Authentication header if necessary. |
| 346 HttpRequestHeaders authorization_headers; | 347 HttpRequestHeaders authorization_headers; |
| 347 if (auth_->HaveAuth()) { | 348 if (auth_->HaveAuth()) { |
| 348 auth_->AddAuthorizationHeader(&authorization_headers); | 349 auth_->AddAuthorizationHeader(&authorization_headers); |
| 349 } | 350 } |
| 350 | 351 |
| 351 std::string request_line; | 352 std::string request_line; |
| 352 HttpRequestHeaders request_headers; | 353 HttpRequestHeaders request_headers; |
| 353 BuildTunnelRequest(request_, authorization_headers, endpoint_, &request_line, | 354 BuildTunnelRequest(request_, |
| 355 authorization_headers, |
| 356 endpoint_, |
| 357 &request_line, |
| 354 &request_headers); | 358 &request_headers); |
| 355 | 359 |
| 356 net_log_.AddEvent( | 360 net_log_.AddEvent(NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, |
| 357 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, | 361 base::Bind(&HttpRequestHeaders::NetLogCallback, |
| 358 base::Bind(&HttpRequestHeaders::NetLogCallback, | 362 base::Unretained(&request_headers), |
| 359 base::Unretained(&request_headers), | 363 &request_line)); |
| 360 &request_line)); | |
| 361 | 364 |
| 362 request_.extra_headers.MergeFrom(request_headers); | 365 request_.extra_headers.MergeFrom(request_headers); |
| 363 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock()); | 366 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock()); |
| 364 CreateSpdyHeadersFromHttpRequest(request_, request_headers, headers.get(), | 367 CreateSpdyHeadersFromHttpRequest(request_, |
| 365 spdy_stream_->GetProtocolVersion(), true); | 368 request_headers, |
| 369 headers.get(), |
| 370 spdy_stream_->GetProtocolVersion(), |
| 371 true); |
| 366 // Reset the URL to be the endpoint of the connection | 372 // Reset the URL to be the endpoint of the connection |
| 367 if (spdy_stream_->GetProtocolVersion() > 2) { | 373 if (spdy_stream_->GetProtocolVersion() > 2) { |
| 368 (*headers)[":path"] = endpoint_.ToString(); | 374 (*headers)[":path"] = endpoint_.ToString(); |
| 369 headers->erase(":scheme"); | 375 headers->erase(":scheme"); |
| 370 } else { | 376 } else { |
| 371 (*headers)["url"] = endpoint_.ToString(); | 377 (*headers)["url"] = endpoint_.ToString(); |
| 372 headers->erase("scheme"); | 378 headers->erase("scheme"); |
| 373 } | 379 } |
| 374 | 380 |
| 375 return spdy_stream_->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND); | 381 return spdy_stream_->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 if (!read_callback_.is_null()) { | 476 if (!read_callback_.is_null()) { |
| 471 int rv = PopulateUserReadBuffer(user_buffer_->data(), user_buffer_len_); | 477 int rv = PopulateUserReadBuffer(user_buffer_->data(), user_buffer_len_); |
| 472 CompletionCallback c = read_callback_; | 478 CompletionCallback c = read_callback_; |
| 473 read_callback_.Reset(); | 479 read_callback_.Reset(); |
| 474 user_buffer_ = NULL; | 480 user_buffer_ = NULL; |
| 475 user_buffer_len_ = 0; | 481 user_buffer_len_ = 0; |
| 476 c.Run(rv); | 482 c.Run(rv); |
| 477 } | 483 } |
| 478 } | 484 } |
| 479 | 485 |
| 480 void SpdyProxyClientSocket::OnDataSent() { | 486 void SpdyProxyClientSocket::OnDataSent() { |
| 481 DCHECK(!write_callback_.is_null()); | 487 DCHECK(!write_callback_.is_null()); |
| 482 | 488 |
| 483 int rv = write_buffer_len_; | 489 int rv = write_buffer_len_; |
| 484 write_buffer_len_ = 0; | 490 write_buffer_len_ = 0; |
| 485 | 491 |
| 486 // Proxy write callbacks result in deep callback chains. Post to allow the | 492 // Proxy write callbacks result in deep callback chains. Post to allow the |
| 487 // stream's write callback chain to unwind (see crbug.com/355511). | 493 // stream's write callback chain to unwind (see crbug.com/355511). |
| 488 base::MessageLoop::current()->PostTask( | 494 base::MessageLoop::current()->PostTask( |
| 489 FROM_HERE, | 495 FROM_HERE, base::Bind(ResetAndReturn(&write_callback_), rv)); |
| 490 base::Bind(ResetAndReturn(&write_callback_), rv)); | |
| 491 } | 496 } |
| 492 | 497 |
| 493 void SpdyProxyClientSocket::OnClose(int status) { | 498 void SpdyProxyClientSocket::OnClose(int status) { |
| 494 was_ever_used_ = spdy_stream_->WasEverUsed(); | 499 was_ever_used_ = spdy_stream_->WasEverUsed(); |
| 495 spdy_stream_.reset(); | 500 spdy_stream_.reset(); |
| 496 | 501 |
| 497 bool connecting = next_state_ != STATE_DISCONNECTED && | 502 bool connecting = |
| 498 next_state_ < STATE_OPEN; | 503 next_state_ != STATE_DISCONNECTED && next_state_ < STATE_OPEN; |
| 499 if (next_state_ == STATE_OPEN) | 504 if (next_state_ == STATE_OPEN) |
| 500 next_state_ = STATE_CLOSED; | 505 next_state_ = STATE_CLOSED; |
| 501 else | 506 else |
| 502 next_state_ = STATE_DISCONNECTED; | 507 next_state_ = STATE_DISCONNECTED; |
| 503 | 508 |
| 504 base::WeakPtr<SpdyProxyClientSocket> weak_ptr = weak_factory_.GetWeakPtr(); | 509 base::WeakPtr<SpdyProxyClientSocket> weak_ptr = weak_factory_.GetWeakPtr(); |
| 505 CompletionCallback write_callback = write_callback_; | 510 CompletionCallback write_callback = write_callback_; |
| 506 write_callback_.Reset(); | 511 write_callback_.Reset(); |
| 507 write_buffer_len_ = 0; | 512 write_buffer_len_ = 0; |
| 508 | 513 |
| 509 // If we're in the middle of connecting, we need to make sure | 514 // If we're in the middle of connecting, we need to make sure |
| 510 // we invoke the connect callback. | 515 // we invoke the connect callback. |
| 511 if (connecting) { | 516 if (connecting) { |
| 512 DCHECK(!read_callback_.is_null()); | 517 DCHECK(!read_callback_.is_null()); |
| 513 CompletionCallback read_callback = read_callback_; | 518 CompletionCallback read_callback = read_callback_; |
| 514 read_callback_.Reset(); | 519 read_callback_.Reset(); |
| 515 read_callback.Run(status); | 520 read_callback.Run(status); |
| 516 } else if (!read_callback_.is_null()) { | 521 } else if (!read_callback_.is_null()) { |
| 517 // If we have a read_callback_, the we need to make sure we call it back. | 522 // If we have a read_callback_, the we need to make sure we call it back. |
| 518 OnDataReceived(scoped_ptr<SpdyBuffer>()); | 523 OnDataReceived(scoped_ptr<SpdyBuffer>()); |
| 519 } | 524 } |
| 520 // This may have been deleted by read_callback_, so check first. | 525 // This may have been deleted by read_callback_, so check first. |
| 521 if (weak_ptr.get() && !write_callback.is_null()) | 526 if (weak_ptr.get() && !write_callback.is_null()) |
| 522 write_callback.Run(ERR_CONNECTION_CLOSED); | 527 write_callback.Run(ERR_CONNECTION_CLOSED); |
| 523 } | 528 } |
| 524 | 529 |
| 525 } // namespace net | 530 } // namespace net |
| OLD | NEW |