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)#include "net/http/http_stream_factory_impl.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string> 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_pipelined_connection.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_pipelined_host.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_pipelined_stream.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_server_properties.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_stream_factory_impl_job.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_stream_factory_impl_request.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_http_stream.h" 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const PortAlternateProtocolPair kNoAlternateProtocol = { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, UNINITIALIZED_ALTERNATE_PROTOCOL 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL UpgradeUrlToHttps(const GURL& original_url, int port) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL::Replacements replacements; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new_sheme and new_port need to be in scope here because GURL::Replacements 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // references the memory contained by them directly. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string new_scheme = "https"; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string new_port = base::IntToString(port); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) replacements.SetSchemeStr(new_scheme); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) replacements.SetPortStr(new_port); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_url.ReplaceComponents(replacements); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochHttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session, 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool for_websockets) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : session_(session), 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_pipelined_host_pool_(this, NULL, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_->http_server_properties(), 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_->force_http_pipelining()), 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for_websockets_(for_websockets) {} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpStreamFactoryImpl::~HttpStreamFactoryImpl() { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(request_map_.empty()); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(spdy_session_request_map_.empty()); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(http_pipelining_request_map_.empty()); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<const Job*> tmp_job_set; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp_job_set.swap(orphaned_job_set_); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteContainerPointers(tmp_job_set.begin(), tmp_job_set.end()); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(orphaned_job_set_.empty()); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp_job_set.clear(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp_job_set.swap(preconnect_job_set_); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteContainerPointers(tmp_job_set.begin(), tmp_job_set.end()); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(preconnect_job_set_.empty()); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpStreamRequest* HttpStreamFactoryImpl::RequestStream( 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HttpRequestInfo& request_info, 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestPriority priority, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SSLConfig& server_ssl_config, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SSLConfig& proxy_ssl_config, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpStreamRequest::Delegate* delegate, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BoundNetLog& net_log) { 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!for_websockets_); 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return RequestStreamInternal(request_info, 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch priority, 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch server_ssl_config, 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch proxy_ssl_config, 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate, 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL, 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch net_log); 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochHttpStreamRequest* HttpStreamFactoryImpl::RequestWebSocketStream( 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const HttpRequestInfo& request_info, 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RequestPriority priority, 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const SSLConfig& server_ssl_config, 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const SSLConfig& proxy_ssl_config, 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HttpStreamRequest::Delegate* delegate, 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WebSocketStreamBase::Factory* factory, 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const BoundNetLog& net_log) { 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(for_websockets_); 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(factory); 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return RequestStreamInternal(request_info, 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch priority, 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch server_ssl_config, 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch proxy_ssl_config, 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate, 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch factory, 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch net_log); 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochHttpStreamRequest* HttpStreamFactoryImpl::RequestStreamInternal( 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const HttpRequestInfo& request_info, 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RequestPriority priority, 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const SSLConfig& server_ssl_config, 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const SSLConfig& proxy_ssl_config, 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HttpStreamRequest::Delegate* delegate, 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WebSocketStreamBase::Factory* websocket_stream_factory, 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const BoundNetLog& net_log) { 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Request* request = new Request(request_info.url, 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this, 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate, 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch websocket_stream_factory, 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch net_log); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL alternate_url; 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PortAlternateProtocolPair alternate = 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAlternateProtocolRequestFor(request_info.url, &alternate_url); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job* alternate_job = NULL; 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (alternate.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Never share connection with other jobs for FTP requests. 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!request_info.url.SchemeIs("ftp")); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpRequestInfo alternate_request_info = request_info; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alternate_request_info.url = alternate_url; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alternate_job = 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new Job(this, session_, alternate_request_info, priority, 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) server_ssl_config, proxy_ssl_config, net_log.net_log()); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->AttachJob(alternate_job); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) alternate_job->MarkAsAlternate(request_info.url, alternate); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Job* job = new Job(this, session_, request_info, priority, 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) server_ssl_config, proxy_ssl_config, net_log.net_log()); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->AttachJob(job); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alternate_job) { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Never share connection with other jobs for FTP requests. 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!request_info.url.SchemeIs("ftp")); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job->WaitFor(alternate_job); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure to wait until we call WaitFor(), before starting 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |alternate_job|, otherwise |alternate_job| will not notify |job| 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appropriately. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alternate_job->Start(request); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Even if |alternate_job| has already finished, it won't have notified the 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // request yet, since we defer that to the next iteration of the MessageLoop, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so starting |job| is always safe. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job->Start(request); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return request; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamFactoryImpl::PreconnectStreams( 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_streams, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HttpRequestInfo& request_info, 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestPriority priority, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SSLConfig& server_ssl_config, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SSLConfig& proxy_ssl_config) { 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!for_websockets_); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL alternate_url; 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PortAlternateProtocolPair alternate = 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAlternateProtocolRequestFor(request_info.url, &alternate_url); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job* job = NULL; 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (alternate.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpRequestInfo alternate_request_info = request_info; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alternate_request_info.url = alternate_url; 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) job = new Job(this, session_, alternate_request_info, priority, 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) server_ssl_config, proxy_ssl_config, session_->net_log()); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) job->MarkAsAlternate(request_info.url, alternate); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) job = new Job(this, session_, request_info, priority, 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) server_ssl_config, proxy_ssl_config, session_->net_log()); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preconnect_job_set_.insert(job); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job->Preconnect(num_streams); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Value* HttpStreamFactoryImpl::PipelineInfoToValue() const { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return http_pipelined_host_pool_.PipelineInfoToValue(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return session_->params().host_mapping_rules; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PortAlternateProtocolPair HttpStreamFactoryImpl::GetAlternateProtocolRequestFor( 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& original_url, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL* alternate_url) const { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!use_alternate_protocols()) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kNoAlternateProtocol; 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (original_url.SchemeIs("ftp")) 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kNoAlternateProtocol; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostPortPair origin = HostPortPair(original_url.HostNoBrackets(), 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_url.EffectiveIntPort()); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HttpServerProperties& http_server_properties = 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *session_->http_server_properties(); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!http_server_properties.HasAlternateProtocol(origin)) 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kNoAlternateProtocol; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PortAlternateProtocolPair alternate = 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_server_properties.GetAlternateProtocol(origin); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alternate.protocol == ALTERNATE_PROTOCOL_BROKEN) 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kNoAlternateProtocol; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(NPN_SPDY_1, alternate.protocol); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(NUM_ALTERNATE_PROTOCOLS, alternate.protocol); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alternate.protocol < NPN_SPDY_2) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kNoAlternateProtocol; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some shared unix systems may have user home directories (like 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://foo.com/~mike) which allow users to emit headers. This is a bad 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // idea already, but with Alternate-Protocol, it provides the ability for a 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // single user on a multi-user system to hijack the alternate protocol. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These systems also enforce ports <1024 as restricted ports. So don't 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allow protocol upgrades to user-controllable ports. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kUnrestrictedPort = 1024; 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!session_->params().enable_user_alternate_protocol_ports && 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (alternate.port >= kUnrestrictedPort && 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) origin.port() < kUnrestrictedPort)) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kNoAlternateProtocol; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) origin.set_port(alternate.port); 229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (alternate.protocol >= NPN_SPDY_MINIMUM_VERSION && 230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch alternate.protocol <= NPN_SPDY_MAXIMUM_VERSION) { 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!spdy_enabled()) 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kNoAlternateProtocol; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (HttpStreamFactory::HasSpdyExclusion(origin)) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kNoAlternateProtocol; 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *alternate_url = UpgradeUrlToHttps(original_url, alternate.port); 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(QUIC, alternate.protocol); 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!session_->params().enable_quic || 2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch !(original_url.SchemeIs("http") || 2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch session_->params().enable_quic_https)) { 2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return kNoAlternateProtocol; 2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rch): Figure out how to make QUIC iteract with PAC 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // scripts. By not re-writing the URL, we will query the PAC script 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for the proxy to use to reach the original URL via TCP. But 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the alternate request will be going via UDP to a different port. 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *alternate_url = original_url; 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return alternate; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamFactoryImpl::OrphanJob(Job* job, const Request* request) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsKey(request_map_, job)); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(request_map_[job], request); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!ContainsKey(orphaned_job_set_, job)); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_map_.erase(job); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) orphaned_job_set_.insert(job); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job->Orphan(request); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HttpStreamFactoryImpl::OnNewSpdySessionReady( 266ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const base::WeakPtr<SpdySession>& spdy_session, 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool direct, 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SSLConfig& used_ssl_config, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProxyInfo& used_proxy_info, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_npn_negotiated, 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NextProto protocol_negotiated, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool using_spdy, 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BoundNetLog& net_log) { 274ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch while (true) { 275ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!spdy_session) 276ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 277ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const SpdySessionKey& spdy_session_key = spdy_session->spdy_session_key(); 278ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Each iteration may empty out the RequestSet for |spdy_session_key| in 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |spdy_session_request_map_|. So each time, check for RequestSet and use 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the first one. 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(willchan): If it's important, switch RequestSet out for a FIFO 283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // queue (Order by priority first, then FIFO within same priority). Unclear 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that it matters here. 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ContainsKey(spdy_session_request_map_, spdy_session_key)) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Request* request = *spdy_session_request_map_[spdy_session_key].begin(); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->Complete(was_npn_negotiated, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol_negotiated, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using_spdy, 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log); 292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (for_websockets_) { 293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WebSocketStreamBase::Factory* factory = 294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch request->websocket_stream_factory(); 295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(factory); 296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool use_relative_url = direct || request->url().SchemeIs("wss"); 297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch request->OnWebSocketStreamReady( 298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL, 299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch used_ssl_config, 300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch used_proxy_info, 301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch factory->CreateSpdyStream(spdy_session, use_relative_url)); 302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool use_relative_url = direct || request->url().SchemeIs("https"); 304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch request->OnStreamReady( 305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL, 306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch used_ssl_config, 307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch used_proxy_info, 308ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new SpdyHttpStream(spdy_session, use_relative_url)); 309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mbelshe): Alert other valid requests. 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamFactoryImpl::OnOrphanedJobComplete(const Job* job) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) orphaned_job_set_.erase(job); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete job; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preconnect_job_set_.erase(job); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete job; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnPreconnectsCompleteInternal(); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamFactoryImpl::OnHttpPipelinedHostHasAdditionalCapacity( 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpPipelinedHost* host) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (ContainsKey(http_pipelining_request_map_, host->GetKey())) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpPipelinedStream* stream = 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_pipelined_host_pool_.CreateStreamOnExistingPipeline( 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->GetKey()); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!stream) { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Request* request = *http_pipelining_request_map_[host->GetKey()].begin(); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->Complete(stream->was_npn_negotiated(), 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->protocol_negotiated(), 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, // not using_spdy 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->net_log()); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->OnStreamReady(NULL, 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->used_ssl_config(), 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->used_proxy_info(), 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamFactoryImpl::AbortPipelinedRequestsWithKey( 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Job* job, const HttpPipelinedHost::Key& key, int status, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SSLConfig& used_ssl_config) { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestVector requests_to_fail = http_pipelining_request_map_[key]; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (RequestVector::const_iterator it = requests_to_fail.begin(); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != requests_to_fail.end(); ++it) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Request* request = *it; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request == request_map_[job]) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->OnStreamFailed(NULL, status, used_ssl_config); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 362