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