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