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