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