15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(ukai): code is similar with http_network_transaction.cc.  We should
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   think about ways to share code, if possible.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket_stream/socket_stream.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
195e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
205e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/auth.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/load_flags.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/host_resolver.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth_controller.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_headers.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_info.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_stream_factory.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_transaction_factory.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_factory.h"
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "net/socket/client_socket_handle.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socks5_client_socket.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socks_client_socket.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_client_socket.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/tcp_client_socket.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket_stream/socket_stream_metrics.h"
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_cert_request_info.h"
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_info.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request_context.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMaxPendingSendAllowed = 32768;  // 32 kilobytes.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kReadBufferSize = 4096;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::Delegate::OnStartOpenConnection(
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SocketStream* socket, const CompletionCallback& callback) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::Delegate::OnAuthRequired(SocketStream* socket,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            AuthChallengeInfo* auth_info) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // By default, no credential is available and close the connection.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket->Close();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::Delegate::OnSSLCertificateError(
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SocketStream* socket,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLInfo& ssl_info,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool fatal) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket->CancelWithSSLError(ssl_info);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SocketStream::Delegate::CanGetCookies(SocketStream* socket,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const GURL& url) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SocketStream::Delegate::CanSetCookie(SocketStream* request,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const GURL& url,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const std::string& cookie_line,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          CookieOptions* options) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SocketStream::ResponseHeaders::ResponseHeaders() : IOBuffer() {}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::ResponseHeaders::Realloc(size_t new_size) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size)));
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SocketStream::ResponseHeaders::~ResponseHeaders() { data_ = NULL; }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SocketStream::SocketStream(const GURL& url, Delegate* delegate,
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           URLRequestContext* context,
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           CookieStore* cookie_store)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : delegate_(delegate),
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_(url),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_pending_send_allowed_(kMaxPendingSendAllowed),
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      context_(context),
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_(STATE_NONE),
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      factory_(ClientSocketFactory::GetDefaultFactory()),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_mode_(kDirectConnection),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_url_(url),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pac_request_(NULL),
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      connection_(new ClientSocketHandle),
104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      privacy_mode_(PRIVACY_MODE_DISABLED),
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Unretained() is required; without it, Bind() creates a circular
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // dependency and the SocketStream object will not be freed.
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      io_callback_(base::Bind(&SocketStream::OnIOCompleted,
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              base::Unretained(this))),
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_buf_(NULL),
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_write_buf_(NULL),
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      waiting_for_write_completion_(false),
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      closing_(false),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_closed_(false),
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      metrics_(new SocketStreamMetrics(url)),
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      cookie_store_(cookie_store) {
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(base::MessageLoop::current())
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must exist";
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(base::MessageLoopForIO::IsCurrent())
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must be TYPE_IO";
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(delegate_);
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (context_) {
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!cookie_store_.get())
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      cookie_store_ = context_->cookie_store();
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net_log_ = BoundNetLog::Make(
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        context->net_log(),
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        NetLog::SOURCE_SOCKET_STREAM);
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE);
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SocketStream::UserData* SocketStream::GetUserData(
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* key) const {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UserDataMap::const_iterator found = user_data_.find(key);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found != user_data_.end())
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return found->second.get();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::SetUserData(const void* key, UserData* data) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_data_[key] = linked_ptr<UserData>(data);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SocketStream::is_secure() const {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url_.SchemeIs("wss");
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SocketStream::DetachContext() {
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!context_)
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (pac_request_) {
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    context_->proxy_service()->CancelPacRequest(pac_request_);
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    pac_request_ = NULL;
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  net_log_.EndEvent(NetLog::TYPE_REQUEST_ALIVE);
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  net_log_ = BoundNetLog();
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  context_ = NULL;
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  cookie_store_ = NULL;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SocketStream::CheckPrivacyMode() {
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (context_ && context_->network_delegate()) {
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    bool enable = context_->network_delegate()->CanEnablePrivacyMode(url_,
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                                     url_);
170e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    privacy_mode_ = enable ? PRIVACY_MODE_ENABLED : PRIVACY_MODE_DISABLED;
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Disable Channel ID if privacy mode is enabled.
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (enable)
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      server_ssl_config_.channel_id_enabled = false;
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::Connect() {
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(base::MessageLoop::current())
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must exist";
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(base::MessageLoopForIO::IsCurrent())
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must be TYPE_IO";
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (context_) {
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    context_->ssl_config_service()->GetSSLConfig(&server_ssl_config_);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_ssl_config_ = server_ssl_config_;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CheckPrivacyMode();
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(next_state_, STATE_NONE);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();  // Released in Finish()
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Open a connection asynchronously, so that delegate won't be called
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // back before returning Connect().
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_BEFORE_CONNECT;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetLog::TYPE_SOCKET_STREAM_CONNECT,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetLog::StringCallback("url", &url_.possibly_invalid_spec()));
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      FROM_HERE, base::Bind(&SocketStream::DoLoop, this, OK));
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SocketStream::GetTotalSizeOfPendingWriteBufs() const {
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t total_size = 0;
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (PendingDataQueue::const_iterator iter = pending_write_bufs_.begin();
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       iter != pending_write_bufs_.end();
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       ++iter)
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    total_size += (*iter)->size();
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return total_size;
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SocketStream::SendData(const char* data, int len) {
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(base::MessageLoop::current())
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must exist";
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(base::MessageLoopForIO::IsCurrent())
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must be TYPE_IO";
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_GT(len, 0);
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!connection_->socket() ||
2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !connection_->socket()->IsConnected() || next_state_ == STATE_NONE) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int total_buffered_bytes = len;
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (current_write_buf_.get()) {
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Since
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // - the purpose of this check is to limit the amount of buffer used by
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    //   this instance.
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // - the DrainableIOBuffer doesn't release consumed memory.
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // we need to use not BytesRemaining() but size() here.
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    total_buffered_bytes += current_write_buf_->size();
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  total_buffered_bytes += GetTotalSizeOfPendingWriteBufs();
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (total_buffered_bytes > max_pending_send_allowed_)
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(tyoshino): Split data into smaller chunks e.g. 8KiB to free consumed
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // buffer progressively
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pending_write_bufs_.push_back(make_scoped_refptr(
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new IOBufferWithSize(len)));
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memcpy(pending_write_bufs_.back()->data(), data, len);
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If current_write_buf_ is not NULL, it means that a) there's ongoing write
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // operation or b) the connection is being closed. If a), the buffer we just
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // pushed will be automatically handled when the completion callback runs
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the loop, and therefore we don't need to enqueue DoLoop(). If b), it's ok
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to do nothing. If current_write_buf_ is NULL, to make sure DoLoop() is
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // ran soon, enequeue it.
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!current_write_buf_.get()) {
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Send pending data asynchronously, so that delegate won't be called
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // back before returning from SendData().
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        FROM_HERE, base::Bind(&SocketStream::DoLoop, this, OK));
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::Close() {
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(base::MessageLoop::current())
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must exist";
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(base::MessageLoopForIO::IsCurrent())
26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must be TYPE_IO";
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If next_state_ is STATE_NONE, the socket was not opened, or already
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // closed.  So, return immediately.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, it might call Finish() more than once, so breaks balance
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of AddRef() and Release() in Connect() and Finish(), respectively.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_state_ == STATE_NONE)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      FROM_HERE, base::Bind(&SocketStream::DoClose, this));
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::RestartWithAuth(const AuthCredentials& credentials) {
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(base::MessageLoop::current())
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must exist";
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(base::MessageLoopForIO::IsCurrent())
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must be TYPE_IO";
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(proxy_auth_controller_.get());
2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!connection_->socket()) {
2797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DVLOG(1) << "Socket is closed before restarting with auth.";
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxy_auth_controller_->ResetAuth(credentials);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      FROM_HERE, base::Bind(&SocketStream::DoRestartWithAuth, this));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::DetachDelegate() {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!delegate_)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_ = NULL;
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Prevent the rest of the function from executing if we are being called from
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // within Finish().
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (next_state_ == STATE_NONE)
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.AddEvent(NetLog::TYPE_CANCELLED);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't need to send pending data when client detach the delegate.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_write_bufs_.clear();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Close();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ProxyServer& SocketStream::proxy_server() const {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return proxy_info_.proxy_server();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::SetClientSocketFactory(
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClientSocketFactory* factory) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(factory);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  factory_ = factory;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::CancelWithError(int error) {
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      FROM_HERE, base::Bind(&SocketStream::DoLoop, this, error));
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::CancelWithSSLError(const SSLInfo& ssl_info) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelWithError(MapCertStatusToNetError(ssl_info.cert_status));
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::ContinueDespiteError() {
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      FROM_HERE, base::Bind(&SocketStream::DoLoop, this, OK));
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SocketStream::~SocketStream() {
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DetachContext();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!delegate_);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!pac_request_);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SocketStream::RequestHeaders::~RequestHeaders() { data_ = NULL; }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::set_addresses(const AddressList& addresses) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addresses_ = addresses;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::DoClose() {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  closing_ = true;
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If next_state_ is:
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // - STATE_TCP_CONNECT_COMPLETE, it's waiting other socket establishing
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   connection.
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // - STATE_AUTH_REQUIRED, it's waiting for restarting.
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // - STATE_RESOLVE_PROTOCOL_COMPLETE, it's waiting for delegate_ to finish
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   OnStartOpenConnection method call
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // In these states, we'll close the SocketStream now.
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (next_state_ == STATE_TCP_CONNECT_COMPLETE ||
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      next_state_ == STATE_AUTH_REQUIRED ||
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      next_state_ == STATE_RESOLVE_PROTOCOL_COMPLETE) {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoLoop(ERR_ABORTED);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If next_state_ is STATE_READ_WRITE, we'll run DoLoop and close
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the SocketStream.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If it's writing now, we should defer the closing after the current
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // writing is completed.
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (next_state_ == STATE_READ_WRITE && !current_write_buf_.get())
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoLoop(ERR_ABORTED);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In other next_state_, we'll wait for callback of other APIs, such as
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ResolveProxy().
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::Finish(int result) {
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(base::MessageLoop::current())
36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must exist";
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(base::MessageLoopForIO::IsCurrent())
36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      << "The current base::MessageLoop must be TYPE_IO";
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(result, OK);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = ERR_CONNECTION_CLOSED;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(next_state_, STATE_NONE);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Finish result=" << ErrorToString(result);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metrics_->OnClose();
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (result != ERR_CONNECTION_CLOSED && delegate_)
37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    delegate_->OnError(this, result);
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (result != ERR_PROTOCOL_SWITCHED && delegate_)
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    delegate_->OnClose(this);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_ = NULL;
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DidEstablishConnection() {
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!connection_->socket() || !connection_->socket()->IsConnected()) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CONNECTION_FAILED;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_READ_WRITE;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metrics_->OnConnected();
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEvent(NetLog::TYPE_SOCKET_STREAM_CONNECT);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->OnConnected(this, max_pending_send_allowed_);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DidReceiveData(int result) {
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(read_buf_.get());
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(result, 0);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_RECEIVED);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = result;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metrics_->OnRead(len);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Notify recevied data to delegate.
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->OnReceivedData(this, read_buf_->data(), len);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buf_ = NULL;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SocketStream::DidSendData(int result) {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(result, 0);
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(current_write_buf_.get());
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_SENT);
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int bytes_sent = result;
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  metrics_->OnWrite(bytes_sent);
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  current_write_buf_->DidConsume(result);
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (current_write_buf_->BytesRemaining())
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t bytes_freed = current_write_buf_->size();
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_write_buf_ = NULL;
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We freed current_write_buf_ and this instance is now able to accept more
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // data via SendData() (note that DidConsume() doesn't free consumed memory).
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We can tell that to delegate_ by calling OnSentData().
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_)
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    delegate_->OnSentData(this, bytes_freed);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::OnIOCompleted(int result) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoLoop(result);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::OnReadCompleted(int result) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == 0) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 0 indicates end-of-file, so socket was closed.
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't close the socket if it's still writing.
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_closed_ = true;
450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (result > 0 && read_buf_.get()) {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = DidReceiveData(result);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoLoop(result);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::OnWriteCompleted(int result) {
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  waiting_for_write_completion_ = false;
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (result > 0) {
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DidSendData(result);
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    result = OK;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoLoop(result);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::DoLoop(int result) {
46668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (next_state_ == STATE_NONE)
46768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
46868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If context was not set, close immediately.
470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!context_)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_state_;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_NONE;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_BEFORE_CONNECT:
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, result);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoBeforeConnect();
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_BEFORE_CONNECT_COMPLETE:
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoBeforeConnectComplete(result);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_RESOLVE_PROXY:
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, result);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoResolveProxy();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_RESOLVE_PROXY_COMPLETE:
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoResolveProxyComplete(result);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_RESOLVE_HOST:
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, result);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoResolveHost();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_RESOLVE_HOST_COMPLETE:
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoResolveHostComplete(result);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_RESOLVE_PROTOCOL:
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoResolveProtocol(result);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_RESOLVE_PROTOCOL_COMPLETE:
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoResolveProtocolComplete(result);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_TCP_CONNECT:
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoTcpConnect(result);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_TCP_CONNECT_COMPLETE:
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoTcpConnectComplete(result);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_GENERATE_PROXY_AUTH_TOKEN:
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoGenerateProxyAuthToken();
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE:
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoGenerateProxyAuthTokenComplete(result);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_WRITE_TUNNEL_HEADERS:
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, result);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoWriteTunnelHeaders();
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_WRITE_TUNNEL_HEADERS_COMPLETE:
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoWriteTunnelHeadersComplete(result);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_READ_TUNNEL_HEADERS:
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, result);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoReadTunnelHeaders();
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_READ_TUNNEL_HEADERS_COMPLETE:
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoReadTunnelHeadersComplete(result);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SOCKS_CONNECT:
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, result);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoSOCKSConnect();
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SOCKS_CONNECT_COMPLETE:
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoSOCKSConnectComplete(result);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SECURE_PROXY_CONNECT:
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, result);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoSecureProxyConnect();
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SECURE_PROXY_CONNECT_COMPLETE:
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoSecureProxyConnectComplete(result);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SECURE_PROXY_HANDLE_CERT_ERROR:
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoSecureProxyHandleCertError(result);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SECURE_PROXY_HANDLE_CERT_ERROR_COMPLETE:
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoSecureProxyHandleCertErrorComplete(result);
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SSL_CONNECT:
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, result);
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoSSLConnect();
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SSL_CONNECT_COMPLETE:
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoSSLConnectComplete(result);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SSL_HANDLE_CERT_ERROR:
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoSSLHandleCertError(result);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SSL_HANDLE_CERT_ERROR_COMPLETE:
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoSSLHandleCertErrorComplete(result);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_READ_WRITE:
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DoReadWrite(result);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_AUTH_REQUIRED:
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // It might be called when DoClose is called while waiting in
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // STATE_AUTH_REQUIRED.
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Finish(result);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_CLOSE:
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_LE(result, OK);
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Finish(result);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "bad state " << state;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Finish(result);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (state == STATE_RESOLVE_PROTOCOL && result == ERR_PROTOCOL_SWITCHED)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the connection is not established yet and had actual errors,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // record the error.  In next iteration, it will close the connection.
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.EndEventWithNetErrorCode(
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NetLog::TYPE_SOCKET_STREAM_CONNECT, result);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (result != ERR_IO_PENDING);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoBeforeConnect() {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_BEFORE_CONNECT_COMPLETE;
593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!context_ || !context_->network_delegate())
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = context_->network_delegate()->NotifyBeforeSocketStreamConnect(
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, io_callback_);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK && result != ERR_IO_PENDING)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoBeforeConnectComplete(int result) {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, result);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_RESOLVE_PROXY;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoResolveProxy() {
616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(context_);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!pac_request_);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proxy_url_.is_valid()) {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_INVALID_ARGUMENT;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(toyoshim): Check server advertisement of SPDY through the HTTP
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Alternate-Protocol header, then switch to SPDY if SPDY is available.
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Usually we already have a session to the SPDY server because JavaScript
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // running WebSocket itself would be served by SPDY. But, in some situation
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (E.g. Used by Chrome Extensions or used for cross origin connection), this
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // connection might be the first one. At that time, we should check
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Alternate-Protocol header here for ws:// or TLS NPN extension for wss:// .
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return context_->proxy_service()->ResolveProxy(
634116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      proxy_url_, net::LOAD_NORMAL, &proxy_info_, io_callback_, &pac_request_,
635116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NULL, net_log_);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoResolveProxyComplete(int result) {
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pac_request_ = NULL;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK) {
6417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DVLOG(1) << "Failed to resolve proxy: " << result;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate_)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->OnError(this, result);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_info_.UseDirect();
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proxy_info_.is_direct()) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If proxy was not found for original URL (i.e. websocket URL),
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // try again with https URL, like Safari implementation.
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that we don't want to use http proxy, because we'll use tunnel
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // proxy using CONNECT method, which is used by https proxy.
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!proxy_url_.SchemeIs("https")) {
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string scheme = "https";
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL::Replacements repl;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      repl.SetSchemeStr(scheme);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_url_ = url_.ReplaceComponents(repl);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "Try https proxy: " << proxy_url_;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_RESOLVE_PROXY;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return OK;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proxy_info_.is_empty()) {
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No proxies/direct to choose from. This happens when we don't support any
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of the proxies in the returned list.
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_NO_SUPPORTED_PROXIES;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_RESOLVE_HOST;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoResolveHost() {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_RESOLVE_HOST_COMPLETE;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!proxy_info_.is_empty());
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proxy_info_.is_direct())
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_mode_ = kDirectConnection;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (proxy_info_.proxy_server().is_socks())
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_mode_ = kSOCKSProxy;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_mode_ = kTunnelProxy;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine the host and port to connect to.
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostPortPair host_port_pair;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proxy_mode_ != kDirectConnection) {
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_port_pair = proxy_info_.proxy_server().host_port_pair();
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_port_pair = HostPortPair::FromURL(url_);
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostResolver::RequestInfo resolve_info(host_port_pair);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(context_->host_resolver());
694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  resolver_.reset(new SingleRequestHostResolver(context_->host_resolver()));
6953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return resolver_->Resolve(resolve_info,
6963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                            DEFAULT_PRIORITY,
6973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                            &addresses_,
6983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                            base::Bind(&SocketStream::OnIOCompleted, this),
6993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                            net_log_);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoResolveHostComplete(int result) {
703868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (result == OK)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_RESOLVE_PROTOCOL;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(ukai): if error occured, reconsider proxy after error.
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoResolveProtocol(int result) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(OK, result);
713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!delegate_) {
715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    next_state_ = STATE_CLOSE;
716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return result;
717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_RESOLVE_PROTOCOL_COMPLETE;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = delegate_->OnStartOpenConnection(this, io_callback_);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERR_IO_PENDING)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    metrics_->OnWaitConnection();
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (result != OK && result != ERR_PROTOCOL_SWITCHED)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoResolveProtocolComplete(int result) {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, result);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERR_PROTOCOL_SWITCHED) {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    metrics_->OnCountWireProtocolType(
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamMetrics::WIRE_PROTOCOL_SPDY);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result == OK) {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_TCP_CONNECT;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    metrics_->OnCountWireProtocolType(
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamMetrics::WIRE_PROTOCOL_WEBSOCKET);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoTcpConnect(int result) {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_TCP_CONNECT_COMPLETE;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(factory_);
7523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  connection_->SetSocket(
7533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      factory_->CreateTransportClientSocket(addresses_,
7543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            net_log_.net_log(),
7553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            net_log_.source()));
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metrics_->OnStartConnection();
7573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return connection_->socket()->Connect(io_callback_);
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoTcpConnectComplete(int result) {
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(ukai): if error occured, reconsider proxy after error.
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proxy_mode_ == kTunnelProxy) {
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (proxy_info_.is_https())
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_SECURE_PROXY_CONNECT;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (proxy_mode_ == kSOCKSProxy) {
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SOCKS_CONNECT;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (is_secure()) {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SSL_CONNECT;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = DidEstablishConnection();
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoGenerateProxyAuthToken() {
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proxy_auth_controller_.get()) {
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(context_);
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(context_->http_transaction_factory());
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(context_->http_transaction_factory()->GetSession());
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpNetworkSession* session =
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_->http_transaction_factory()->GetSession();
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* scheme = proxy_info_.is_https() ? "https://" : "http://";
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL auth_url(scheme +
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  proxy_info_.proxy_server().host_port_pair().ToString());
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_auth_controller_ =
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new HttpAuthController(HttpAuth::AUTH_PROXY,
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               auth_url,
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               session->http_auth_cache(),
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               session->http_auth_handler_factory());
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request_info;
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info.url = url_;
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info.method = "CONNECT";
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return proxy_auth_controller_->MaybeGenerateAuthToken(
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &request_info, io_callback_, net_log_);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoGenerateProxyAuthTokenComplete(int result) {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK) {
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_WRITE_TUNNEL_HEADERS;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoWriteTunnelHeaders() {
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kTunnelProxy, proxy_mode_);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_WRITE_TUNNEL_HEADERS_COMPLETE;
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tunnel_request_headers_.get()) {
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    metrics_->OnCountConnectionType(SocketStreamMetrics::TUNNEL_CONNECTION);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tunnel_request_headers_ = new RequestHeaders();
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tunnel_request_headers_bytes_sent_ = 0;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tunnel_request_headers_->headers_.empty()) {
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestHeaders request_headers;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_headers.SetHeader("Host", GetHostAndOptionalPort(url_));
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_headers.SetHeader("Proxy-Connection", "keep-alive");
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (proxy_auth_controller_.get() && proxy_auth_controller_->HaveAuth())
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_auth_controller_->AddAuthorizationHeader(&request_headers);
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tunnel_request_headers_->headers_ = base::StringPrintf(
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "CONNECT %s HTTP/1.1\r\n"
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "%s",
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetHostAndPort(url_).c_str(),
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        request_headers.ToString().c_str());
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tunnel_request_headers_->SetDataOffset(tunnel_request_headers_bytes_sent_);
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int buf_len = static_cast<int>(tunnel_request_headers_->headers_.size() -
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 tunnel_request_headers_bytes_sent_);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(buf_len, 0);
8423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return connection_->socket()->Write(
8433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      tunnel_request_headers_.get(), buf_len, io_callback_);
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoWriteTunnelHeadersComplete(int result) {
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kTunnelProxy, proxy_mode_);
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0) {
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tunnel_request_headers_bytes_sent_ += result;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tunnel_request_headers_bytes_sent_ <
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tunnel_request_headers_->headers_.size()) {
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Handling a cert error or a client cert request requires reconnection.
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // DoWriteTunnelHeaders() will be called again.
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Thus |tunnel_request_headers_bytes_sent_| should be reset to 0 for
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sending |tunnel_request_headers_| correctly.
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tunnel_request_headers_bytes_sent_ = 0;
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_READ_TUNNEL_HEADERS;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoReadTunnelHeaders() {
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kTunnelProxy, proxy_mode_);
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_READ_TUNNEL_HEADERS_COMPLETE;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tunnel_response_headers_.get()) {
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tunnel_response_headers_ = new ResponseHeaders();
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tunnel_response_headers_capacity_ = kMaxTunnelResponseHeadersSize;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tunnel_response_headers_->Realloc(tunnel_response_headers_capacity_);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tunnel_response_headers_len_ = 0;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int buf_len = tunnel_response_headers_capacity_ -
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tunnel_response_headers_len_;
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tunnel_response_headers_->SetDataOffset(tunnel_response_headers_len_);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(tunnel_response_headers_->data());
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return connection_->socket()->Read(
8873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      tunnel_response_headers_.get(), buf_len, io_callback_);
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoReadTunnelHeadersComplete(int result) {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kTunnelProxy, proxy_mode_);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0) {
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == 0) {
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 0 indicates end-of-file, so socket was closed.
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CONNECTION_CLOSED;
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tunnel_response_headers_len_ += result;
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(tunnel_response_headers_len_ <= tunnel_response_headers_capacity_);
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int eoh = HttpUtil::LocateEndOfHeaders(
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tunnel_response_headers_->headers(), tunnel_response_headers_len_, 0);
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (eoh == -1) {
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tunnel_response_headers_len_ >= kMaxTunnelResponseHeadersSize) {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_CLOSE;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_RESPONSE_HEADERS_TOO_BIG;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_READ_TUNNEL_HEADERS;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DidReadResponseHeaders
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<HttpResponseHeaders> headers;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers = new HttpResponseHeaders(
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HttpUtil::AssembleRawHeaders(tunnel_response_headers_->headers(), eoh));
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Require the "HTTP/1.x" status line.
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_TUNNEL_CONNECTION_FAILED;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (headers->response_code()) {
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 200:  // OK
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (is_secure()) {
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(eoh, tunnel_response_headers_len_);
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_state_ = STATE_SSL_CONNECT;
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result = DidEstablishConnection();
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (result < 0) {
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          next_state_ = STATE_CLOSE;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return result;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((eoh < tunnel_response_headers_len_) && delegate_)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          delegate_->OnReceivedData(
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              this, tunnel_response_headers_->headers() + eoh,
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              tunnel_response_headers_len_ - eoh);
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return OK;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 407:  // Proxy Authentication Required.
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (proxy_mode_ != kTunnelProxy)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERR_UNEXPECTED_PROXY_AUTH;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = proxy_auth_controller_->HandleAuthChallenge(
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          headers, false, true, net_log_);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result != OK)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return result;
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!proxy_info_.is_empty());
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_AUTH_REQUIRED;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (proxy_auth_controller_->HaveAuth()) {
95590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::MessageLoop::current()->PostTask(
95690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            FROM_HERE, base::Bind(&SocketStream::DoRestartWithAuth, this));
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERR_IO_PENDING;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (delegate_) {
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Wait until RestartWithAuth or Close is called.
96190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::MessageLoop::current()->PostTask(
96290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            FROM_HERE, base::Bind(&SocketStream::DoAuthRequired, this));
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERR_IO_PENDING;
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_CLOSE;
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_TUNNEL_CONNECTION_FAILED;
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoSOCKSConnect() {
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kSOCKSProxy, proxy_mode_);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostResolver::RequestInfo req_info(HostPortPair::FromURL(url_));
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!proxy_info_.is_empty());
9813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<StreamSocket> s;
9823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5) {
9833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    s.reset(new SOCKS5ClientSocket(connection_.Pass(), req_info));
9843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else {
9853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    s.reset(new SOCKSClientSocket(connection_.Pass(),
9863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  req_info,
9873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  DEFAULT_PRIORITY,
9883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  context_->host_resolver()));
9893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
9903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  connection_.reset(new ClientSocketHandle);
9913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  connection_->SetSocket(s.Pass());
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metrics_->OnCountConnectionType(SocketStreamMetrics::SOCKS_CONNECTION);
9933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return connection_->socket()->Connect(io_callback_);
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoSOCKSConnectComplete(int result) {
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kSOCKSProxy, proxy_mode_);
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_secure())
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_SSL_CONNECT;
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = DidEstablishConnection();
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoSecureProxyConnect() {
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(factory_);
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLClientSocketContext ssl_context;
1013868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ssl_context.cert_verifier = context_->cert_verifier();
10147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ssl_context.transport_security_state = context_->transport_security_state();
10155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ssl_context.channel_id_service = context_->channel_id_service();
10163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<StreamSocket> socket(factory_->CreateSSLClientSocket(
10173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      connection_.Pass(),
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_info_.proxy_server().host_port_pair(),
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_ssl_config_,
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_context));
10213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  connection_.reset(new ClientSocketHandle);
10223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  connection_->SetSocket(socket.Pass());
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_SECURE_PROXY_CONNECT_COMPLETE;
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metrics_->OnCountConnectionType(SocketStreamMetrics::SECURE_PROXY_CONNECTION);
10253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return connection_->socket()->Connect(io_callback_);
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoSecureProxyConnectComplete(int result) {
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reconnect with client authentication.
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HandleCertificateRequest(result, &proxy_ssl_config_);
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsCertificateError(result))
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SECURE_PROXY_HANDLE_CERT_ERROR;
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (result == OK)
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoSecureProxyHandleCertError(int result) {
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsCertificateError(result));
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = HandleCertificateError(result);
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERR_IO_PENDING)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SECURE_PROXY_HANDLE_CERT_ERROR_COMPLETE;
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoSecureProxyHandleCertErrorComplete(int result) {
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
10573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!connection_->socket()->IsConnectedAndIdle())
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AllowCertErrorForReconnection(&proxy_ssl_config_);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN;
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoSSLConnect() {
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(factory_);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLClientSocketContext ssl_context;
1069868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ssl_context.cert_verifier = context_->cert_verifier();
10707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ssl_context.transport_security_state = context_->transport_security_state();
10715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ssl_context.channel_id_service = context_->channel_id_service();
10723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<StreamSocket> socket(
10733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      factory_->CreateSSLClientSocket(connection_.Pass(),
10743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                      HostPortPair::FromURL(url_),
10753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                      server_ssl_config_,
10763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                      ssl_context));
10773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  connection_.reset(new ClientSocketHandle);
10783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  connection_->SetSocket(socket.Pass());
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_SSL_CONNECT_COMPLETE;
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metrics_->OnCountConnectionType(SocketStreamMetrics::SSL_CONNECTION);
10813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return connection_->socket()->Connect(io_callback_);
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoSSLConnectComplete(int result) {
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reconnect with client authentication.
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HandleCertificateRequest(result, &server_ssl_config_);
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsCertificateError(result))
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SSL_HANDLE_CERT_ERROR;
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (result == OK)
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = DidEstablishConnection();
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoSSLHandleCertError(int result) {
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsCertificateError(result));
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = HandleCertificateError(result);
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK || result == ERR_IO_PENDING)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SSL_HANDLE_CERT_ERROR_COMPLETE;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoSSLHandleCertErrorComplete(int result) {
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(toyoshim): Upgrade to SPDY through TLS NPN extension if possible.
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we use HTTPS and this is the first connection to the SPDY server,
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we should take care of TLS NPN extension here.
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
11173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!connection_->socket()->IsConnectedAndIdle())
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AllowCertErrorForReconnection(&server_ssl_config_);
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = DidEstablishConnection();
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::DoReadWrite(int result) {
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < OK) {
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!connection_->socket() || !connection_->socket()->IsConnected()) {
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CONNECTION_CLOSED;
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If client has requested close(), and there's nothing to write, then
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // let's close the socket.
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't care about receiving data after the socket is closed.
1139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (closing_ && !current_write_buf_.get() && pending_write_bufs_.empty()) {
11403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    connection_->socket()->Disconnect();
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_READ_WRITE;
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If server already closed the socket, we don't try to read.
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!server_closed_) {
1149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!read_buf_.get()) {
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // No read pending and server didn't close the socket.
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_buf_ = new IOBuffer(kReadBufferSize);
11523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      result = connection_->socket()->Read(
1153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          read_buf_.get(),
1154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          kReadBufferSize,
1155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          base::Bind(&SocketStream::OnReadCompleted, base::Unretained(this)));
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result > 0) {
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return DidReceiveData(result);
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (result == 0) {
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // 0 indicates end-of-file, so socket was closed.
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_state_ = STATE_CLOSE;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_closed_ = true;
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERR_CONNECTION_CLOSED;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If read is pending, try write as well.
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Otherwise, return the result and do next loop (to close the
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // connection).
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result != ERR_IO_PENDING) {
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_state_ = STATE_CLOSE;
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        server_closed_ = true;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return result;
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read is pending.
1174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(read_buf_.get());
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (waiting_for_write_completion_)
1178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ERR_IO_PENDING;
1179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!current_write_buf_.get()) {
1181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (pending_write_bufs_.empty()) {
1182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Nothing buffered for send.
1183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return ERR_IO_PENDING;
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    current_write_buf_ = new DrainableIOBuffer(
1187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pending_write_bufs_.front().get(), pending_write_bufs_.front()->size());
1188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pending_write_bufs_.pop_front();
1189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  result = connection_->socket()->Write(
1192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      current_write_buf_.get(),
1193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      current_write_buf_->BytesRemaining(),
1194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&SocketStream::OnWriteCompleted, base::Unretained(this)));
1195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (result == ERR_IO_PENDING) {
1197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    waiting_for_write_completion_ = true;
1198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (result < 0) {
1199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Shortcut. Enter STATE_CLOSE now by changing next_state_ here than by
1200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // calling DoReadWrite() again with the error code.
1201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    next_state_ = STATE_CLOSE;
1202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (result > 0) {
1203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Write is not pending. Return OK and do next loop.
1204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DidSendData(result);
1205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    result = OK;
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return result;
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL SocketStream::ProxyAuthOrigin() const {
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!proxy_info_.is_empty());
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GURL("http://" +
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              proxy_info_.proxy_server().host_port_pair().ToString());
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::HandleCertificateRequest(int result, SSLConfig* ssl_config) {
12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ssl_config->send_client_cert) {
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We already have performed SSL client authentication once and failed.
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
12212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(connection_->socket());
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SSLCertRequestInfo> cert_request_info = new SSLCertRequestInfo;
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLClientSocket* ssl_socket =
12263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      static_cast<SSLClientSocket*>(connection_->socket());
1227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ssl_socket->GetSSLCertRequestInfo(cert_request_info.get());
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpTransactionFactory* factory = context_->http_transaction_factory();
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!factory)
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<HttpNetworkSession> session = factory->GetSession();
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!session.get())
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the user selected one of the certificates in client_certs or declined
12372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to provide one for this server before, use the past decision
12382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // automatically.
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<X509Certificate> client_cert;
12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!session->ssl_client_auth_cache()->Lookup(
12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          cert_request_info->host_and_port, &client_cert)) {
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note: |client_cert| may be NULL, indicating that the caller
12462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // wishes to proceed anonymously (eg: continue the handshake
12472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // without sending a client cert)
12482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that the certificate selected is still a certificate the server
12502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // is likely to accept, based on the criteria supplied in the
12512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CertificateRequest message.
12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::vector<std::string>& cert_authorities =
12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cert_request_info->cert_authorities;
1254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (client_cert.get() && !cert_authorities.empty() &&
12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !client_cert->IsIssuedByEncoded(cert_authorities)) {
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
12572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_config->send_client_cert = true;
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_config->client_cert = client_cert;
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_TCP_CONNECT;
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::AllowCertErrorForReconnection(SSLConfig* ssl_config) {
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ssl_config);
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The SSL handshake didn't finish, or the server closed the SSL connection.
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // So, we should restart establishing connection with the certificate in
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // allowed bad certificates in |ssl_config|.
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See also net/http/http_network_transaction.cc HandleCertificateError() and
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RestartIgnoringLastError().
12723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SSLClientSocket* ssl_socket =
12733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      static_cast<SSLClientSocket*>(connection_->socket());
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLInfo ssl_info;
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_socket->GetSSLInfo(&ssl_info);
1276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ssl_info.cert.get() == NULL ||
1277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ssl_config->IsAllowedBadCert(ssl_info.cert.get(), NULL)) {
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we already have the certificate in the set of allowed bad
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // certificates, we did try it and failed again, so we should not
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // retry again: the connection should fail at last.
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add the bad certificate to the set of allowed certificates in the
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSL config object.
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLConfig::CertAndStatus bad_cert;
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!X509Certificate::GetDEREncoded(ssl_info.cert->os_cert_handle(),
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      &bad_cert.der_cert)) {
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_CLOSE;
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bad_cert.cert_status = ssl_info.cert_status;
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_config->allowed_bad_certs.push_back(bad_cert);
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restart connection ignoring the bad certificate.
12953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  connection_->socket()->Disconnect();
12963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  connection_->SetSocket(scoped_ptr<StreamSocket>());
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_TCP_CONNECT;
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::DoAuthRequired() {
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_ && proxy_auth_controller_.get())
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->OnAuthRequired(this, proxy_auth_controller_->auth_info().get());
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoLoop(ERR_UNEXPECTED);
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SocketStream::DoRestartWithAuth() {
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED);
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tunnel_request_headers_ = NULL;
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tunnel_request_headers_bytes_sent_ = 0;
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tunnel_response_headers_ = NULL;
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tunnel_response_headers_capacity_ = 0;
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tunnel_response_headers_len_ = 0;
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_TCP_CONNECT;
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoLoop(OK);
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SocketStream::HandleCertificateError(int result) {
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsCertificateError(result));
13223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SSLClientSocket* ssl_socket =
13233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      static_cast<SSLClientSocket*>(connection_->socket());
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ssl_socket);
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!context_)
1327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return result;
1328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SSLClientSocket::IgnoreCertError(result, LOAD_IGNORE_ALL_CERT_ERRORS)) {
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpNetworkSession::Params* session_params =
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_->GetNetworkSessionParams();
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (session_params && session_params->ignore_certificate_errors)
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return OK;
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!delegate_)
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLInfo ssl_info;
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_socket->GetSSLInfo(&ssl_info);
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1342010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TransportSecurityState* state = context_->transport_security_state();
13431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const bool fatal = state && state->ShouldSSLErrorsBeFatal(url_.host());
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->OnSSLCertificateError(this, ssl_info, fatal);
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_IO_PENDING;
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)CookieStore* SocketStream::cookie_store() const {
13501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return cookie_store_.get();
1351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
1352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1354