spdy_proxy_client_socket.cc revision 868fa2fe829687343ffae624259930155e16dbd8
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_proxy_client_socket.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> // min 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/callback_helpers.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/auth.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth_cache.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth_handler_factory.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_http_utils.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyProxyClientSocket::SpdyProxyClientSocket( 27a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const base::WeakPtr<SpdyStream>& spdy_stream, 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& user_agent, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HostPortPair& endpoint, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HostPortPair& proxy_server, 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BoundNetLog& source_net_log, 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuthCache* auth_cache, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuthHandlerFactory* auth_handler_factory) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : next_state_(STATE_DISCONNECTED), 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_stream_(spdy_stream), 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) endpoint_(endpoint), 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_( 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new HttpAuthController(HttpAuth::AUTH_PROXY, 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL("https://" + proxy_server.ToString()), 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_cache, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_handler_factory)), 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_buffer_len_(0), 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_len_(0), 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this), 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log_(BoundNetLog::Make(spdy_stream->net_log().net_log(), 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::SOURCE_PROXY_CLIENT_SOCKET)) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.method = "CONNECT"; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.url = url; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!user_agent.empty()) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_agent); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_net_log.source().ToEventParametersCallback()); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log_.AddEvent( 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::TYPE_SPDY_PROXY_CLIENT_SESSION, 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spdy_stream->net_log().source().ToEventParametersCallback()); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_stream_->SetDelegate(this); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) was_ever_used_ = spdy_stream_->WasEverUsed(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyProxyClientSocket::~SpdyProxyClientSocket() { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Disconnect(); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const HttpResponseInfo* SpdyProxyClientSocket::GetConnectResponseInfo() const { 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return response_.headers.get() ? &response_ : NULL; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const scoped_refptr<HttpAuthController>& 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyProxyClientSocket::GetAuthController() const { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return auth_; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::RestartWithAuth(const CompletionCallback& callback) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A SPDY Stream can only handle a single request, so the underlying 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stream may not be reused and a new SpdyProxyClientSocket must be 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // created (possibly on top of the same SPDY Session). 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_DISCONNECTED; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyProxyClientSocket::IsUsingSpdy() const { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NextProto SpdyProxyClientSocket::GetProtocolNegotiated() const { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the negotiated protocol 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLInfo ssl_info; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_npn_negotiated; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NextProto protocol_negotiated; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_stream_->GetSSLInfo(&ssl_info, &was_npn_negotiated, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &protocol_negotiated); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return protocol_negotiated; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpStream* SpdyProxyClientSocket::CreateConnectResponseStream() { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(response_stream_.get()); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return response_stream_.release(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sends a SYN_STREAM frame to the proxy with a CONNECT request 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for the specified endpoint. Waits for the server to send back 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a SYN_REPLY frame. OK will be returned if the status is 200. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ERR_TUNNEL_CONNECTION_FAILED will be returned for any other status. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In any of these cases, Read() may be called to retrieve the HTTP 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// response body. Any other return values should be considered fatal. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(rch): handle 407 proxy auth requested correctly, perhaps 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by creating a new stream for the subsequent request. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(rch): create a more appropriate error code to disambiguate 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the HTTPS Proxy tunnel failure from an HTTP Proxy tunnel failure. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::Connect(const CompletionCallback& callback) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(read_callback_.is_null()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_state_ == STATE_OPEN) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(STATE_DISCONNECTED, next_state_); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GENERATE_AUTH_TOKEN; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoLoop(OK); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == ERR_IO_PENDING) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_ = callback; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyProxyClientSocket::Disconnect() { 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) read_buffer_queue_.Clear(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_buffer_ = NULL; 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_buffer_len_ = 0; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_len_ = 0; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_.Reset(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_DISCONNECTED; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (spdy_stream_.get()) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will cause OnClose to be invoked, which takes care of 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cleaning up all the internal state. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_stream_->Cancel(); 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!spdy_stream_.get()); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyProxyClientSocket::IsConnected() const { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return next_state_ == STATE_OPEN; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyProxyClientSocket::IsConnectedAndIdle() const { 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return IsConnected() && read_buffer_queue_.IsEmpty() && 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spdy_stream_->is_idle(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& SpdyProxyClientSocket::NetLog() const { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net_log_; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyProxyClientSocket::SetSubresourceSpeculation() { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rch): what should this implementation be? 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyProxyClientSocket::SetOmniboxSpeculation() { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rch): what should this implementation be? 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyProxyClientSocket::WasEverUsed() const { 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return was_ever_used_ || (spdy_stream_.get() && spdy_stream_->WasEverUsed()); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyProxyClientSocket::UsingTCPFastOpen() const { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyProxyClientSocket::WasNpnNegotiated() const { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NextProto SpdyProxyClientSocket::GetNegotiatedProtocol() const { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kProtoUnknown; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_npn_negotiated; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NextProto protocol_negotiated; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return spdy_stream_->GetSSLInfo(ssl_info, &was_npn_negotiated, 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &protocol_negotiated); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(read_callback_.is_null()); 195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!user_buffer_.get()); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_state_ == STATE_DISCONNECTED) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (next_state_ == STATE_CLOSED && read_buffer_queue_.IsEmpty()) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buf); 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t result = PopulateUserReadBuffer(buf->data(), buf_len); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == 0) { 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_buffer_ = buf; 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_buffer_len_ = static_cast<size_t>(buf_len); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_ = callback; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_buffer_ = NULL; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyProxyClientSocket::PopulateUserReadBuffer(char* data, size_t len) { 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return read_buffer_queue_.Dequeue(data, len); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(write_callback_.is_null()); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_state_ != STATE_OPEN) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(spdy_stream_.get()); 22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_stream_->SendData(buf, buf_len, MORE_DATA_TO_SEND); 23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, 23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) buf_len, buf->data()); 23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) write_callback_ = callback; 23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) write_buffer_len_ = buf_len; 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return ERR_IO_PENDING; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyProxyClientSocket::SetReceiveBufferSize(int32 size) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since this StreamSocket sits on top of a shared SpdySession, it 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is not safe for callers to set change this underlying socket. 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyProxyClientSocket::SetSendBufferSize(int32 size) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since this StreamSocket sits on top of a shared SpdySession, it 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is not safe for callers to set change this underlying socket. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::GetPeerAddress(IPEndPoint* address) const { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsConnected()) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return spdy_stream_->GetPeerAddress(address); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::GetLocalAddress(IPEndPoint* address) const { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsConnected()) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return spdy_stream_->GetLocalAddress(address); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyProxyClientSocket::LogBlockedTunnelResponse() const { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProxyClientSocket::LogBlockedTunnelResponse( 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_.headers->response_code(), 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.url, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* is_https_proxy = */ true); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyProxyClientSocket::OnIOComplete(int result) { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(STATE_DISCONNECTED, next_state_); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoLoop(result); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != ERR_IO_PENDING) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback c = read_callback_; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Run(rv); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::DoLoop(int last_io_result) { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(next_state_, STATE_DISCONNECTED); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = last_io_result; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) State state = next_state_; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_DISCONNECTED; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_GENERATE_AUTH_TOKEN: 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoGenerateAuthToken(); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_GENERATE_AUTH_TOKEN_COMPLETE: 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoGenerateAuthTokenComplete(rv); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_SEND_REQUEST: 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoSendRequest(); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_SEND_REQUEST_COMPLETE: 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode( 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoSendRequestComplete(rv); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv >= 0 || rv == ERR_IO_PENDING) { 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Emit extra event so can use the same events as 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // HttpProxyClientSocket. 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log_.BeginEvent( 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_READ_REPLY_COMPLETE: 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoReadReplyComplete(rv); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode( 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "bad state"; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = ERR_UNEXPECTED; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (rv != ERR_IO_PENDING && next_state_ != STATE_DISCONNECTED && 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ != STATE_OPEN); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::DoGenerateAuthToken() { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return auth_->MaybeGenerateAuthToken( 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &request_, 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SpdyProxyClientSocket::OnIOComplete, 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weak_factory_.GetWeakPtr()), 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::DoGenerateAuthTokenComplete(int result) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(ERR_IO_PENDING, result); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == OK) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_SEND_REQUEST; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::DoSendRequest() { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_SEND_REQUEST_COMPLETE; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add Proxy-Authentication header if necessary. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpRequestHeaders authorization_headers; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (auth_->HaveAuth()) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_->AddAuthorizationHeader(&authorization_headers); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string request_line; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpRequestHeaders request_headers; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildTunnelRequest(request_, authorization_headers, endpoint_, &request_line, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &request_headers); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&HttpRequestHeaders::NetLogCallback, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(&request_headers), 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &request_line)); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.extra_headers.MergeFrom(request_headers); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock()); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateSpdyHeadersFromHttpRequest(request_, request_headers, headers.get(), 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_stream_->GetProtocolVersion(), true); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset the URL to be the endpoint of the connection 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (spdy_stream_->GetProtocolVersion() > 2) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*headers)[":path"] = endpoint_.ToString(); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) headers->erase(":scheme"); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*headers)["url"] = endpoint_.ToString(); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) headers->erase("scheme"); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return spdy_stream_->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::DoSendRequestComplete(int result) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for SYN_REPLY frame from the server 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_READ_REPLY_COMPLETE; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdyProxyClientSocket::DoReadReplyComplete(int result) { 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We enter this method directly from DoSendRequestComplete, since 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we are notified by a callback when the SYN_REPLY frame arrives 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Require the "HTTP/1.x" status line for SSL CONNECT. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_TUNNEL_CONNECTION_FAILED; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&HttpResponseHeaders::NetLogCallback, response_.headers)); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (response_.headers->response_code()) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 200: // OK 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_OPEN; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 302: // Found / Moved Temporarily 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to return a sanitized response so we can follow auth redirects. 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we can't, fail the tunnel connection. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SanitizeProxyRedirect(&response_, request_.url)) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Immediately hand off our SpdyStream to a newly created 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SpdyHttpStream so that any subsequent SpdyFrames are processed in 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the context of the HttpStream, not the socket. 411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(spdy_stream_.get()); 412a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = spdy_stream_; 413a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) spdy_stream_.reset(); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_stream_.reset(new SpdyHttpStream(NULL, false)); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_stream_->InitializeWithExistingStream(stream); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_DISCONNECTED; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogBlockedTunnelResponse(); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_TUNNEL_CONNECTION_FAILED; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 407: // Proxy Authentication Required 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_OPEN; 425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return HandleProxyAuthChallenge(auth_.get(), &response_, net_log_); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore response to avoid letting the proxy impersonate the target 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // server. (See http://crbug.com/137891.) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogBlockedTunnelResponse(); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_TUNNEL_CONNECTION_FAILED; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SpdyStream::Delegate methods: 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called when SYN frame has been sent. 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if no more data to be sent after SYN frame. 43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SpdyProxyClientSocket::OnRequestHeadersSent() { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(next_state_, STATE_SEND_REQUEST_COMPLETE); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnIOComplete(OK); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int SpdyProxyClientSocket::OnResponseHeadersReceived( 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyHeaderBlock& response, 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time response_time, 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int status) { 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we've already received the reply, existing headers are too late. 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mbelshe): figure out a way to make HEADERS frames useful after the 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // initial response. 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_state_ != STATE_READ_REPLY_COMPLETE) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the response 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SpdyHeadersToHttpResponse( 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response, spdy_stream_->GetProtocolVersion(), &response_)) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INCOMPLETE_SPDY_HEADERS; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnIOComplete(status); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Called when data is received or on EOF (if |buffer| is NULL). 464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int SpdyProxyClientSocket::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { 465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (buffer) { 466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, 467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buffer->GetRemainingSize(), 468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buffer->GetRemainingData()); 469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) read_buffer_queue_.Enqueue(buffer.Pass()); 470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, 0, NULL); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_callback_.is_null()) { 475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int rv = PopulateUserReadBuffer(user_buffer_->data(), user_buffer_len_); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback c = read_callback_; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_buffer_ = NULL; 479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_buffer_len_ = 0; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Run(rv); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SpdyProxyClientSocket::OnDataSent() { 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!write_callback_.is_null()); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int rv = write_buffer_len_; 48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) write_buffer_len_ = 0; 49090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ResetAndReturn(&write_callback_).Run(rv); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyProxyClientSocket::OnClose(int status) { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) was_ever_used_ = spdy_stream_->WasEverUsed(); 495a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) spdy_stream_.reset(); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool connecting = next_state_ != STATE_DISCONNECTED && 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ < STATE_OPEN; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_state_ == STATE_OPEN) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_CLOSED; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_DISCONNECTED; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WeakPtr<SpdyProxyClientSocket> weak_ptr = weak_factory_.GetWeakPtr(); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback write_callback = write_callback_; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_.Reset(); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buffer_len_ = 0; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're in the middle of connecting, we need to make sure 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we invoke the connect callback. 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (connecting) { 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!read_callback_.is_null()); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback read_callback = read_callback_; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback.Run(status); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!read_callback_.is_null()) { 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have a read_callback_, the we need to make sure we call it back. 518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnDataReceived(scoped_ptr<SpdyBuffer>()); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This may have been deleted by read_callback_, so check first. 521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (weak_ptr.get() && !write_callback.is_null()) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback.Run(ERR_CONNECTION_CLOSED); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 526