1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(ukai): code is similar with http_network_transaction.cc.  We should
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   think about ways to share code, if possible.
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket_stream/socket_stream.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/auth.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/host_resolver.h"
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h"
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_util.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_response_headers.h"
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_util.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/client_socket_factory.h"
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/ssl_client_socket.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/socks5_client_socket.h"
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/socks_client_socket.h"
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/tcp_client_socket.h"
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket_stream/socket_stream_metrics.h"
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket_stream/socket_stream_throttle.h"
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request.h"
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kMaxPendingSendAllowed = 32768;  // 32 kilobytes.
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kReadBufferSize = 4096;
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::ResponseHeaders::Realloc(size_t new_size) {
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size)));
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSocketStream::SocketStream(const GURL& url, Delegate* delegate)
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : url_(url),
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      delegate_(delegate),
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      max_pending_send_allowed_(kMaxPendingSendAllowed),
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_(STATE_NONE),
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      factory_(ClientSocketFactory::GetDefaultFactory()),
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      proxy_mode_(kDirectConnection),
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      proxy_url_(url),
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      pac_request_(NULL),
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          io_callback_(this, &SocketStream::OnIOCompleted)),
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          read_callback_(this, &SocketStream::OnReadCompleted)),
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          write_callback_(this, &SocketStream::OnWriteCompleted)),
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      read_buf_(NULL),
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_(NULL),
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      current_write_buf_(NULL),
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_offset_(0),
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_size_(0),
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      throttle_(
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          SocketStreamThrottle::GetSocketStreamThrottleForScheme(
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              url.scheme())),
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      metrics_(new SocketStreamMetrics(url)),
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          request_tracker_node_(this)) {
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current()) <<
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must exist";
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must be TYPE_IO";
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(delegate_);
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(throttle_);
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSocketStream::~SocketStream() {
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  set_context(NULL);
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!delegate_);
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSocketStream::UserData* SocketStream::GetUserData(
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const void* key) const {
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UserDataMap::const_iterator found = user_data_.find(key);
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (found != user_data_.end())
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return found->second.get();
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NULL;
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::SetUserData(const void* key, UserData* data) {
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_data_[key] = linked_ptr<UserData>(data);
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::set_context(URLRequestContext* context) {
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<URLRequestContext> prev_context = context_;
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  context_ = context;
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (prev_context != context) {
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (prev_context)
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      prev_context->socket_stream_tracker()->Remove(this);
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (context) {
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!load_log_) {
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // Create the LoadLog -- we waited until now to create it so we know
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // what constraints the URLRequestContext is enforcing on log levels.
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        load_log_ = context->socket_stream_tracker()->CreateLoadLog();
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      context->socket_stream_tracker()->Add(this);
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (context_)
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    host_resolver_ = context_->host_resolver();
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::Connect() {
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current()) <<
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must exist";
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must be TYPE_IO";
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (context_)
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ssl_config_service()->GetSSLConfig(&ssl_config_);
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(next_state_, STATE_NONE);
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddRef();  // Released in Finish()
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Open a connection asynchronously, so that delegate won't be called
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // back before returning Connect().
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_RESOLVE_PROXY;
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LoadLog::BeginEvent(load_log_, LoadLog::TYPE_SOCKET_STREAM_CONNECT);
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      FROM_HERE,
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NewRunnableMethod(this, &SocketStream::DoLoop, OK));
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SocketStream::SendData(const char* data, int len) {
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current()) <<
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must exist";
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must be TYPE_IO";
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!socket_.get() || !socket_->IsConnected() || next_state_ == STATE_NONE)
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (write_buf_) {
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int current_amount_send = write_buf_size_ - write_buf_offset_;
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (PendingDataQueue::const_iterator iter = pending_write_bufs_.begin();
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         iter != pending_write_bufs_.end();
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         ++iter)
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      current_amount_send += (*iter)->size();
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current_amount_send += len;
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (current_amount_send > max_pending_send_allowed_)
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pending_write_bufs_.push_back(new IOBufferWithSize(len));
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    memcpy(pending_write_bufs_.back()->data(), data, len);
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!current_write_buf_);
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_buf_ = new IOBuffer(len);
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memcpy(write_buf_->data(), data, len);
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_buf_size_ = len;
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_buf_offset_ = 0;
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Send pending data asynchronously, so that delegate won't be called
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // back before returning SendData().
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      FROM_HERE,
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NewRunnableMethod(this, &SocketStream::DoLoop, OK));
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::Close() {
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current()) <<
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must exist";
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must be TYPE_IO";
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!socket_.get() || !socket_->IsConnected() || next_state_ == STATE_NONE)
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_->Disconnect();
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_CLOSE;
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Close asynchronously, so that delegate won't be called
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // back before returning Close().
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      FROM_HERE,
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NewRunnableMethod(this, &SocketStream::DoLoop, OK));
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::RestartWithAuth(
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const std::wstring& username, const std::wstring& password) {
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current()) <<
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must exist";
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must be TYPE_IO";
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(auth_handler_);
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!socket_.get()) {
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Socket is closed before restarting with auth.";
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (auth_identity_.invalid) {
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Update the username/password.
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_.source = HttpAuth::IDENT_SRC_EXTERNAL;
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_.invalid = false;
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_.username = username;
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_.password = password;
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      FROM_HERE,
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NewRunnableMethod(this, &SocketStream::DoRestartWithAuth));
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DetachDelegate() {
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!delegate_)
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delegate_ = NULL;
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LoadLog::AddEvent(load_log_, LoadLog::TYPE_CANCELLED);
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Close();
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::Finish(int result) {
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current()) <<
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must exist";
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must be TYPE_IO";
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_LE(result, OK);
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == OK)
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = ERR_CONNECTION_CLOSED;
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(next_state_, STATE_NONE);
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DLOG(INFO) << "Finish result=" << net::ErrorToString(result);
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate_)
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate_->OnError(this, result);
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnClose();
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Delegate* delegate = delegate_;
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delegate_ = NULL;
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate) {
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate->OnClose(this);
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  throttle_->OnClose(this);
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Release();
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::SetHostResolver(HostResolver* host_resolver) {
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(host_resolver);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  host_resolver_ = host_resolver;
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::SetClientSocketFactory(
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ClientSocketFactory* factory) {
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(factory);
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  factory_ = factory;
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::CopyAddrInfo(struct addrinfo* head) {
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  addresses_.Copy(head);
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DidEstablishConnection() {
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!socket_.get() || !socket_->IsConnected()) {
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_CONNECTION_FAILED;
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_READ_WRITE;
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnConnected();
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LoadLog::EndEvent(load_log_, LoadLog::TYPE_SOCKET_STREAM_CONNECT);
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate_)
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate_->OnConnected(this, max_pending_send_allowed_);
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return OK;
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DidReceiveData(int result) {
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(read_buf_);
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(result, 0);
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LoadLog::AddEvent(load_log_, LoadLog::TYPE_SOCKET_STREAM_RECEIVED);
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int len = result;
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnRead(len);
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  result = throttle_->OnRead(this, read_buf_->data(), len, &io_callback_);
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate_) {
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Notify recevied data to delegate.
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate_->OnReceivedData(this, read_buf_->data(), len);
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_buf_ = NULL;
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DidSendData(int result) {
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(result, 0);
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LoadLog::AddEvent(load_log_, LoadLog::TYPE_SOCKET_STREAM_SENT);
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int len = result;
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnWrite(len);
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  result = throttle_->OnWrite(this, current_write_buf_->data(), len,
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                              &io_callback_);
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  current_write_buf_ = NULL;
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate_)
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate_->OnSentData(this, len);
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int remaining_size = write_buf_size_ - write_buf_offset_ - len;
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (remaining_size == 0) {
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!pending_write_bufs_.empty()) {
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_size_ = pending_write_bufs_.front()->size();
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_ = pending_write_bufs_.front();
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      pending_write_bufs_.pop_front();
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_size_ = 0;
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_ = NULL;
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_buf_offset_ = 0;
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_buf_offset_ += len;
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::OnIOCompleted(int result) {
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DoLoop(result);
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::OnReadCompleted(int result) {
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == 0) {
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // 0 indicates end-of-file, so socket was closed.
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else if (result > 0 && read_buf_) {
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = DidReceiveData(result);
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DoLoop(result);
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::OnWriteCompleted(int result) {
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result >= 0 && write_buf_) {
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = DidSendData(result);
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DoLoop(result);
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DoLoop(int result) {
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If context was not set, close immediately.
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!context_)
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (next_state_ == STATE_NONE)
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  do {
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    State state = next_state_;
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_NONE;
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    switch (state) {
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_RESOLVE_PROXY:
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoResolveProxy();
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_RESOLVE_PROXY_COMPLETE:
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoResolveProxyComplete(result);
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_RESOLVE_HOST:
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoResolveHost();
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_RESOLVE_HOST_COMPLETE:
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoResolveHostComplete(result);
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_TCP_CONNECT:
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoTcpConnect();
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_TCP_CONNECT_COMPLETE:
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoTcpConnectComplete(result);
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_WRITE_TUNNEL_HEADERS:
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoWriteTunnelHeaders();
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_WRITE_TUNNEL_HEADERS_COMPLETE:
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoWriteTunnelHeadersComplete(result);
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_READ_TUNNEL_HEADERS:
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoReadTunnelHeaders();
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_READ_TUNNEL_HEADERS_COMPLETE:
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoReadTunnelHeadersComplete(result);
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_SOCKS_CONNECT:
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoSOCKSConnect();
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_SOCKS_CONNECT_COMPLETE:
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoSOCKSConnectComplete(result);
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_SSL_CONNECT:
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoSSLConnect();
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_SSL_CONNECT_COMPLETE:
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoSSLConnectComplete(result);
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_READ_WRITE:
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoReadWrite(result);
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_CLOSE:
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_LE(result, OK);
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        Finish(result);
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      default:
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        NOTREACHED() << "bad state";
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        Finish(result);
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If the connection is not established yet and had actual errors,
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // close the connection.
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) {
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DCHECK_EQ(next_state_, STATE_CLOSE);
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LoadLog::EndEvent(load_log_, LoadLog::TYPE_SOCKET_STREAM_CONNECT);
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (result != ERR_IO_PENDING);
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveProxy() {
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!pac_request_);
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!proxy_url_.is_valid()) {
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_INVALID_ARGUMENT;
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return proxy_service()->ResolveProxy(
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      proxy_url_, &proxy_info_, &io_callback_, &pac_request_, load_log_);
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveProxyComplete(int result) {
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_RESOLVE_HOST;
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  pac_request_ = NULL;
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result != OK) {
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Failed to resolve proxy: " << result;
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (delegate_)
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      delegate_->OnError(this, result);
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    proxy_info_.UseDirect();
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_info_.is_direct()) {
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If proxy was not found for original URL (i.e. websocket URL),
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // try again with https URL, like Safari implementation.
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Note that we don't want to use http proxy, because we'll use tunnel
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // proxy using CONNECT method, which is used by https proxy.
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!proxy_url_.SchemeIs("https")) {
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      const std::string scheme = "https";
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      GURL::Replacements repl;
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      repl.SetSchemeStr(scheme);
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      proxy_url_ = url_.ReplaceComponents(repl);
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DLOG(INFO) << "Try https proxy: " << proxy_url_;
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_RESOLVE_PROXY;
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return OK;
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return OK;
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveHost() {
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_RESOLVE_HOST_COMPLETE;
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_info_.is_direct())
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    proxy_mode_ = kDirectConnection;
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else if (proxy_info_.proxy_server().is_socks())
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    proxy_mode_ = kSOCKSProxy;
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    proxy_mode_ = kTunnelProxy;
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Determine the host and port to connect to.
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string host;
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int port;
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_mode_ != kDirectConnection) {
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ProxyServer proxy_server = proxy_info_.proxy_server();
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    host = proxy_server.HostNoBrackets();
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    port = proxy_server.port();
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    host = url_.HostNoBrackets();
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    port = url_.EffectiveIntPort();
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HostResolver::RequestInfo resolve_info(host, port);
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(host_resolver_.get());
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  resolver_.reset(new SingleRequestHostResolver(host_resolver_.get()));
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return resolver_->Resolve(resolve_info, &addresses_, &io_callback_,
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            load_log_);
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveHostComplete(int result) {
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == OK) {
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_TCP_CONNECT;
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = throttle_->OnStartOpenConnection(this, &io_callback_);
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (result == net::ERR_IO_PENDING)
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      metrics_->OnWaitConnection();
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(ukai): if error occured, reconsider proxy after error.
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoTcpConnect() {
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_TCP_CONNECT_COMPLETE;
504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(factory_);
505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_.reset(factory_->CreateTCPClientSocket(addresses_));
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnStartConnection();
507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return socket_->Connect(&io_callback_, load_log_);
508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoTcpConnectComplete(int result) {
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(ukai): if error occured, reconsider proxy after error.
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result != OK) {
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_mode_ == kTunnelProxy)
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_WRITE_TUNNEL_HEADERS;
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else if (proxy_mode_ == kSOCKSProxy)
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_SOCKS_CONNECT;
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else if (is_secure()) {
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_SSL_CONNECT;
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = DidEstablishConnection();
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoWriteTunnelHeaders() {
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kTunnelProxy, proxy_mode_);
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_WRITE_TUNNEL_HEADERS_COMPLETE;
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!tunnel_request_headers_.get()) {
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    metrics_->OnTunnelProxy();
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_request_headers_ = new RequestHeaders();
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_request_headers_bytes_sent_ = 0;
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (tunnel_request_headers_->headers_.empty()) {
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string authorization_headers;
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!auth_handler_.get()) {
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // First attempt.  Find auth from the proxy address.
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      HttpAuthCache::Entry* entry = auth_cache_.LookupByPath(
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          ProxyAuthOrigin(), std::string());
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (entry && !entry->handler()->is_connection_based()) {
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_identity_.source = HttpAuth::IDENT_SRC_PATH_LOOKUP;
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_identity_.invalid = false;
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_identity_.username = entry->username();
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_identity_.password = entry->password();
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_handler_ = entry->handler();
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Support basic authentication scheme only, because we don't have
556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // HttpRequestInfo.
557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // TODO(ukai): Add support other authentication scheme.
558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (auth_handler_.get() && auth_handler_->scheme() == "basic") {
559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      std::string credentials = auth_handler_->GenerateCredentials(
560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          auth_identity_.username,
561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          auth_identity_.password,
562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          NULL,
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          &proxy_info_);
564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      authorization_headers.append(
565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY) +
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          ": " + credentials + "\r\n");
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_request_headers_->headers_ = StringPrintf(
570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        "CONNECT %s HTTP/1.1\r\n"
571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        "Host: %s\r\n"
572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        "Proxy-Connection: keep-alive\r\n",
573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        GetHostAndPort(url_).c_str(),
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        GetHostAndOptionalPort(url_).c_str());
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!authorization_headers.empty())
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      tunnel_request_headers_->headers_ += authorization_headers;
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_request_headers_->headers_ += "\r\n";
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_request_headers_->SetDataOffset(tunnel_request_headers_bytes_sent_);
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int buf_len = static_cast<int>(tunnel_request_headers_->headers_.size() -
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 tunnel_request_headers_bytes_sent_);
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(buf_len, 0);
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return socket_->Write(tunnel_request_headers_, buf_len, &io_callback_);
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoWriteTunnelHeadersComplete(int result) {
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kTunnelProxy, proxy_mode_);
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result < 0) {
590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_request_headers_bytes_sent_ += result;
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (tunnel_request_headers_bytes_sent_ <
596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      tunnel_request_headers_->headers_.size())
597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_WRITE_TUNNEL_HEADERS;
598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_READ_TUNNEL_HEADERS;
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return OK;
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoReadTunnelHeaders() {
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kTunnelProxy, proxy_mode_);
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_READ_TUNNEL_HEADERS_COMPLETE;
607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!tunnel_response_headers_.get()) {
609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_response_headers_ = new ResponseHeaders();
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_response_headers_capacity_ = kMaxTunnelResponseHeadersSize;
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_response_headers_->Realloc(tunnel_response_headers_capacity_);
612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_response_headers_len_ = 0;
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int buf_len = tunnel_response_headers_capacity_ -
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      tunnel_response_headers_len_;
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_response_headers_->SetDataOffset(tunnel_response_headers_len_);
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK(tunnel_response_headers_->data());
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return socket_->Read(tunnel_response_headers_, buf_len, &io_callback_);
621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoReadTunnelHeadersComplete(int result) {
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kTunnelProxy, proxy_mode_);
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result < 0) {
627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == 0) {
632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // 0 indicates end-of-file, so socket was closed.
633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_CONNECTION_CLOSED;
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_response_headers_len_ += result;
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(tunnel_response_headers_len_ <= tunnel_response_headers_capacity_);
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int eoh = HttpUtil::LocateEndOfHeaders(
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      tunnel_response_headers_->headers(), tunnel_response_headers_len_, 0);
642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (eoh == -1) {
643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (tunnel_response_headers_len_ >= kMaxTunnelResponseHeadersSize) {
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_CLOSE;
645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_RESPONSE_HEADERS_TOO_BIG;
646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_READ_TUNNEL_HEADERS;
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return OK;
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // DidReadResponseHeaders
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<HttpResponseHeaders> headers;
653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  headers = new HttpResponseHeaders(
654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      HttpUtil::AssembleRawHeaders(tunnel_response_headers_->headers(), eoh));
655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Require the "HTTP/1.x" status line.
657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_TUNNEL_CONNECTION_FAILED;
659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (headers->response_code()) {
661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case 200:  // OK
662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (is_secure()) {
663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(eoh, tunnel_response_headers_len_);
664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        next_state_ = STATE_SSL_CONNECT;
665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DidEstablishConnection();
667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (result < 0) {
668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          next_state_ = STATE_CLOSE;
669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return result;
670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if ((eoh < tunnel_response_headers_len_) && delegate_)
672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          delegate_->OnReceivedData(
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              this, tunnel_response_headers_->headers() + eoh,
674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              tunnel_response_headers_len_ - eoh);
675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return OK;
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case 407:  // Proxy Authentication Required.
678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      result = HandleAuthChallenge(headers.get());
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (result == ERR_PROXY_AUTH_REQUESTED &&
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          auth_handler_.get() && delegate_) {
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_info_ = new AuthChallengeInfo;
682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_info_->is_proxy = true;
683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_info_->host_and_port =
684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            ASCIIToWide(proxy_info_.proxy_server().host_and_port());
685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_info_->scheme = ASCIIToWide(auth_handler_->scheme());
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_info_->realm = ASCIIToWide(auth_handler_->realm());
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // Wait until RestartWithAuth or Close is called.
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        MessageLoop::current()->PostTask(
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            FROM_HERE,
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            NewRunnableMethod(this, &SocketStream::DoAuthRequired));
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        next_state_ = STATE_AUTH_REQUIRED;
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return ERR_IO_PENDING;
693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_CLOSE;
698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_TUNNEL_CONNECTION_FAILED;
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSOCKSConnect() {
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kSOCKSProxy, proxy_mode_);
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ClientSocket* s = socket_.release();
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HostResolver::RequestInfo req_info(url_.HostNoBrackets(),
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     url_.EffectiveIntPort());
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5)
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    s = new SOCKS5ClientSocket(s, req_info);
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    s = new SOCKSClientSocket(s, req_info, host_resolver_.get());
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_.reset(s);
715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnSOCKSProxy();
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return socket_->Connect(&io_callback_, load_log_);
717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSOCKSConnectComplete(int result) {
720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kSOCKSProxy, proxy_mode_);
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == OK) {
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (is_secure())
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_SSL_CONNECT;
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    else
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      result = DidEstablishConnection();
727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSSLConnect() {
734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(factory_);
735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_.reset(factory_->CreateSSLClientSocket(
736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      socket_.release(), url_.HostNoBrackets(), ssl_config_));
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_SSL_CONNECT_COMPLETE;
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnSSLConnection();
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return socket_->Connect(&io_callback_, load_log_);
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSSLConnectComplete(int result) {
743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (IsCertificateError(result)) {
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (socket_->IsConnectedAndIdle()) {
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      result = HandleCertificateError(result);
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // SSLClientSocket for Mac will report socket is not connected,
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // if it returns cert verification error.  It didn't perform
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // SSLHandshake yet.
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // So, we should restart establishing connection with the
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // certificate in allowed bad certificates in |ssl_config_|.
752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // See also net/http/http_network_transaction.cc
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      //  HandleCertificateError() and RestartIgnoringLastError().
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      SSLClientSocket* ssl_socket =
755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        reinterpret_cast<SSLClientSocket*>(socket_.get());
756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      SSLInfo ssl_info;
757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ssl_socket->GetSSLInfo(&ssl_info);
758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      SSLConfig::CertAndStatus bad_cert;
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      bad_cert.cert = ssl_info.cert;
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      bad_cert.cert_status = ssl_info.cert_status;
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (ssl_config_.IsAllowedBadCert(ssl_info.cert)) {
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // If we already have the certificate in the set of allowed bad
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // certificates, we did try it and failed again, so we should not
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // retry again: the connection should fail at last.
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        next_state_ = STATE_CLOSE;
766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return result;
767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Add the bad certificate to the set of allowed certificates in the
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // SSL info object.
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ssl_config_.allowed_bad_certs.push_back(bad_cert);
771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Restart connection ignoring the bad certificate.
772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      socket_->Disconnect();
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      socket_.reset();
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_TCP_CONNECT;
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return OK;
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == OK)
780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = DidEstablishConnection();
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoReadWrite(int result) {
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result < OK) {
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!socket_.get() || !socket_->IsConnected()) {
792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_CONNECTION_CLOSED;
794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_READ_WRITE;
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!read_buf_) {
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // No read pending.
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    read_buf_ = new IOBuffer(kReadBufferSize);
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = socket_->Read(read_buf_, kReadBufferSize, &read_callback_);
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (result > 0) {
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return DidReceiveData(result);
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else if (result == 0) {
805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // 0 indicates end-of-file, so socket was closed.
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_CLOSE;
807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_CONNECTION_CLOSED;
808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If read is pending, try write as well.
810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Otherwise, return the result and do next loop (to close the connection).
811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (result != ERR_IO_PENDING) {
812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_CLOSE;
813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return result;
814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Read is pending.
817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(read_buf_);
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (write_buf_ && !current_write_buf_) {
820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // No write pending.
821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current_write_buf_ = new DrainableIOBuffer(write_buf_, write_buf_size_);
822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current_write_buf_->SetOffset(write_buf_offset_);
823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = socket_->Write(current_write_buf_,
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            current_write_buf_->BytesRemaining(),
825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            &write_callback_);
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (result > 0) {
827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return DidSendData(result);
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If write is not pending, return the result and do next loop (to close
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // the connection).
831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (result != 0 && result != ERR_IO_PENDING) {
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_CLOSE;
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return result;
834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We arrived here when both operation is pending.
839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_IO_PENDING;
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL SocketStream::ProxyAuthOrigin() const {
843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return GURL("http://" + proxy_info_.proxy_server().host_and_port());
844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::HandleAuthChallenge(const HttpResponseHeaders* headers) {
847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  GURL auth_origin(ProxyAuthOrigin());
848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(INFO) << "The proxy " << auth_origin << " requested auth";
850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The auth we tried just failed, hence it can't be valid.
852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Remove it from the cache so it won't be used again.
853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (auth_handler_.get() && !auth_identity_.invalid &&
854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      auth_handler_->IsFinalRound()) {
855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (auth_identity_.source != HttpAuth::IDENT_SRC_PATH_LOOKUP)
856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      auth_cache_.Remove(auth_origin,
857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         auth_handler_->realm(),
858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         auth_identity_.username,
859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         auth_identity_.password);
860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_handler_ = NULL;
861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_ = HttpAuth::Identity();
862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  auth_identity_.invalid = true;
865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HttpAuth::ChooseBestChallenge(headers, HttpAuth::AUTH_PROXY, auth_origin,
866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                &auth_handler_);
867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!auth_handler_) {
868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Can't perform auth to the proxy " << auth_origin;
869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_TUNNEL_CONNECTION_FAILED;
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (auth_handler_->NeedsIdentity()) {
872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    HttpAuthCache::Entry* entry = auth_cache_.LookupByRealm(
873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_origin, auth_handler_->realm());
874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (entry) {
875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (entry->handler()->scheme() != "basic") {
876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // We only support basic authentication scheme now.
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // TODO(ukai): Support other authentication scheme.
878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return ERR_TUNNEL_CONNECTION_FAILED;
879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      auth_identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      auth_identity_.invalid = false;
882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      auth_identity_.username = entry->username();
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      auth_identity_.password = entry->password();
884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Restart with auth info.
885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_PROXY_AUTH_REQUESTED;
887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_.invalid = false;
889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_TUNNEL_CONNECTION_FAILED;
891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DoAuthRequired() {
894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate_ && auth_info_.get())
895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate_->OnAuthRequired(this, auth_info_.get());
896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DoLoop(net::ERR_UNEXPECTED);
898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DoRestartWithAuth() {
901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED);
902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  auth_cache_.Add(ProxyAuthOrigin(), auth_handler_,
903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                  auth_identity_.username, auth_identity_.password,
904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                  std::string());
905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_request_headers_ = NULL;
907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_request_headers_bytes_sent_ = 0;
908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_response_headers_ = NULL;
909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_response_headers_capacity_ = 0;
910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_response_headers_len_ = 0;
911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_TCP_CONNECT;
913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DoLoop(OK);
914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::HandleCertificateError(int result) {
917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(ukai): handle cert error properly.
918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (result) {
919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ERR_CERT_COMMON_NAME_INVALID:
920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ERR_CERT_DATE_INVALID:
921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ERR_CERT_AUTHORITY_INVALID:
922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      result = OK;
923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SocketStream::is_secure() const {
931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return url_.SchemeIs("wss");
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSSLConfigService* SocketStream::ssl_config_service() const {
935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return context_->ssl_config_service();
936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProxyService* SocketStream::proxy_service() const {
939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return context_->proxy_service();
940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::GetInfoForTracker(
943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RequestTracker<SocketStream>::RecentRequestInfo* info) const {
944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  info->original_url = url_;
945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  info->load_log = load_log_;
946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
949