172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 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
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <set>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h"
183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/auth.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/host_resolver.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h"
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_util.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_auth_handler_factory.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_request_info.h"
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_response_headers.h"
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_util.h"
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/client_socket_factory.h"
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/socks5_client_socket.h"
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/socks_client_socket.h"
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/socket/ssl_client_socket.h"
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/tcp_client_socket.h"
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket_stream/socket_stream_metrics.h"
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request.h"
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kMaxPendingSendAllowed = 32768;  // 32 kilobytes.
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kReadBufferSize = 4096;
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSocketStream::ResponseHeaders::ResponseHeaders() : IOBuffer() {}
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::ResponseHeaders::Realloc(size_t new_size) {
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size)));
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSocketStream::ResponseHeaders::~ResponseHeaders() { data_ = NULL; }
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSocketStream::SocketStream(const GURL& url, Delegate* delegate)
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : delegate_(delegate),
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url_(url),
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      max_pending_send_allowed_(kMaxPendingSendAllowed),
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_(STATE_NONE),
5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      host_resolver_(NULL),
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      cert_verifier_(NULL),
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      http_auth_handler_factory_(NULL),
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      factory_(ClientSocketFactory::GetDefaultFactory()),
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      proxy_mode_(kDirectConnection),
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      proxy_url_(url),
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      pac_request_(NULL),
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          io_callback_(this, &SocketStream::OnIOCompleted)),
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          read_callback_(this, &SocketStream::OnReadCompleted)),
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          write_callback_(this, &SocketStream::OnWriteCompleted)),
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      read_buf_(NULL),
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_(NULL),
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      current_write_buf_(NULL),
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_offset_(0),
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_size_(0),
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      closing_(false),
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      server_closed_(false),
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      metrics_(new SocketStreamMetrics(url)) {
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current()) <<
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must exist";
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must be TYPE_IO";
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(delegate_);
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSocketStream::UserData* SocketStream::GetUserData(
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const void* key) const {
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UserDataMap::const_iterator found = user_data_.find(key);
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (found != user_data_.end())
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return found->second.get();
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NULL;
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::SetUserData(const void* key, UserData* data) {
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_data_[key] = linked_ptr<UserData>(data);
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SocketStream::is_secure() const {
9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return url_.SchemeIs("wss");
9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::set_context(URLRequestContext* context) {
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<URLRequestContext> prev_context = context_;
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  context_ = context;
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (prev_context != context) {
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (prev_context && pac_request_) {
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prev_context->proxy_service()->CancelPacRequest(pac_request_);
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      pac_request_ = NULL;
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net_log_.EndEvent(NetLog::TYPE_REQUEST_ALIVE, NULL);
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net_log_ = BoundNetLog();
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (context) {
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net_log_ = BoundNetLog::Make(
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          context->net_log(),
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NetLog::SOURCE_SOCKET_STREAM);
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE, NULL);
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (context_) {
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    host_resolver_ = context_->host_resolver();
12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cert_verifier_ = context_->cert_verifier();
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    http_auth_handler_factory_ = context_->http_auth_handler_factory();
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::Connect() {
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current()) <<
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must exist";
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must be TYPE_IO";
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (context_)
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ssl_config_service()->GetSSLConfig(&ssl_config_);
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(next_state_, STATE_NONE);
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddRef();  // Released in Finish()
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Open a connection asynchronously, so that delegate won't be called
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // back before returning Connect().
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_RESOLVE_PROXY;
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.BeginEvent(
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NetLog::TYPE_SOCKET_STREAM_CONNECT,
143513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      make_scoped_refptr(
144513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          new NetLogStringParameter("url", url_.possibly_invalid_spec())));
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      FROM_HERE,
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NewRunnableMethod(this, &SocketStream::DoLoop, OK));
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SocketStream::SendData(const char* data, int len) {
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current()) <<
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must exist";
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must be TYPE_IO";
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!socket_.get() || !socket_->IsConnected() || next_state_ == STATE_NONE)
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (write_buf_) {
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int current_amount_send = write_buf_size_ - write_buf_offset_;
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (PendingDataQueue::const_iterator iter = pending_write_bufs_.begin();
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         iter != pending_write_bufs_.end();
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         ++iter)
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      current_amount_send += (*iter)->size();
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current_amount_send += len;
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (current_amount_send > max_pending_send_allowed_)
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    pending_write_bufs_.push_back(make_scoped_refptr(
169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        new IOBufferWithSize(len)));
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    memcpy(pending_write_bufs_.back()->data(), data, len);
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!current_write_buf_);
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_buf_ = new IOBuffer(len);
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memcpy(write_buf_->data(), data, len);
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_buf_size_ = len;
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_buf_offset_ = 0;
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Send pending data asynchronously, so that delegate won't be called
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // back before returning SendData().
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      FROM_HERE,
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NewRunnableMethod(this, &SocketStream::DoLoop, OK));
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::Close() {
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";
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If next_state_ is STATE_NONE, the socket was not opened, or already
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // closed.  So, return immediately.
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise, it might call Finish() more than once, so breaks balance
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // of AddRef() and Release() in Connect() and Finish(), respectively.
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (next_state_ == STATE_NONE)
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      FROM_HERE,
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NewRunnableMethod(this, &SocketStream::DoClose));
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::RestartWithAuth(
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const string16& username, const string16& password) {
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current()) <<
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must exist";
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must be TYPE_IO";
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(auth_handler_.get());
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!socket_.get()) {
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Socket is closed before restarting with auth.";
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (auth_identity_.invalid) {
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Update the username/password.
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_.source = HttpAuth::IDENT_SRC_EXTERNAL;
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_.invalid = false;
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_.username = username;
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_.password = password;
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      FROM_HERE,
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NewRunnableMethod(this, &SocketStream::DoRestartWithAuth));
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DetachDelegate() {
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!delegate_)
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delegate_ = NULL;
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't need to send pending data when client detach the delegate.
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_write_bufs_.clear();
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Close();
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SocketStream::SetHostResolver(HostResolver* host_resolver) {
23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(host_resolver);
23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  host_resolver_ = host_resolver;
24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SocketStream::SetClientSocketFactory(
24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ClientSocketFactory* factory) {
24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(factory);
24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  factory_ = factory;
24672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
24772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
24872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSocketStream::~SocketStream() {
24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  set_context(NULL);
25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!delegate_);
25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!pac_request_);
25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
25472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SocketStream::CopyAddrInfo(struct addrinfo* head) {
25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  addresses_.Copy(head, true);
25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SocketStream::DoClose() {
25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  closing_ = true;
26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If next_state_ is STATE_TCP_CONNECT, it's waiting other socket establishing
26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // connection.  If next_state_ is STATE_AUTH_REQUIRED, it's waiting for
26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // restarting.  In these states, we'll close the SocketStream now.
26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (next_state_ == STATE_TCP_CONNECT || next_state_ == STATE_AUTH_REQUIRED) {
26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DoLoop(ERR_ABORTED);
26572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If next_state_ is STATE_READ_WRITE, we'll run DoLoop and close
26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // the SocketStream.
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If it's writing now, we should defer the closing after the current
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // writing is completed.
27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (next_state_ == STATE_READ_WRITE && !current_write_buf_)
27272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DoLoop(ERR_ABORTED);
27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // In other next_state_, we'll wait for callback of other APIs, such as
27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // ResolveProxy().
27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::Finish(int result) {
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(MessageLoop::current()) <<
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must exist";
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "The current MessageLoop must be TYPE_IO";
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_LE(result, OK);
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == OK)
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = ERR_CONNECTION_CLOSED;
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(next_state_, STATE_NONE);
28772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DVLOG(1) << "Finish result=" << ErrorToString(result);
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate_)
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate_->OnError(this, result);
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnClose();
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Delegate* delegate = delegate_;
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delegate_ = NULL;
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate) {
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate->OnClose(this);
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Release();
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DidEstablishConnection() {
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!socket_.get() || !socket_->IsConnected()) {
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_CONNECTION_FAILED;
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_READ_WRITE;
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnConnected();
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.EndEvent(NetLog::TYPE_SOCKET_STREAM_CONNECT, NULL);
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate_)
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate_->OnConnected(this, max_pending_send_allowed_);
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return OK;
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DidReceiveData(int result) {
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(read_buf_);
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(result, 0);
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_RECEIVED, NULL);
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int len = result;
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnRead(len);
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate_) {
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Notify recevied data to delegate.
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate_->OnReceivedData(this, read_buf_->data(), len);
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_buf_ = NULL;
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OK;
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DidSendData(int result) {
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(result, 0);
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_SENT, NULL);
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int len = result;
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnWrite(len);
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  current_write_buf_ = NULL;
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate_)
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate_->OnSentData(this, len);
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int remaining_size = write_buf_size_ - write_buf_offset_ - len;
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (remaining_size == 0) {
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!pending_write_bufs_.empty()) {
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_size_ = pending_write_bufs_.front()->size();
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_ = pending_write_bufs_.front();
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      pending_write_bufs_.pop_front();
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_size_ = 0;
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_buf_ = NULL;
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_buf_offset_ = 0;
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_buf_offset_ += len;
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OK;
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::OnIOCompleted(int result) {
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DoLoop(result);
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::OnReadCompleted(int result) {
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == 0) {
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // 0 indicates end-of-file, so socket was closed.
3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Don't close the socket if it's still writing.
3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    server_closed_ = true;
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else if (result > 0 && read_buf_) {
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = DidReceiveData(result);
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DoLoop(result);
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::OnWriteCompleted(int result) {
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result >= 0 && write_buf_) {
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = DidSendData(result);
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DoLoop(result);
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DoLoop(int result) {
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If context was not set, close immediately.
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!context_)
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (next_state_ == STATE_NONE)
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  do {
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    State state = next_state_;
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_NONE;
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    switch (state) {
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_RESOLVE_PROXY:
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoResolveProxy();
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_RESOLVE_PROXY_COMPLETE:
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoResolveProxyComplete(result);
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_RESOLVE_HOST:
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoResolveHost();
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_RESOLVE_HOST_COMPLETE:
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoResolveHostComplete(result);
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_TCP_CONNECT:
4043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        result = DoTcpConnect(result);
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_TCP_CONNECT_COMPLETE:
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoTcpConnectComplete(result);
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_WRITE_TUNNEL_HEADERS:
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoWriteTunnelHeaders();
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_WRITE_TUNNEL_HEADERS_COMPLETE:
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoWriteTunnelHeadersComplete(result);
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_READ_TUNNEL_HEADERS:
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoReadTunnelHeaders();
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_READ_TUNNEL_HEADERS_COMPLETE:
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoReadTunnelHeadersComplete(result);
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_SOCKS_CONNECT:
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoSOCKSConnect();
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_SOCKS_CONNECT_COMPLETE:
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoSOCKSConnectComplete(result);
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_SSL_CONNECT:
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(OK, result);
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoSSLConnect();
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_SSL_CONNECT_COMPLETE:
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoSSLConnectComplete(result);
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_READ_WRITE:
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DoReadWrite(result);
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
4403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case STATE_AUTH_REQUIRED:
4413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // It might be called when DoClose is called while waiting in
4423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // STATE_AUTH_REQUIRED.
4433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        Finish(result);
4443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return;
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case STATE_CLOSE:
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_LE(result, OK);
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        Finish(result);
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      default:
4503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        NOTREACHED() << "bad state " << state;
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        Finish(result);
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If the connection is not established yet and had actual errors,
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // close the connection.
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) {
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DCHECK_EQ(next_state_, STATE_CLOSE);
45872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      net_log_.EndEventWithNetErrorCode(
45972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          NetLog::TYPE_SOCKET_STREAM_CONNECT, result);
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } while (result != ERR_IO_PENDING);
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveProxy() {
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!pac_request_);
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!proxy_url_.is_valid()) {
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_INVALID_ARGUMENT;
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return proxy_service()->ResolveProxy(
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      proxy_url_, &proxy_info_, &io_callback_, &pac_request_, net_log_);
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveProxyComplete(int result) {
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  pac_request_ = NULL;
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result != OK) {
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Failed to resolve proxy: " << result;
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (delegate_)
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      delegate_->OnError(this, result);
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    proxy_info_.UseDirect();
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_info_.is_direct()) {
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If proxy was not found for original URL (i.e. websocket URL),
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // try again with https URL, like Safari implementation.
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Note that we don't want to use http proxy, because we'll use tunnel
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // proxy using CONNECT method, which is used by https proxy.
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!proxy_url_.SchemeIs("https")) {
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      const std::string scheme = "https";
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      GURL::Replacements repl;
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      repl.SetSchemeStr(scheme);
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      proxy_url_ = url_.ReplaceComponents(repl);
495731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      DVLOG(1) << "Try https proxy: " << proxy_url_;
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_RESOLVE_PROXY;
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return OK;
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (proxy_info_.is_empty()) {
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // No proxies/direct to choose from. This happens when we don't support any
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // of the proxies in the returned list.
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ERR_NO_SUPPORTED_PROXIES;
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_state_ = STATE_RESOLVE_HOST;
508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return OK;
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveHost() {
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_RESOLVE_HOST_COMPLETE;
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!proxy_info_.is_empty());
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_info_.is_direct())
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    proxy_mode_ = kDirectConnection;
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else if (proxy_info_.proxy_server().is_socks())
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    proxy_mode_ = kSOCKSProxy;
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    proxy_mode_ = kTunnelProxy;
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Determine the host and port to connect to.
5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostPortPair host_port_pair;
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_mode_ != kDirectConnection) {
5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    host_port_pair = proxy_info_.proxy_server().host_port_pair();
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
5273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    host_port_pair = HostPortPair::FromURL(url_);
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostResolver::RequestInfo resolve_info(host_port_pair);
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
532731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(host_resolver_);
533731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  resolver_.reset(new SingleRequestHostResolver(host_resolver_));
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return resolver_->Resolve(resolve_info, &addresses_, &io_callback_,
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            net_log_);
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveHostComplete(int result) {
5393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (result == OK && delegate_) {
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_TCP_CONNECT;
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    result = delegate_->OnStartOpenConnection(this, &io_callback_);
54272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (result == ERR_IO_PENDING)
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      metrics_->OnWaitConnection();
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(ukai): if error occured, reconsider proxy after error.
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint SocketStream::DoTcpConnect(int result) {
5523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (result != OK) {
5533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    next_state_ = STATE_CLOSE;
5543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return result;
5553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_TCP_CONNECT_COMPLETE;
557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(factory_);
558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  socket_.reset(factory_->CreateTransportClientSocket(addresses_,
559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                      net_log_.net_log(),
560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                      net_log_.source()));
561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnStartConnection();
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return socket_->Connect(&io_callback_);
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoTcpConnectComplete(int result) {
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(ukai): if error occured, reconsider proxy after error.
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result != OK) {
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_mode_ == kTunnelProxy)
573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_WRITE_TUNNEL_HEADERS;
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else if (proxy_mode_ == kSOCKSProxy)
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_SOCKS_CONNECT;
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else if (is_secure()) {
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_SSL_CONNECT;
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = DidEstablishConnection();
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoWriteTunnelHeaders() {
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kTunnelProxy, proxy_mode_);
586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_WRITE_TUNNEL_HEADERS_COMPLETE;
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!tunnel_request_headers_.get()) {
590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    metrics_->OnTunnelProxy();
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_request_headers_ = new RequestHeaders();
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_request_headers_bytes_sent_ = 0;
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (tunnel_request_headers_->headers_.empty()) {
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string authorization_headers;
596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!auth_handler_.get()) {
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Do preemptive authentication.
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      HttpAuthCache::Entry* entry = auth_cache_.LookupByPath(
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          ProxyAuthOrigin(), std::string());
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (entry) {
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        scoped_ptr<HttpAuthHandler> handler_preemptive;
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        int rv_create = http_auth_handler_factory_->
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            CreatePreemptiveAuthHandlerFromString(
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                entry->auth_challenge(), HttpAuth::AUTH_PROXY,
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                ProxyAuthOrigin(), entry->IncrementNonceCount(),
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                net_log_, &handler_preemptive);
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (rv_create == OK) {
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          auth_identity_.source = HttpAuth::IDENT_SRC_PATH_LOOKUP;
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          auth_identity_.invalid = false;
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          auth_identity_.username = entry->username();
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          auth_identity_.password = entry->password();
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          auth_handler_.swap(handler_preemptive);
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Support basic authentication scheme only, because we don't have
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // HttpRequestInfo.
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // TODO(ukai): Add support other authentication scheme.
62172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (auth_handler_.get() &&
62272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        auth_handler_->auth_scheme() == HttpAuth::AUTH_SCHEME_BASIC) {
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      HttpRequestInfo request_info;
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::string auth_token;
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int rv = auth_handler_->GenerateAuthToken(
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          &auth_identity_.username,
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          &auth_identity_.password,
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          &request_info,
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          NULL,
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          &auth_token);
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // TODO(cbentzel): Support async auth handlers.
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DCHECK_NE(ERR_IO_PENDING, rv);
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (rv != OK)
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return rv;
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      authorization_headers.append(
636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY) +
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          ": " + auth_token + "\r\n");
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    tunnel_request_headers_->headers_ = base::StringPrintf(
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        "CONNECT %s HTTP/1.1\r\n"
642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        "Host: %s\r\n"
643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        "Proxy-Connection: keep-alive\r\n",
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        GetHostAndPort(url_).c_str(),
645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        GetHostAndOptionalPort(url_).c_str());
646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!authorization_headers.empty())
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      tunnel_request_headers_->headers_ += authorization_headers;
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_request_headers_->headers_ += "\r\n";
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_request_headers_->SetDataOffset(tunnel_request_headers_bytes_sent_);
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int buf_len = static_cast<int>(tunnel_request_headers_->headers_.size() -
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 tunnel_request_headers_bytes_sent_);
653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(buf_len, 0);
654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return socket_->Write(tunnel_request_headers_, buf_len, &io_callback_);
655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoWriteTunnelHeadersComplete(int result) {
658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kTunnelProxy, proxy_mode_);
659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result < 0) {
661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_request_headers_bytes_sent_ += result;
666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (tunnel_request_headers_bytes_sent_ <
667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      tunnel_request_headers_->headers_.size())
668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_WRITE_TUNNEL_HEADERS;
669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_READ_TUNNEL_HEADERS;
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return OK;
672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoReadTunnelHeaders() {
675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kTunnelProxy, proxy_mode_);
676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_READ_TUNNEL_HEADERS_COMPLETE;
678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!tunnel_response_headers_.get()) {
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_response_headers_ = new ResponseHeaders();
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_response_headers_capacity_ = kMaxTunnelResponseHeadersSize;
682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_response_headers_->Realloc(tunnel_response_headers_capacity_);
683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tunnel_response_headers_len_ = 0;
684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int buf_len = tunnel_response_headers_capacity_ -
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      tunnel_response_headers_len_;
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_response_headers_->SetDataOffset(tunnel_response_headers_len_);
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK(tunnel_response_headers_->data());
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return socket_->Read(tunnel_response_headers_, buf_len, &io_callback_);
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoReadTunnelHeadersComplete(int result) {
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kTunnelProxy, proxy_mode_);
696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result < 0) {
698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == 0) {
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // 0 indicates end-of-file, so socket was closed.
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_CONNECTION_CLOSED;
706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_response_headers_len_ += result;
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(tunnel_response_headers_len_ <= tunnel_response_headers_capacity_);
710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int eoh = HttpUtil::LocateEndOfHeaders(
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      tunnel_response_headers_->headers(), tunnel_response_headers_len_, 0);
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (eoh == -1) {
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (tunnel_response_headers_len_ >= kMaxTunnelResponseHeadersSize) {
715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_CLOSE;
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_RESPONSE_HEADERS_TOO_BIG;
717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_READ_TUNNEL_HEADERS;
720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return OK;
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // DidReadResponseHeaders
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<HttpResponseHeaders> headers;
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  headers = new HttpResponseHeaders(
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      HttpUtil::AssembleRawHeaders(tunnel_response_headers_->headers(), eoh));
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Require the "HTTP/1.x" status line.
728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_TUNNEL_CONNECTION_FAILED;
730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (headers->response_code()) {
732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case 200:  // OK
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (is_secure()) {
734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DCHECK_EQ(eoh, tunnel_response_headers_len_);
735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        next_state_ = STATE_SSL_CONNECT;
736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        result = DidEstablishConnection();
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (result < 0) {
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          next_state_ = STATE_CLOSE;
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return result;
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if ((eoh < tunnel_response_headers_len_) && delegate_)
743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          delegate_->OnReceivedData(
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              this, tunnel_response_headers_->headers() + eoh,
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              tunnel_response_headers_len_ - eoh);
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return OK;
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case 407:  // Proxy Authentication Required.
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      result = HandleAuthChallenge(headers.get());
750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (result == ERR_PROXY_AUTH_UNSUPPORTED &&
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          auth_handler_.get() && delegate_) {
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK(!proxy_info_.is_empty());
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_info_ = new AuthChallengeInfo;
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_info_->is_proxy = true;
755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_info_->host_and_port =
7563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            ASCIIToWide(proxy_info_.proxy_server().host_port_pair().ToString());
75772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        auth_info_->scheme = ASCIIToWide(
75872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            HttpAuth::SchemeToString(auth_handler_->auth_scheme()));
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        auth_info_->realm = ASCIIToWide(auth_handler_->realm());
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // Wait until RestartWithAuth or Close is called.
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        MessageLoop::current()->PostTask(
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            FROM_HERE,
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            NewRunnableMethod(this, &SocketStream::DoAuthRequired));
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        next_state_ = STATE_AUTH_REQUIRED;
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return ERR_IO_PENDING;
766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_CLOSE;
771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_TUNNEL_CONNECTION_FAILED;
772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSOCKSConnect() {
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kSOCKSProxy, proxy_mode_);
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ClientSocket* s = socket_.release();
7803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostResolver::RequestInfo req_info(HostPortPair::FromURL(url_));
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!proxy_info_.is_empty());
783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5)
784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    s = new SOCKS5ClientSocket(s, req_info);
785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
786731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    s = new SOCKSClientSocket(s, req_info, host_resolver_);
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_.reset(s);
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnSOCKSProxy();
789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return socket_->Connect(&io_callback_);
790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSOCKSConnectComplete(int result) {
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(kSOCKSProxy, proxy_mode_);
794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == OK) {
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (is_secure())
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_SSL_CONNECT;
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    else
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      result = DidEstablishConnection();
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSSLConnect() {
807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(factory_);
808731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO(agl): look into plumbing SSLHostInfo here.
8094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  socket_.reset(factory_->CreateSSLClientSocket(socket_.release(),
8104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                                HostPortPair::FromURL(url_),
8114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                                ssl_config_,
81221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                                NULL /* ssl_host_info */,
81321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                                cert_verifier_));
814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_SSL_CONNECT_COMPLETE;
815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  metrics_->OnSSLConnection();
816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return socket_->Connect(&io_callback_);
817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSSLConnectComplete(int result) {
820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (IsCertificateError(result)) {
821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (socket_->IsConnectedAndIdle()) {
822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      result = HandleCertificateError(result);
823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // SSLClientSocket for Mac will report socket is not connected,
825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // if it returns cert verification error.  It didn't perform
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // SSLHandshake yet.
827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // So, we should restart establishing connection with the
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // certificate in allowed bad certificates in |ssl_config_|.
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // See also net/http/http_network_transaction.cc
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      //  HandleCertificateError() and RestartIgnoringLastError().
831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      SSLClientSocket* ssl_socket =
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        reinterpret_cast<SSLClientSocket*>(socket_.get());
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      SSLInfo ssl_info;
834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ssl_socket->GetSSLInfo(&ssl_info);
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (ssl_config_.IsAllowedBadCert(ssl_info.cert)) {
836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // If we already have the certificate in the set of allowed bad
837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // certificates, we did try it and failed again, so we should not
838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // retry again: the connection should fail at last.
839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        next_state_ = STATE_CLOSE;
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return result;
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Add the bad certificate to the set of allowed certificates in the
843ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // SSL config object.
844ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SSLConfig::CertAndStatus bad_cert;
845ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bad_cert.cert = ssl_info.cert;
846ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bad_cert.cert_status = ssl_info.cert_status;
847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ssl_config_.allowed_bad_certs.push_back(bad_cert);
848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Restart connection ignoring the bad certificate.
849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      socket_->Disconnect();
850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      socket_.reset();
851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_TCP_CONNECT;
852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return OK;
853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == OK)
857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = DidEstablishConnection();
858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoReadWrite(int result) {
864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result < OK) {
865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!socket_.get() || !socket_->IsConnected()) {
869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_state_ = STATE_CLOSE;
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_CONNECTION_CLOSED;
871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If client has requested close(), and there's nothing to write, then
874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // let's close the socket.
875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't care about receiving data after the socket is closed.
876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (closing_ && !write_buf_ && pending_write_bufs_.empty()) {
877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    socket_->Disconnect();
878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_state_ = STATE_CLOSE;
879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return OK;
880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_READ_WRITE;
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // If server already closed the socket, we don't try to read.
8853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!server_closed_) {
8863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!read_buf_) {
8873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // No read pending and server didn't close the socket.
8883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      read_buf_ = new IOBuffer(kReadBufferSize);
8893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      result = socket_->Read(read_buf_, kReadBufferSize, &read_callback_);
8903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (result > 0) {
8913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return DidReceiveData(result);
8923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      } else if (result == 0) {
8933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // 0 indicates end-of-file, so socket was closed.
8943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        next_state_ = STATE_CLOSE;
8953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        server_closed_ = true;
8963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return ERR_CONNECTION_CLOSED;
8973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
8983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // If read is pending, try write as well.
8993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Otherwise, return the result and do next loop (to close the
9003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // connection).
9013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (result != ERR_IO_PENDING) {
9023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        next_state_ = STATE_CLOSE;
9033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        server_closed_ = true;
9043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return result;
9053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
9073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Read is pending.
9083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(read_buf_);
909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (write_buf_ && !current_write_buf_) {
912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // No write pending.
913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current_write_buf_ = new DrainableIOBuffer(write_buf_, write_buf_size_);
914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current_write_buf_->SetOffset(write_buf_offset_);
915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = socket_->Write(current_write_buf_,
916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            current_write_buf_->BytesRemaining(),
917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            &write_callback_);
918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (result > 0) {
919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return DidSendData(result);
920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If write is not pending, return the result and do next loop (to close
922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // the connection).
923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (result != 0 && result != ERR_IO_PENDING) {
924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      next_state_ = STATE_CLOSE;
925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return result;
926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We arrived here when both operation is pending.
931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_IO_PENDING;
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL SocketStream::ProxyAuthOrigin() const {
935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!proxy_info_.is_empty());
9363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return GURL("http://" +
9373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              proxy_info_.proxy_server().host_port_pair().ToString());
938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::HandleAuthChallenge(const HttpResponseHeaders* headers) {
941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  GURL auth_origin(ProxyAuthOrigin());
942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
943731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  VLOG(1) << "The proxy " << auth_origin << " requested auth";
944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(cbentzel): Since SocketStream only suppports basic authentication
9463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // right now, another challenge is always treated as a rejection.
9473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Ultimately this should be converted to use HttpAuthController like the
9483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // HttpNetworkTransaction has.
9493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (auth_handler_.get() && !auth_identity_.invalid) {
950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (auth_identity_.source != HttpAuth::IDENT_SRC_PATH_LOOKUP)
951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      auth_cache_.Remove(auth_origin,
952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         auth_handler_->realm(),
95372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                         auth_handler_->auth_scheme(),
954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         auth_identity_.username,
955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         auth_identity_.password);
956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    auth_handler_.reset();
957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_ = HttpAuth::Identity();
958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  auth_identity_.invalid = true;
96172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::set<HttpAuth::Scheme> disabled_schemes;
962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, headers,
963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                HttpAuth::AUTH_PROXY,
964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                auth_origin, disabled_schemes,
965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                net_log_, &auth_handler_);
966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!auth_handler_.get()) {
967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Can't perform auth to the proxy " << auth_origin;
968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_TUNNEL_CONNECTION_FAILED;
969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (auth_handler_->NeedsIdentity()) {
971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We only support basic authentication scheme now.
972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TODO(ukai): Support other authentication scheme.
97372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    HttpAuthCache::Entry* entry = auth_cache_.Lookup(
97472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        auth_origin, auth_handler_->realm(), HttpAuth::AUTH_SCHEME_BASIC);
975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (entry) {
976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      auth_identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      auth_identity_.invalid = false;
978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      auth_identity_.username = entry->username();
979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      auth_identity_.password = entry->password();
980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Restart with auth info.
981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ERR_PROXY_AUTH_UNSUPPORTED;
983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    auth_identity_.invalid = false;
985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_TUNNEL_CONNECTION_FAILED;
987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DoAuthRequired() {
990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (delegate_ && auth_info_.get())
991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delegate_->OnAuthRequired(this, auth_info_.get());
992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
99372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DoLoop(ERR_UNEXPECTED);
994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DoRestartWithAuth() {
997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED);
998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  auth_cache_.Add(ProxyAuthOrigin(),
999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  auth_handler_->realm(),
100072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                  auth_handler_->auth_scheme(),
1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  auth_handler_->challenge(),
1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  auth_identity_.username,
1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  auth_identity_.password,
1004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                  std::string());
1005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_request_headers_ = NULL;
1007c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_request_headers_bytes_sent_ = 0;
1008c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_response_headers_ = NULL;
1009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_response_headers_capacity_ = 0;
1010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tunnel_response_headers_len_ = 0;
1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  next_state_ = STATE_TCP_CONNECT;
1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DoLoop(OK);
1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::HandleCertificateError(int result) {
1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(ukai): handle cert error properly.
1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (result) {
1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ERR_CERT_COMMON_NAME_INVALID:
1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ERR_CERT_DATE_INVALID:
1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ERR_CERT_AUTHORITY_INVALID:
1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      result = OK;
1023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
1028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSSLConfigService* SocketStream::ssl_config_service() const {
1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return context_->ssl_config_service();
1032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProxyService* SocketStream::proxy_service() const {
1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return context_->proxy_service();
1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
1039