socket_stream.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 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 MurdochSocketStream::ResponseHeaders::~ResponseHeaders() { data_ = NULL; } 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::ResponseHeaders::Realloc(size_t new_size) { 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size))); 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSocketStream::SocketStream(const GURL& url, Delegate* delegate) 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : delegate_(delegate), 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_(url), 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott max_pending_send_allowed_(kMaxPendingSendAllowed), 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_(STATE_NONE), 5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen host_resolver_(NULL), 5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_verifier_(NULL), 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch http_auth_handler_factory_(NULL), 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott factory_(ClientSocketFactory::GetDefaultFactory()), 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott proxy_mode_(kDirectConnection), 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott proxy_url_(url), 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pac_request_(NULL), 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ALLOW_THIS_IN_INITIALIZER_LIST( 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_callback_(this, &SocketStream::OnIOCompleted)), 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ALLOW_THIS_IN_INITIALIZER_LIST( 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_callback_(this, &SocketStream::OnReadCompleted)), 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ALLOW_THIS_IN_INITIALIZER_LIST( 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_callback_(this, &SocketStream::OnWriteCompleted)), 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_(NULL), 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_(NULL), 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_write_buf_(NULL), 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_offset_(0), 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_size_(0), 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch closing_(false), 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick server_closed_(false), 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metrics_(new SocketStreamMetrics(url)) { 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(MessageLoop::current()) << 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must exist"; 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must be TYPE_IO"; 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(delegate_); 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSocketStream::~SocketStream() { 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott set_context(NULL); 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!delegate_); 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!pac_request_); 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSocketStream::UserData* SocketStream::GetUserData( 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const void* key) const { 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UserDataMap::const_iterator found = user_data_.find(key); 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (found != user_data_.end()) 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return found->second.get(); 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::SetUserData(const void* key, UserData* data) { 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_data_[key] = linked_ptr<UserData>(data); 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::set_context(URLRequestContext* context) { 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<URLRequestContext> prev_context = context_; 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott context_ = context; 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (prev_context != context) { 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (prev_context && pac_request_) { 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prev_context->proxy_service()->CancelPacRequest(pac_request_); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pac_request_ = NULL; 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.EndEvent(NetLog::TYPE_REQUEST_ALIVE, NULL); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_ = BoundNetLog(); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (context) { 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_ = BoundNetLog::Make( 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context->net_log(), 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NetLog::SOURCE_SOCKET_STREAM); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE, NULL); 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (context_) { 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott host_resolver_ = context_->host_resolver(); 12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_verifier_ = context_->cert_verifier(); 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch http_auth_handler_factory_ = context_->http_auth_handler_factory(); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::Connect() { 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(MessageLoop::current()) << 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must exist"; 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must be TYPE_IO"; 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (context_) 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_config_service()->GetSSLConfig(&ssl_config_); 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(next_state_, STATE_NONE); 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddRef(); // Released in Finish() 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Open a connection asynchronously, so that delegate won't be called 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // back before returning Connect(). 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_RESOLVE_PROXY; 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.BeginEvent( 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NetLog::TYPE_SOCKET_STREAM_CONNECT, 144513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch make_scoped_refptr( 145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new NetLogStringParameter("url", url_.possibly_invalid_spec()))); 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop::current()->PostTask( 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FROM_HERE, 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NewRunnableMethod(this, &SocketStream::DoLoop, OK)); 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SocketStream::SendData(const char* data, int len) { 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(MessageLoop::current()) << 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must exist"; 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must be TYPE_IO"; 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!socket_.get() || !socket_->IsConnected() || next_state_ == STATE_NONE) 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (write_buf_) { 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int current_amount_send = write_buf_size_ - write_buf_offset_; 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (PendingDataQueue::const_iterator iter = pending_write_bufs_.begin(); 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott iter != pending_write_bufs_.end(); 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++iter) 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_amount_send += (*iter)->size(); 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_amount_send += len; 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (current_amount_send > max_pending_send_allowed_) 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch pending_write_bufs_.push_back(make_scoped_refptr( 170513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new IOBufferWithSize(len))); 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(pending_write_bufs_.back()->data(), data, len); 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!current_write_buf_); 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_ = new IOBuffer(len); 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(write_buf_->data(), data, len); 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_size_ = len; 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_offset_ = 0; 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Send pending data asynchronously, so that delegate won't be called 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // back before returning SendData(). 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop::current()->PostTask( 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FROM_HERE, 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NewRunnableMethod(this, &SocketStream::DoLoop, OK)); 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::Close() { 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(MessageLoop::current()) << 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must exist"; 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must be TYPE_IO"; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If next_state_ is STATE_NONE, the socket was not opened, or already 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // closed. So, return immediately. 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Otherwise, it might call Finish() more than once, so breaks balance 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of AddRef() and Release() in Connect() and Finish(), respectively. 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (next_state_ == STATE_NONE) 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop::current()->PostTask( 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FROM_HERE, 2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NewRunnableMethod(this, &SocketStream::DoClose)); 2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SocketStream::DoClose() { 2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick closing_ = true; 2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If next_state_ is STATE_TCP_CONNECT, it's waiting other socket establishing 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // connection. If next_state_ is STATE_AUTH_REQUIRED, it's waiting for 2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // restarting. In these states, we'll close the SocketStream now. 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (next_state_ == STATE_TCP_CONNECT || next_state_ == STATE_AUTH_REQUIRED) { 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DoLoop(ERR_ABORTED); 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If next_state_ is STATE_READ_WRITE, we'll run DoLoop and close 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // the SocketStream. 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If it's writing now, we should defer the closing after the current 2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // writing is completed. 2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (next_state_ == STATE_READ_WRITE && !current_write_buf_) 2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DoLoop(ERR_ABORTED); 2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // In other next_state_, we'll wait for callback of other APIs, such as 2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // ResolveProxy(). 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::RestartWithAuth( 2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16& username, const string16& password) { 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(MessageLoop::current()) << 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must exist"; 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must be TYPE_IO"; 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(auth_handler_.get()); 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!socket_.get()) { 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Socket is closed before restarting with auth."; 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (auth_identity_.invalid) { 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Update the username/password. 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.source = HttpAuth::IDENT_SRC_EXTERNAL; 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.invalid = false; 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.username = username; 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.password = password; 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop::current()->PostTask( 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FROM_HERE, 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NewRunnableMethod(this, &SocketStream::DoRestartWithAuth)); 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DetachDelegate() { 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!delegate_) 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_ = NULL; 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't need to send pending data when client detach the delegate. 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_write_bufs_.clear(); 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Close(); 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::Finish(int result) { 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(MessageLoop::current()) << 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must exist"; 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "The current MessageLoop must be TYPE_IO"; 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_LE(result, OK); 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == OK) 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = ERR_CONNECTION_CLOSED; 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(next_state_, STATE_NONE); 267731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "Finish result=" << net::ErrorToString(result); 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delegate_) 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_->OnError(this, result); 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott metrics_->OnClose(); 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Delegate* delegate = delegate_; 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_ = NULL; 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delegate) { 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate->OnClose(this); 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Release(); 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::SetHostResolver(HostResolver* host_resolver) { 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(host_resolver); 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott host_resolver_ = host_resolver; 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::SetClientSocketFactory( 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ClientSocketFactory* factory) { 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(factory); 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott factory_ = factory; 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::CopyAddrInfo(struct addrinfo* head) { 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch addresses_.Copy(head, true); 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DidEstablishConnection() { 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!socket_.get() || !socket_->IsConnected()) { 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CONNECTION_FAILED; 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_READ_WRITE; 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott metrics_->OnConnected(); 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.EndEvent(NetLog::TYPE_SOCKET_STREAM_CONNECT, NULL); 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delegate_) 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_->OnConnected(this, max_pending_send_allowed_); 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DidReceiveData(int result) { 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(read_buf_); 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GT(result, 0); 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_RECEIVED, NULL); 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int len = result; 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott metrics_->OnRead(len); 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delegate_) { 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Notify recevied data to delegate. 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_->OnReceivedData(this, read_buf_->data(), len); 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buf_ = NULL; 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DidSendData(int result) { 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GT(result, 0); 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_SENT, NULL); 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int len = result; 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott metrics_->OnWrite(len); 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_write_buf_ = NULL; 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delegate_) 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_->OnSentData(this, len); 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int remaining_size = write_buf_size_ - write_buf_offset_ - len; 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (remaining_size == 0) { 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!pending_write_bufs_.empty()) { 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_size_ = pending_write_bufs_.front()->size(); 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_ = pending_write_bufs_.front(); 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pending_write_bufs_.pop_front(); 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_size_ = 0; 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_ = NULL; 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_offset_ = 0; 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_offset_ += len; 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::OnIOCompleted(int result) { 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoLoop(result); 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::OnReadCompleted(int result) { 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == 0) { 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 0 indicates end-of-file, so socket was closed. 3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Don't close the socket if it's still writing. 3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick server_closed_ = true; 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (result > 0 && read_buf_) { 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DidReceiveData(result); 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoLoop(result); 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::OnWriteCompleted(int result) { 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result >= 0 && write_buf_) { 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DidSendData(result); 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoLoop(result); 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DoLoop(int result) { 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If context was not set, close immediately. 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!context_) 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (next_state_ == STATE_NONE) 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott State state = next_state_; 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_NONE; 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (state) { 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_RESOLVE_PROXY: 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, result); 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoResolveProxy(); 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_RESOLVE_PROXY_COMPLETE: 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoResolveProxyComplete(result); 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_RESOLVE_HOST: 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, result); 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoResolveHost(); 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_RESOLVE_HOST_COMPLETE: 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoResolveHostComplete(result); 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_TCP_CONNECT: 3993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick result = DoTcpConnect(result); 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_TCP_CONNECT_COMPLETE: 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoTcpConnectComplete(result); 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_WRITE_TUNNEL_HEADERS: 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, result); 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoWriteTunnelHeaders(); 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_WRITE_TUNNEL_HEADERS_COMPLETE: 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoWriteTunnelHeadersComplete(result); 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_READ_TUNNEL_HEADERS: 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, result); 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoReadTunnelHeaders(); 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_READ_TUNNEL_HEADERS_COMPLETE: 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoReadTunnelHeadersComplete(result); 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_SOCKS_CONNECT: 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, result); 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoSOCKSConnect(); 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_SOCKS_CONNECT_COMPLETE: 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoSOCKSConnectComplete(result); 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_SSL_CONNECT: 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, result); 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoSSLConnect(); 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_SSL_CONNECT_COMPLETE: 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoSSLConnectComplete(result); 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_READ_WRITE: 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DoReadWrite(result); 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 4353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case STATE_AUTH_REQUIRED: 4363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // It might be called when DoClose is called while waiting in 4373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // STATE_AUTH_REQUIRED. 4383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Finish(result); 4393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_CLOSE: 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_LE(result, OK); 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Finish(result); 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 4453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED() << "bad state " << state; 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Finish(result); 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the connection is not established yet and had actual errors, 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // close the connection. 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) { 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(next_state_, STATE_CLOSE); 453513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch net_log_.EndEvent( 454513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NetLog::TYPE_SOCKET_STREAM_CONNECT, 455513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch make_scoped_refptr(new NetLogIntegerParameter("net_error", result))); 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (result != ERR_IO_PENDING); 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveProxy() { 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!pac_request_); 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_RESOLVE_PROXY_COMPLETE; 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!proxy_url_.is_valid()) { 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_INVALID_ARGUMENT; 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return proxy_service()->ResolveProxy( 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proxy_url_, &proxy_info_, &io_callback_, &pac_request_, net_log_); 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveProxyComplete(int result) { 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pac_request_ = NULL; 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result != OK) { 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Failed to resolve proxy: " << result; 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delegate_) 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_->OnError(this, result); 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott proxy_info_.UseDirect(); 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (proxy_info_.is_direct()) { 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If proxy was not found for original URL (i.e. websocket URL), 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // try again with https URL, like Safari implementation. 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note that we don't want to use http proxy, because we'll use tunnel 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // proxy using CONNECT method, which is used by https proxy. 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!proxy_url_.SchemeIs("https")) { 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string scheme = "https"; 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GURL::Replacements repl; 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott repl.SetSchemeStr(scheme); 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott proxy_url_ = url_.ReplaceComponents(repl); 491731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "Try https proxy: " << proxy_url_; 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_RESOLVE_PROXY; 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (proxy_info_.is_empty()) { 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No proxies/direct to choose from. This happens when we don't support any 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of the proxies in the returned list. 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_NO_SUPPORTED_PROXIES; 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_RESOLVE_HOST; 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveHost() { 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_RESOLVE_HOST_COMPLETE; 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!proxy_info_.is_empty()); 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (proxy_info_.is_direct()) 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott proxy_mode_ = kDirectConnection; 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (proxy_info_.proxy_server().is_socks()) 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott proxy_mode_ = kSOCKSProxy; 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott proxy_mode_ = kTunnelProxy; 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Determine the host and port to connect to. 5193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HostPortPair host_port_pair; 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (proxy_mode_ != kDirectConnection) { 5213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick host_port_pair = proxy_info_.proxy_server().host_port_pair(); 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick host_port_pair = HostPortPair::FromURL(url_); 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HostResolver::RequestInfo resolve_info(host_port_pair); 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 528731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(host_resolver_); 529731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick resolver_.reset(new SingleRequestHostResolver(host_resolver_)); 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return resolver_->Resolve(resolve_info, &addresses_, &io_callback_, 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_); 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoResolveHostComplete(int result) { 5353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (result == OK && delegate_) { 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_TCP_CONNECT; 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result = delegate_->OnStartOpenConnection(this, &io_callback_); 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == net::ERR_IO_PENDING) 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott metrics_->OnWaitConnection(); 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(ukai): if error occured, reconsider proxy after error. 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint SocketStream::DoTcpConnect(int result) { 5483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (result != OK) { 5493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_state_ = STATE_CLOSE; 5503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return result; 5513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_TCP_CONNECT_COMPLETE; 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(factory_); 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_.reset(factory_->CreateTCPClientSocket(addresses_, 5553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net_log_.net_log(), 5563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net_log_.source())); 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott metrics_->OnStartConnection(); 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return socket_->Connect(&io_callback_); 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoTcpConnectComplete(int result) { 562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(ukai): if error occured, reconsider proxy after error. 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result != OK) { 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (proxy_mode_ == kTunnelProxy) 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_WRITE_TUNNEL_HEADERS; 570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (proxy_mode_ == kSOCKSProxy) 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_SOCKS_CONNECT; 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (is_secure()) { 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_SSL_CONNECT; 574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DidEstablishConnection(); 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoWriteTunnelHeaders() { 581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(kTunnelProxy, proxy_mode_); 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_WRITE_TUNNEL_HEADERS_COMPLETE; 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!tunnel_request_headers_.get()) { 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott metrics_->OnTunnelProxy(); 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_request_headers_ = new RequestHeaders(); 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_request_headers_bytes_sent_ = 0; 589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (tunnel_request_headers_->headers_.empty()) { 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string authorization_headers; 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!auth_handler_.get()) { 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Do preemptive authentication. 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpAuthCache::Entry* entry = auth_cache_.LookupByPath( 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ProxyAuthOrigin(), std::string()); 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry) { 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<HttpAuthHandler> handler_preemptive; 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv_create = http_auth_handler_factory_-> 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreatePreemptiveAuthHandlerFromString( 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry->auth_challenge(), HttpAuth::AUTH_PROXY, 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProxyAuthOrigin(), entry->IncrementNonceCount(), 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_, &handler_preemptive); 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv_create == OK) { 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_identity_.source = HttpAuth::IDENT_SRC_PATH_LOOKUP; 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_identity_.invalid = false; 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_identity_.username = entry->username(); 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_identity_.password = entry->password(); 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_handler_.swap(handler_preemptive); 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Support basic authentication scheme only, because we don't have 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // HttpRequestInfo. 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(ukai): Add support other authentication scheme. 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (auth_handler_.get() && auth_handler_->scheme() == "basic") { 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HttpRequestInfo request_info; 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string auth_token; 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = auth_handler_->GenerateAuthToken( 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &auth_identity_.username, 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &auth_identity_.password, 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &request_info, 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &auth_token); 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(cbentzel): Support async auth handlers. 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(ERR_IO_PENDING, rv); 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != OK) 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott authorization_headers.append( 631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY) + 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ": " + auth_token + "\r\n"); 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick tunnel_request_headers_->headers_ = base::StringPrintf( 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "CONNECT %s HTTP/1.1\r\n" 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "Host: %s\r\n" 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "Proxy-Connection: keep-alive\r\n", 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetHostAndPort(url_).c_str(), 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetHostAndOptionalPort(url_).c_str()); 641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!authorization_headers.empty()) 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_request_headers_->headers_ += authorization_headers; 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_request_headers_->headers_ += "\r\n"; 644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_request_headers_->SetDataOffset(tunnel_request_headers_bytes_sent_); 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int buf_len = static_cast<int>(tunnel_request_headers_->headers_.size() - 647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_request_headers_bytes_sent_); 648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GT(buf_len, 0); 649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return socket_->Write(tunnel_request_headers_, buf_len, &io_callback_); 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoWriteTunnelHeadersComplete(int result) { 653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(kTunnelProxy, proxy_mode_); 654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) { 656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_request_headers_bytes_sent_ += result; 661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (tunnel_request_headers_bytes_sent_ < 662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_request_headers_->headers_.size()) 663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_WRITE_TUNNEL_HEADERS; 664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_READ_TUNNEL_HEADERS; 666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoReadTunnelHeaders() { 670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(kTunnelProxy, proxy_mode_); 671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_READ_TUNNEL_HEADERS_COMPLETE; 673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!tunnel_response_headers_.get()) { 675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_ = new ResponseHeaders(); 676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_capacity_ = kMaxTunnelResponseHeadersSize; 677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_->Realloc(tunnel_response_headers_capacity_); 678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_len_ = 0; 679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int buf_len = tunnel_response_headers_capacity_ - 682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_len_; 683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_->SetDataOffset(tunnel_response_headers_len_); 684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK(tunnel_response_headers_->data()); 685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return socket_->Read(tunnel_response_headers_, buf_len, &io_callback_); 687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoReadTunnelHeadersComplete(int result) { 690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(kTunnelProxy, proxy_mode_); 691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) { 693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == 0) { 698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 0 indicates end-of-file, so socket was closed. 699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CONNECTION_CLOSED; 701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_len_ += result; 704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(tunnel_response_headers_len_ <= tunnel_response_headers_capacity_); 705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int eoh = HttpUtil::LocateEndOfHeaders( 707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_->headers(), tunnel_response_headers_len_, 0); 708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (eoh == -1) { 709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (tunnel_response_headers_len_ >= kMaxTunnelResponseHeadersSize) { 710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_RESPONSE_HEADERS_TOO_BIG; 712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_READ_TUNNEL_HEADERS; 715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // DidReadResponseHeaders 718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<HttpResponseHeaders> headers; 719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers = new HttpResponseHeaders( 720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpUtil::AssembleRawHeaders(tunnel_response_headers_->headers(), eoh)); 721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (headers->GetParsedHttpVersion() < HttpVersion(1, 0)) { 722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Require the "HTTP/1.x" status line. 723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_TUNNEL_CONNECTION_FAILED; 725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (headers->response_code()) { 727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 200: // OK 728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (is_secure()) { 729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(eoh, tunnel_response_headers_len_); 730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_SSL_CONNECT; 731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DidEstablishConnection(); 733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) { 734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((eoh < tunnel_response_headers_len_) && delegate_) 738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_->OnReceivedData( 739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott this, tunnel_response_headers_->headers() + eoh, 740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_len_ - eoh); 741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case 407: // Proxy Authentication Required. 744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = HandleAuthChallenge(headers.get()); 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result == ERR_PROXY_AUTH_UNSUPPORTED && 746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_handler_.get() && delegate_) { 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!proxy_info_.is_empty()); 748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_info_ = new AuthChallengeInfo; 749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_info_->is_proxy = true; 750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_info_->host_and_port = 7513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASCIIToWide(proxy_info_.proxy_server().host_port_pair().ToString()); 752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_info_->scheme = ASCIIToWide(auth_handler_->scheme()); 753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_info_->realm = ASCIIToWide(auth_handler_->realm()); 754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Wait until RestartWithAuth or Close is called. 755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop::current()->PostTask( 756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FROM_HERE, 757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NewRunnableMethod(this, &SocketStream::DoAuthRequired)); 758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_AUTH_REQUIRED; 759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_IO_PENDING; 760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_TUNNEL_CONNECTION_FAILED; 766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSOCKSConnect() { 769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(kSOCKSProxy, proxy_mode_); 770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_SOCKS_CONNECT_COMPLETE; 772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ClientSocket* s = socket_.release(); 7743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HostResolver::RequestInfo req_info(HostPortPair::FromURL(url_)); 775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!proxy_info_.is_empty()); 777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5) 778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott s = new SOCKS5ClientSocket(s, req_info); 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 780731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick s = new SOCKSClientSocket(s, req_info, host_resolver_); 781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socket_.reset(s); 782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott metrics_->OnSOCKSProxy(); 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return socket_->Connect(&io_callback_); 784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSOCKSConnectComplete(int result) { 787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(kSOCKSProxy, proxy_mode_); 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == OK) { 790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (is_secure()) 791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_SSL_CONNECT; 792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DidEstablishConnection(); 794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSSLConnect() { 801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(factory_); 802731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO(agl): look into plumbing SSLHostInfo here. 8034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch socket_.reset(factory_->CreateSSLClientSocket(socket_.release(), 8044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch HostPortPair::FromURL(url_), 8054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ssl_config_, 80621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen NULL /* ssl_host_info */, 80721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_verifier_)); 808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_SSL_CONNECT_COMPLETE; 809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott metrics_->OnSSLConnection(); 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return socket_->Connect(&io_callback_); 811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoSSLConnectComplete(int result) { 814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (IsCertificateError(result)) { 815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (socket_->IsConnectedAndIdle()) { 816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = HandleCertificateError(result); 817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SSLClientSocket for Mac will report socket is not connected, 819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // if it returns cert verification error. It didn't perform 820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SSLHandshake yet. 821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // So, we should restart establishing connection with the 822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // certificate in allowed bad certificates in |ssl_config_|. 823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // See also net/http/http_network_transaction.cc 824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // HandleCertificateError() and RestartIgnoringLastError(). 825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLClientSocket* ssl_socket = 826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<SSLClientSocket*>(socket_.get()); 827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLInfo ssl_info; 828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_socket->GetSSLInfo(&ssl_info); 829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLConfig::CertAndStatus bad_cert; 830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bad_cert.cert = ssl_info.cert; 831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bad_cert.cert_status = ssl_info.cert_status; 832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ssl_config_.IsAllowedBadCert(ssl_info.cert)) { 833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If we already have the certificate in the set of allowed bad 834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // certificates, we did try it and failed again, so we should not 835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // retry again: the connection should fail at last. 836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Add the bad certificate to the set of allowed certificates in the 840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SSL info object. 841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_config_.allowed_bad_certs.push_back(bad_cert); 842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Restart connection ignoring the bad certificate. 843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socket_->Disconnect(); 844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socket_.reset(); 845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_TCP_CONNECT; 846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == OK) 851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = DidEstablishConnection(); 852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::DoReadWrite(int result) { 858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < OK) { 859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!socket_.get() || !socket_->IsConnected()) { 863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CONNECTION_CLOSED; 865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If client has requested close(), and there's nothing to write, then 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // let's close the socket. 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't care about receiving data after the socket is closed. 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (closing_ && !write_buf_ && pending_write_bufs_.empty()) { 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch socket_->Disconnect(); 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_ = STATE_CLOSE; 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_READ_WRITE; 877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If server already closed the socket, we don't try to read. 8793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!server_closed_) { 8803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!read_buf_) { 8813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // No read pending and server didn't close the socket. 8823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick read_buf_ = new IOBuffer(kReadBufferSize); 8833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick result = socket_->Read(read_buf_, kReadBufferSize, &read_callback_); 8843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (result > 0) { 8853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return DidReceiveData(result); 8863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else if (result == 0) { 8873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // 0 indicates end-of-file, so socket was closed. 8883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_state_ = STATE_CLOSE; 8893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick server_closed_ = true; 8903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return ERR_CONNECTION_CLOSED; 8913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 8923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If read is pending, try write as well. 8933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Otherwise, return the result and do next loop (to close the 8943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // connection). 8953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (result != ERR_IO_PENDING) { 8963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next_state_ = STATE_CLOSE; 8973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick server_closed_ = true; 8983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return result; 8993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 9013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Read is pending. 9023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(read_buf_); 903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (write_buf_ && !current_write_buf_) { 906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // No write pending. 907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_write_buf_ = new DrainableIOBuffer(write_buf_, write_buf_size_); 908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_write_buf_->SetOffset(write_buf_offset_); 909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = socket_->Write(current_write_buf_, 910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_write_buf_->BytesRemaining(), 911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &write_callback_); 912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result > 0) { 913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DidSendData(result); 914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If write is not pending, return the result and do next loop (to close 916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the connection). 917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result != 0 && result != ERR_IO_PENDING) { 918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_CLOSE; 919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We arrived here when both operation is pending. 925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_IO_PENDING; 926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGURL SocketStream::ProxyAuthOrigin() const { 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!proxy_info_.is_empty()); 9303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return GURL("http://" + 9313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick proxy_info_.proxy_server().host_port_pair().ToString()); 932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::HandleAuthChallenge(const HttpResponseHeaders* headers) { 935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GURL auth_origin(ProxyAuthOrigin()); 936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 937731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "The proxy " << auth_origin << " requested auth"; 938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(cbentzel): Since SocketStream only suppports basic authentication 9403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // right now, another challenge is always treated as a rejection. 9413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Ultimately this should be converted to use HttpAuthController like the 9423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // HttpNetworkTransaction has. 9433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (auth_handler_.get() && !auth_identity_.invalid) { 944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (auth_identity_.source != HttpAuth::IDENT_SRC_PATH_LOOKUP) 945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_cache_.Remove(auth_origin, 946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_handler_->realm(), 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_handler_->scheme(), 948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.username, 949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.password); 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_handler_.reset(); 951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_ = HttpAuth::Identity(); 952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.invalid = true; 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<std::string> disabled_schemes; 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, headers, 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HttpAuth::AUTH_PROXY, 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_origin, disabled_schemes, 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_, &auth_handler_); 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!auth_handler_.get()) { 961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Can't perform auth to the proxy " << auth_origin; 962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_TUNNEL_CONNECTION_FAILED; 963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (auth_handler_->NeedsIdentity()) { 965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We only support basic authentication scheme now. 966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(ukai): Support other authentication scheme. 967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HttpAuthCache::Entry* entry = 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_cache_.Lookup(auth_origin, auth_handler_->realm(), "basic"); 969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (entry) { 970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP; 971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.invalid = false; 972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.username = entry->username(); 973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.password = entry->password(); 974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Restart with auth info. 975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_PROXY_AUTH_UNSUPPORTED; 977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott auth_identity_.invalid = false; 979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_TUNNEL_CONNECTION_FAILED; 981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DoAuthRequired() { 984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delegate_ && auth_info_.get()) 985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_->OnAuthRequired(this, auth_info_.get()); 986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoLoop(net::ERR_UNEXPECTED); 988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SocketStream::DoRestartWithAuth() { 991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED); 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_cache_.Add(ProxyAuthOrigin(), 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_handler_->realm(), 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_handler_->scheme(), 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_handler_->challenge(), 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_identity_.username, 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auth_identity_.password, 998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string()); 999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_request_headers_ = NULL; 1001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_request_headers_bytes_sent_ = 0; 1002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_ = NULL; 1003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_capacity_ = 0; 1004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tunnel_response_headers_len_ = 0; 1005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_TCP_CONNECT; 1007c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoLoop(OK); 1008c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SocketStream::HandleCertificateError(int result) { 1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(ukai): handle cert error properly. 1012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (result) { 1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_CERT_COMMON_NAME_INVALID: 1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_CERT_DATE_INVALID: 1015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_CERT_AUTHORITY_INVALID: 1016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = OK; 1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SocketStream::is_secure() const { 1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return url_.SchemeIs("wss"); 1026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSSLConfigService* SocketStream::ssl_config_service() const { 1029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return context_->ssl_config_service(); 1030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottProxyService* SocketStream::proxy_service() const { 1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return context_->proxy_service(); 1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 1037