1731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Use of this source code is governed by a BSD-style license that can be 3731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// found in the LICENSE file. 4731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/spdy/spdy_proxy_client_socket.h" 6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <algorithm> // min 8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/logging.h" 10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/string_util.h" 11731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "googleurl/src/gurl.h" 12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/auth.h" 13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/io_buffer.h" 14731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/net_util.h" 15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/http/http_auth_cache.h" 16731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/http/http_auth_handler_factory.h" 17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/http/http_net_log_params.h" 18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/http/http_proxy_utils.h" 19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/http/http_response_headers.h" 20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/spdy/spdy_http_utils.h" 21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 22731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace net { 23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 24731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSpdyProxyClientSocket::SpdyProxyClientSocket( 25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SpdyStream* spdy_stream, 26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& user_agent, 27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const HostPortPair& endpoint, 28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GURL& url, 29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const HostPortPair& proxy_server, 30731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HttpAuthCache* auth_cache, 31731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HttpAuthHandlerFactory* auth_handler_factory) 32731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : ALLOW_THIS_IN_INITIALIZER_LIST( 33731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick io_callback_(this, &SpdyProxyClientSocket::OnIOComplete)), 34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_(STATE_DISCONNECTED), 35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick spdy_stream_(spdy_stream), 36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick read_callback_(NULL), 37731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_callback_(NULL), 38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick endpoint_(endpoint), 39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick auth_( 40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new HttpAuthController(HttpAuth::AUTH_PROXY, 41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GURL("http://" + proxy_server.ToString()), 42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick auth_cache, 43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick auth_handler_factory)), 44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick user_buffer_(NULL), 45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_buffer_len_(0), 46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_bytes_outstanding_(0), 47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick eof_has_been_read_(false), 48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick net_log_(spdy_stream->net_log()) { 49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick request_.method = "CONNECT"; 50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick request_.url = url; 51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!user_agent.empty()) 52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick user_agent); 54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick spdy_stream_->SetDelegate(this); 55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick was_ever_used_ = spdy_stream_->WasEverUsed(); 56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 58731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSpdyProxyClientSocket::~SpdyProxyClientSocket() { 59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Disconnect(); 60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst HttpResponseInfo* SpdyProxyClientSocket::GetConnectResponseInfo() const { 6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return response_.headers ? &response_ : NULL; 6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenHttpStream* SpdyProxyClientSocket::CreateConnectResponseStream() { 6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(response_stream_.get()); 6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return response_stream_.release(); 6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Sends a SYN_STREAM frame to the proxy with a CONNECT request 72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// for the specified endpoint. Waits for the server to send back 73731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// a SYN_REPLY frame. OK will be returned if the status is 200. 74731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// ERR_TUNNEL_CONNECTION_FAILED will be returned for any other status. 75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// In any of these cases, Read() may be called to retrieve the HTTP 76731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// response body. Any other return values should be considered fatal. 77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// TODO(rch): handle 407 proxy auth requested correctly, perhaps 78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// by creating a new stream for the subsequent request. 79731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// TODO(rch): create a more appropriate error code to disambiguate 80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// the HTTPS Proxy tunnel failure from an HTTP Proxy tunnel failure. 817b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 827b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// TODO(kristianm): handle the case when wait_for_connect is true 837b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// (sync requests) 847b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 857b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsenint SpdyProxyClientSocket::Connect(CompletionCallback* callback 867b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 877b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen , bool wait_for_connect 88e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma , bool valid_uid 89e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma , uid_t calling_uid 907b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 917b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen ) { 92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(!read_callback_); 93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (next_state_ == STATE_OPEN) 94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return OK; 95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK_EQ(STATE_DISCONNECTED, next_state_); 97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ = STATE_GENERATE_AUTH_TOKEN; 98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int rv = DoLoop(OK); 100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (rv == ERR_IO_PENDING) 101731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick read_callback_ = callback; 102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return rv; 103731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SpdyProxyClientSocket::Disconnect() { 106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick read_buffer_.clear(); 107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick user_buffer_ = NULL; 108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick read_callback_ = NULL; 109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_buffer_len_ = 0; 111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_bytes_outstanding_ = 0; 112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_callback_ = NULL; 113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ = STATE_DISCONNECTED; 115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (spdy_stream_) 117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // This will cause OnClose to be invoked, which takes care of 118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // cleaning up all the internal state. 119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick spdy_stream_->Cancel(); 120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool SpdyProxyClientSocket::IsConnected() const { 123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED; 124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool SpdyProxyClientSocket::IsConnectedAndIdle() const { 127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return IsConnected() && !spdy_stream_->is_idle(); 128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 129731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst BoundNetLog& SpdyProxyClientSocket::NetLog() const { 13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return net_log_; 13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 134731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SpdyProxyClientSocket::SetSubresourceSpeculation() { 135731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO(rch): what should this implementation be? 136731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 137731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SpdyProxyClientSocket::SetOmniboxSpeculation() { 139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO(rch): what should this implementation be? 140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool SpdyProxyClientSocket::WasEverUsed() const { 143731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return was_ever_used_ || (spdy_stream_ && spdy_stream_->WasEverUsed()); 144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 146513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool SpdyProxyClientSocket::UsingTCPFastOpen() const { 147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, 151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CompletionCallback* callback) { 152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(!read_callback_); 153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(!user_buffer_); 154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (next_state_ == STATE_DISCONNECTED) 156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_SOCKET_NOT_CONNECTED; 157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!spdy_stream_ && read_buffer_.empty()) { 159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (eof_has_been_read_) 160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_CONNECTION_CLOSED; 161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick eof_has_been_read_ = true; 162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return 0; 163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); 166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(buf); 167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick user_buffer_ = new DrainableIOBuffer(buf, buf_len); 168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int result = PopulateUserReadBuffer(); 169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (result == 0) { 170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(callback); 171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick read_callback_ = callback; 172731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_IO_PENDING; 173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 174731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick user_buffer_ = NULL; 175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return result; 176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::PopulateUserReadBuffer() { 179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!user_buffer_) 180731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_IO_PENDING; 181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick while (!read_buffer_.empty() && user_buffer_->BytesRemaining() > 0) { 183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick scoped_refptr<DrainableIOBuffer> data = read_buffer_.front(); 184731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const int bytes_to_copy = std::min(user_buffer_->BytesRemaining(), 185731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick data->BytesRemaining()); 186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick memcpy(user_buffer_->data(), data->data(), bytes_to_copy); 187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick user_buffer_->DidConsume(bytes_to_copy); 188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (data->BytesRemaining() == bytes_to_copy) { 189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Consumed all data from this buffer 190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick read_buffer_.pop_front(); 191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick data->DidConsume(bytes_to_copy); 193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return user_buffer_->BytesConsumed(); 197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, 200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CompletionCallback* callback) { 201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(!write_callback_); 202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (next_state_ == STATE_DISCONNECTED) 203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_SOCKET_NOT_CONNECTED; 204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 205731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!spdy_stream_) 206731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_CONNECTION_CLOSED; 207731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 208731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_bytes_outstanding_= buf_len; 209731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (buf_len <= kMaxSpdyFrameChunkSize) { 210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int rv = spdy_stream_->WriteStreamData(buf, buf_len, spdy::DATA_FLAG_NONE); 211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (rv == ERR_IO_PENDING) { 212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_callback_ = callback; 213731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_buffer_len_ = buf_len; 214731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 215731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return rv; 216731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 217731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Since a SPDY Data frame can only include kMaxSpdyFrameChunkSize bytes 219731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // we need to send multiple data frames 220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (int i = 0; i < buf_len; i += kMaxSpdyFrameChunkSize) { 221731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int len = std::min(kMaxSpdyFrameChunkSize, buf_len - i); 222731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick scoped_refptr<DrainableIOBuffer> iobuf(new DrainableIOBuffer(buf, i + len)); 223731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick iobuf->SetOffset(i); 224731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int rv = spdy_stream_->WriteStreamData(iobuf, len, spdy::DATA_FLAG_NONE); 225731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (rv > 0) { 226731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_bytes_outstanding_ -= rv; 227731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else if (rv != ERR_IO_PENDING) { 228731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return rv; 229731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 230731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 231731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (write_bytes_outstanding_ > 0) { 232731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_callback_ = callback; 233731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_buffer_len_ = buf_len; 234731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_IO_PENDING; 235731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 236731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return buf_len; 237731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 238731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 239731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 240731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool SpdyProxyClientSocket::SetReceiveBufferSize(int32 size) { 241731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Since this ClientSocket sits on top of a shared SpdySession, it 242731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // is not safe for callers to set change this underlying socket. 243731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return false; 244731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 245731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 246731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool SpdyProxyClientSocket::SetSendBufferSize(int32 size) { 247731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Since this ClientSocket sits on top of a shared SpdySession, it 248731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // is not safe for callers to set change this underlying socket. 249731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return false; 250731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 251731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 252731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::GetPeerAddress(AddressList* address) const { 253731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!IsConnected()) 254731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_SOCKET_NOT_CONNECTED; 255731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return spdy_stream_->GetPeerAddress(address); 256731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 257731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint SpdyProxyClientSocket::GetLocalAddress(IPEndPoint* address) const { 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!IsConnected()) 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return ERR_SOCKET_NOT_CONNECTED; 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return spdy_stream_->GetLocalAddress(address); 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 264731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SpdyProxyClientSocket::OnIOComplete(int result) { 265731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK_NE(STATE_DISCONNECTED, next_state_); 266731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int rv = DoLoop(result); 267731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (rv != ERR_IO_PENDING) { 268731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CompletionCallback* c = read_callback_; 269731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick read_callback_ = NULL; 270731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick c->Run(rv); 271731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 272731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 273731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 274731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::DoLoop(int last_io_result) { 275731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK_NE(next_state_, STATE_DISCONNECTED); 276731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int rv = last_io_result; 277731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick do { 278731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick State state = next_state_; 279731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ = STATE_DISCONNECTED; 280731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick switch (state) { 281731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case STATE_GENERATE_AUTH_TOKEN: 282731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK_EQ(OK, rv); 283731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick rv = DoGenerateAuthToken(); 284731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 285731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case STATE_GENERATE_AUTH_TOKEN_COMPLETE: 286731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick rv = DoGenerateAuthTokenComplete(rv); 287731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 288731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case STATE_SEND_REQUEST: 289731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK_EQ(OK, rv); 29072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.BeginEvent( 29172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, NULL); 292731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick rv = DoSendRequest(); 293731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 294731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case STATE_SEND_REQUEST_COMPLETE: 29572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode( 29672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv); 297731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick rv = DoSendRequestComplete(rv); 298731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 299731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case STATE_READ_REPLY_COMPLETE: 300731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick rv = DoReadReplyComplete(rv); 30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode( 30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv); 303731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 304731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick default: 305731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NOTREACHED() << "bad state"; 306731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick rv = ERR_UNEXPECTED; 307731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 308731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 309731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } while (rv != ERR_IO_PENDING && next_state_ != STATE_DISCONNECTED && 310731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ != STATE_OPEN); 311731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return rv; 312731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 313731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 314731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::DoGenerateAuthToken() { 315731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE; 316731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return auth_->MaybeGenerateAuthToken(&request_, &io_callback_, net_log_); 317731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 318731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 319731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::DoGenerateAuthTokenComplete(int result) { 320731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK_NE(ERR_IO_PENDING, result); 321731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (result == OK) 322731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ = STATE_SEND_REQUEST; 323731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return result; 324731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 325731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 326731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::DoSendRequest() { 327731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ = STATE_SEND_REQUEST_COMPLETE; 328731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 329731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Add Proxy-Authentication header if necessary. 330731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HttpRequestHeaders authorization_headers; 331731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (auth_->HaveAuth()) { 332731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick auth_->AddAuthorizationHeader(&authorization_headers); 333731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 334731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 335731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string request_line; 336731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HttpRequestHeaders request_headers; 337731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BuildTunnelRequest(request_, authorization_headers, endpoint_, &request_line, 338731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &request_headers); 339731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (net_log_.IsLoggingAllEvents()) { 340731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick net_log_.AddEvent( 341731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 342513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch make_scoped_refptr(new NetLogHttpRequestParameter( 343513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch request_line, request_headers))); 344731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 345731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 346731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick request_.extra_headers.MergeFrom(request_headers); 347731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock()); 348731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CreateSpdyHeadersFromHttpRequest(request_, request_headers, headers.get(), 349731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick true); 350731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Reset the URL to be the endpoint of the connection 351731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (*headers)["url"] = endpoint_.ToString(); 352731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick headers->erase("scheme"); 353731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick spdy_stream_->set_spdy_headers(headers); 354731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 355731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return spdy_stream_->SendRequest(true); 356731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 357731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 358731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::DoSendRequestComplete(int result) { 359731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (result < 0) 360731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return result; 361731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 362731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Wait for SYN_REPLY frame from the server 363731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ = STATE_READ_REPLY_COMPLETE; 364731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_IO_PENDING; 365731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 366731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 367731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::DoReadReplyComplete(int result) { 368731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // We enter this method directly from DoSendRequestComplete, since 369731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // we are notified by a callback when the SYN_REPLY frame arrives 370731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 371731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (result < 0) 372731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return result; 373731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 374731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Require the "HTTP/1.x" status line for SSL CONNECT. 375731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0)) 376731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_TUNNEL_CONNECTION_FAILED; 377731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 378731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ = STATE_OPEN; 379731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (net_log_.IsLoggingAllEvents()) { 380731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick net_log_.AddEvent( 381731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 382513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers))); 383731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 384731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 38521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (response_.headers->response_code() == 200) { 386731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return OK; 38721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } else if (response_.headers->response_code() == 407) { 388731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_TUNNEL_CONNECTION_FAILED; 38921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } else { 39021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Immediately hand off our SpdyStream to a newly created SpdyHttpStream 39121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // so that any subsequent SpdyFrames are processed in the context of 39221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // the HttpStream, not the socket. 39321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(spdy_stream_); 39421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SpdyStream* stream = spdy_stream_; 39521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen spdy_stream_ = NULL; 39621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen response_stream_.reset(new SpdyHttpStream(NULL, false)); 39721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen response_stream_->InitializeWithExistingStream(stream); 39821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen next_state_ = STATE_DISCONNECTED; 39921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; 40021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 401731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 402731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 403731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// SpdyStream::Delegate methods: 404731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Called when SYN frame has been sent. 405731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Returns true if no more data to be sent after SYN frame. 406731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool SpdyProxyClientSocket::OnSendHeadersComplete(int status) { 407731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK_EQ(next_state_, STATE_SEND_REQUEST_COMPLETE); 408731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 409731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick OnIOComplete(status); 410731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 411731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // We return true here so that we send |spdy_stream_| into 412731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // STATE_OPEN (ala WebSockets). 413731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 414731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 415731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 416731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::OnSendBody() { 417731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Because we use |spdy_stream_| via STATE_OPEN (ala WebSockets) 418731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // OnSendBody() should never be called. 419731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NOTREACHED(); 420731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_UNEXPECTED; 421731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 422731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 423dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint SpdyProxyClientSocket::OnSendBodyComplete(int /*status*/, bool* /*eof*/) { 424731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Because we use |spdy_stream_| via STATE_OPEN (ala WebSockets) 425731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // OnSendBodyComplete() should never be called. 426731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NOTREACHED(); 427dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return ERR_UNEXPECTED; 428731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 429731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 430731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SpdyProxyClientSocket::OnResponseReceived( 431731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const spdy::SpdyHeaderBlock& response, 432731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::Time response_time, 433731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int status) { 434201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // If we've already received the reply, existing headers are too late. 435201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // TODO(mbelshe): figure out a way to make HEADERS frames useful after the 436201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // initial response. 437201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (next_state_ != STATE_READ_REPLY_COMPLETE) 438201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return OK; 439731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 440201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Save the response 441201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int rv = SpdyHeadersToHttpResponse(response, &response_); 442201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (rv == ERR_INCOMPLETE_SPDY_HEADERS) 443201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return rv; // More headers are coming. 444731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 445731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick OnIOComplete(status); 446731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return OK; 447731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 448731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 449731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Called when data is received. 450731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SpdyProxyClientSocket::OnDataReceived(const char* data, int length) { 451731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (length > 0) { 452731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Save the received data. 453513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<IOBuffer> io_buffer(new IOBuffer(length)); 454731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick memcpy(io_buffer->data(), data, length); 455513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch read_buffer_.push_back( 456513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch make_scoped_refptr(new DrainableIOBuffer(io_buffer, length))); 457731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 458731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 459731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (read_callback_) { 460731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int rv = PopulateUserReadBuffer(); 461731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CompletionCallback* c = read_callback_; 462731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick read_callback_ = NULL; 463731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick user_buffer_ = NULL; 464731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick c->Run(rv); 465731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 466731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 467731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 468731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SpdyProxyClientSocket::OnDataSent(int length) { 469731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(write_callback_); 470731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 471731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_bytes_outstanding_ -= length; 472731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 473731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK_GE(write_bytes_outstanding_, 0); 474731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 475731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (write_bytes_outstanding_ == 0) { 476731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int rv = write_buffer_len_; 477731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_buffer_len_ = 0; 478731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_bytes_outstanding_ = 0; 479731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CompletionCallback* c = write_callback_; 480731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_callback_ = NULL; 481731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick c->Run(rv); 482731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 483731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 484731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 485731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SpdyProxyClientSocket::OnClose(int status) { 486731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(spdy_stream_); 487731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick was_ever_used_ = spdy_stream_->WasEverUsed(); 488731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick spdy_stream_ = NULL; 489731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 490731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool connecting = next_state_ != STATE_DISCONNECTED && 491731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ < STATE_OPEN; 492731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (next_state_ == STATE_OPEN) 493731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ = STATE_CLOSED; 494731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick else 495731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_state_ = STATE_DISCONNECTED; 496731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 497731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CompletionCallback* write_callback = write_callback_; 498731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_callback_ = NULL; 499731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_buffer_len_ = 0; 500731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_bytes_outstanding_ = 0; 501731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 502731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If we're in the middle of connecting, we need to make sure 503731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // we invoke the connect callback. 504731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (connecting) { 505731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(read_callback_); 506731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CompletionCallback* read_callback = read_callback_; 507731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick read_callback_ = NULL; 508731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick read_callback->Run(status); 509731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else if (read_callback_) { 510731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If we have a read_callback, the we need to make sure we call it back 511731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick OnDataReceived(NULL, 0); 512731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 513731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (write_callback) 514731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick write_callback->Run(ERR_CONNECTION_CLOSED); 515731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 516731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 517dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdyProxyClientSocket::set_chunk_callback(ChunkCallback* /*callback*/) { 518dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 519dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 520731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} // namespace net 521