http_stream_factory_job.cc 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/http/http_stream_factory_job.h"
  5. #include <algorithm>
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include "base/bind.h"
  10. #include "base/callback.h"
  11. #include "base/callback_helpers.h"
  12. #include "base/check_op.h"
  13. #include "base/containers/contains.h"
  14. #include "base/feature_list.h"
  15. #include "base/location.h"
  16. #include "base/metrics/histogram_macros.h"
  17. #include "base/metrics/sparse_histogram.h"
  18. #include "base/notreached.h"
  19. #include "base/strings/string_number_conversions.h"
  20. #include "base/strings/string_util.h"
  21. #include "base/task/single_thread_task_runner.h"
  22. #include "base/threading/thread_task_runner_handle.h"
  23. #include "base/trace_event/trace_event.h"
  24. #include "base/values.h"
  25. #include "build/build_config.h"
  26. #include "net/base/host_port_pair.h"
  27. #include "net/base/port_util.h"
  28. #include "net/base/proxy_delegate.h"
  29. #include "net/base/trace_constants.h"
  30. #include "net/cert/cert_verifier.h"
  31. #include "net/dns/public/secure_dns_policy.h"
  32. #include "net/http/bidirectional_stream_impl.h"
  33. #include "net/http/http_basic_stream.h"
  34. #include "net/http/http_network_session.h"
  35. #include "net/http/http_request_info.h"
  36. #include "net/http/http_server_properties.h"
  37. #include "net/http/http_stream_factory.h"
  38. #include "net/http/proxy_fallback.h"
  39. #include "net/log/net_log.h"
  40. #include "net/log/net_log_capture_mode.h"
  41. #include "net/log/net_log_event_type.h"
  42. #include "net/log/net_log_source.h"
  43. #include "net/log/net_log_source_type.h"
  44. #include "net/quic/bidirectional_stream_quic_impl.h"
  45. #include "net/quic/quic_http_stream.h"
  46. #include "net/socket/client_socket_handle.h"
  47. #include "net/socket/client_socket_pool_manager.h"
  48. #include "net/socket/connect_job.h"
  49. #include "net/socket/ssl_client_socket.h"
  50. #include "net/socket/stream_socket.h"
  51. #include "net/spdy/bidirectional_stream_spdy_impl.h"
  52. #include "net/spdy/http2_push_promise_index.h"
  53. #include "net/spdy/spdy_http_stream.h"
  54. #include "net/spdy/spdy_session.h"
  55. #include "net/ssl/ssl_cert_request_info.h"
  56. #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
  57. #include "url/scheme_host_port.h"
  58. #include "url/url_constants.h"
  59. namespace net {
  60. namespace {
  61. // Experiment to preconnect only one connection if HttpServerProperties is
  62. // not supported or initialized.
  63. const base::Feature kLimitEarlyPreconnectsExperiment{
  64. "LimitEarlyPreconnects", base::FEATURE_ENABLED_BY_DEFAULT};
  65. } // namespace
  66. const char* NetLogHttpStreamJobType(HttpStreamFactory::JobType job_type) {
  67. switch (job_type) {
  68. case HttpStreamFactory::MAIN:
  69. return "main";
  70. case HttpStreamFactory::ALTERNATIVE:
  71. return "alternative";
  72. case HttpStreamFactory::DNS_ALPN_H3:
  73. return "dns_alpn_h3";
  74. case HttpStreamFactory::PRECONNECT:
  75. return "preconnect";
  76. case HttpStreamFactory::PRECONNECT_DNS_ALPN_H3:
  77. return "preconnect_dns_alpn_h3";
  78. }
  79. return "";
  80. }
  81. // Returns parameters associated with the start of a HTTP stream job.
  82. base::Value NetLogHttpStreamJobParams(const NetLogSource& source,
  83. const GURL& original_url,
  84. const GURL& url,
  85. bool expect_spdy,
  86. bool using_quic,
  87. HttpStreamFactory::JobType job_type,
  88. RequestPriority priority) {
  89. base::Value::Dict dict;
  90. if (source.IsValid())
  91. source.AddToEventParameters(dict);
  92. dict.Set("original_url", original_url.DeprecatedGetOriginAsURL().spec());
  93. dict.Set("url", url.DeprecatedGetOriginAsURL().spec());
  94. dict.Set("expect_spdy", expect_spdy);
  95. dict.Set("using_quic", using_quic);
  96. dict.Set("priority", RequestPriorityToString(priority));
  97. dict.Set("type", NetLogHttpStreamJobType(job_type));
  98. return base::Value(std::move(dict));
  99. }
  100. // Returns parameters associated with the ALPN protocol of a HTTP stream.
  101. base::Value NetLogHttpStreamProtoParams(NextProto negotiated_protocol) {
  102. base::Value::Dict dict;
  103. dict.Set("proto", NextProtoToString(negotiated_protocol));
  104. return base::Value(std::move(dict));
  105. }
  106. HttpStreamFactory::Job::Job(Delegate* delegate,
  107. JobType job_type,
  108. HttpNetworkSession* session,
  109. const HttpRequestInfo& request_info,
  110. RequestPriority priority,
  111. const ProxyInfo& proxy_info,
  112. const SSLConfig& server_ssl_config,
  113. const SSLConfig& proxy_ssl_config,
  114. url::SchemeHostPort destination,
  115. GURL origin_url,
  116. NextProto alternative_protocol,
  117. quic::ParsedQuicVersion quic_version,
  118. bool is_websocket,
  119. bool enable_ip_based_pooling,
  120. NetLog* net_log)
  121. : request_info_(request_info),
  122. priority_(priority),
  123. proxy_info_(proxy_info),
  124. server_ssl_config_(server_ssl_config),
  125. proxy_ssl_config_(proxy_ssl_config),
  126. net_log_(
  127. NetLogWithSource::Make(net_log, NetLogSourceType::HTTP_STREAM_JOB)),
  128. io_callback_(
  129. base::BindRepeating(&Job::OnIOComplete, base::Unretained(this))),
  130. connection_(std::make_unique<ClientSocketHandle>()),
  131. session_(session),
  132. destination_(std::move(destination)),
  133. origin_url_(origin_url),
  134. is_websocket_(is_websocket),
  135. try_websocket_over_http2_(
  136. is_websocket_ && origin_url_.SchemeIs(url::kWssScheme) &&
  137. // TODO(https://crbug.com/1277306): Remove the proxy check.
  138. proxy_info_.is_direct()),
  139. // Don't use IP connection pooling for HTTP over HTTPS proxies. It doesn't
  140. // get us much, and testing it is more effort than its worth.
  141. enable_ip_based_pooling_(
  142. enable_ip_based_pooling &&
  143. !(proxy_info_.proxy_server().is_secure_http_like() &&
  144. origin_url_.SchemeIs(url::kHttpScheme))),
  145. delegate_(delegate),
  146. job_type_(job_type),
  147. using_ssl_(origin_url_.SchemeIs(url::kHttpsScheme) ||
  148. origin_url_.SchemeIs(url::kWssScheme)),
  149. using_quic_(
  150. alternative_protocol == kProtoQUIC ||
  151. (ShouldForceQuic(session, destination_, proxy_info, using_ssl_)) ||
  152. job_type == DNS_ALPN_H3 || job_type == PRECONNECT_DNS_ALPN_H3),
  153. quic_version_(quic_version),
  154. expect_spdy_(alternative_protocol == kProtoHTTP2 && !using_quic_),
  155. quic_request_(session_->quic_stream_factory()),
  156. pushed_stream_id_(kNoPushedStreamFound),
  157. spdy_session_key_(
  158. using_quic_ ? SpdySessionKey()
  159. : GetSpdySessionKey(proxy_info_.proxy_server(),
  160. origin_url_,
  161. request_info_.privacy_mode,
  162. request_info_.socket_tag,
  163. request_info_.network_isolation_key,
  164. request_info_.secure_dns_policy)) {
  165. // Websocket `destination` schemes should be converted to HTTP(S).
  166. DCHECK(base::EqualsCaseInsensitiveASCII(destination_.scheme(),
  167. url::kHttpScheme) ||
  168. base::EqualsCaseInsensitiveASCII(destination_.scheme(),
  169. url::kHttpsScheme));
  170. // This class is specific to a single `ProxyServer`, so `proxy_info_` must be
  171. // non-empty. Entries beyond the first are ignored. It should simply take a
  172. // `ProxyServer`, but the full `ProxyInfo` is passed back to
  173. // `HttpNetworkTransaction`, which consumes additional fields.
  174. DCHECK(!proxy_info_.is_empty());
  175. // QUIC can only be spoken to servers, never to proxies.
  176. if (alternative_protocol == kProtoQUIC)
  177. DCHECK(proxy_info_.is_direct());
  178. // The Job is forced to use QUIC without a designated version, try the
  179. // preferred QUIC version that is supported by default.
  180. if (quic_version_ == quic::ParsedQuicVersion::Unsupported() &&
  181. ShouldForceQuic(session, destination_, proxy_info, using_ssl_)) {
  182. quic_version_ =
  183. session->context().quic_context->params()->supported_versions[0];
  184. }
  185. if (using_quic_) {
  186. DCHECK((quic_version_ != quic::ParsedQuicVersion::Unsupported()) ||
  187. (job_type_ == DNS_ALPN_H3) || (job_type_ == PRECONNECT_DNS_ALPN_H3));
  188. }
  189. DCHECK(session);
  190. if (alternative_protocol != kProtoUnknown) {
  191. // If the alternative service protocol is specified, then the job type must
  192. // be either ALTERNATIVE or PRECONNECT.
  193. DCHECK(job_type_ == ALTERNATIVE || job_type_ == PRECONNECT);
  194. }
  195. if (expect_spdy_) {
  196. DCHECK(origin_url_.SchemeIs(url::kHttpsScheme));
  197. }
  198. if (using_quic_) {
  199. DCHECK(session_->IsQuicEnabled());
  200. }
  201. if (job_type_ == PRECONNECT || is_websocket_) {
  202. DCHECK(request_info_.socket_tag == SocketTag());
  203. }
  204. if (is_websocket_) {
  205. DCHECK(origin_url_.SchemeIsWSOrWSS());
  206. } else {
  207. DCHECK(!origin_url_.SchemeIsWSOrWSS());
  208. }
  209. }
  210. HttpStreamFactory::Job::~Job() {
  211. net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB);
  212. // When we're in a partially constructed state, waiting for the user to
  213. // provide certificate handling information or authentication, we can't reuse
  214. // this stream at all.
  215. if (next_state_ == STATE_WAITING_USER_ACTION) {
  216. connection_->socket()->Disconnect();
  217. connection_.reset();
  218. }
  219. // The stream could be in a partial state. It is not reusable.
  220. if (stream_.get() && next_state_ != STATE_DONE)
  221. stream_->Close(true /* not reusable */);
  222. }
  223. void HttpStreamFactory::Job::Start(HttpStreamRequest::StreamType stream_type) {
  224. stream_type_ = stream_type;
  225. StartInternal();
  226. }
  227. int HttpStreamFactory::Job::Preconnect(int num_streams) {
  228. DCHECK_GT(num_streams, 0);
  229. HttpServerProperties* http_server_properties =
  230. session_->http_server_properties();
  231. DCHECK(http_server_properties);
  232. // Preconnect one connection if either of the following is true:
  233. // (1) kLimitEarlyPreconnectsStreamExperiment is turned on,
  234. // HttpServerProperties is not initialized, and url scheme is cryptographic.
  235. // (2) The server supports H2 or QUIC.
  236. bool connect_one_stream =
  237. base::FeatureList::IsEnabled(kLimitEarlyPreconnectsExperiment) &&
  238. !http_server_properties->IsInitialized() &&
  239. request_info_.url.SchemeIsCryptographic();
  240. if (connect_one_stream || http_server_properties->SupportsRequestPriority(
  241. url::SchemeHostPort(request_info_.url),
  242. request_info_.network_isolation_key)) {
  243. num_streams_ = 1;
  244. } else {
  245. num_streams_ = num_streams;
  246. }
  247. return StartInternal();
  248. }
  249. int HttpStreamFactory::Job::RestartTunnelWithProxyAuth() {
  250. DCHECK(establishing_tunnel_);
  251. DCHECK(restart_with_auth_callback_);
  252. std::move(restart_with_auth_callback_).Run();
  253. return ERR_IO_PENDING;
  254. }
  255. LoadState HttpStreamFactory::Job::GetLoadState() const {
  256. switch (next_state_) {
  257. case STATE_INIT_CONNECTION_COMPLETE:
  258. case STATE_CREATE_STREAM_COMPLETE:
  259. return using_quic_ ? LOAD_STATE_CONNECTING : connection_->GetLoadState();
  260. default:
  261. return LOAD_STATE_IDLE;
  262. }
  263. }
  264. void HttpStreamFactory::Job::Resume() {
  265. DCHECK_EQ(job_type_, MAIN);
  266. DCHECK_EQ(next_state_, STATE_WAIT_COMPLETE);
  267. OnIOComplete(OK);
  268. }
  269. void HttpStreamFactory::Job::Orphan() {
  270. DCHECK(job_type_ == ALTERNATIVE || job_type_ == DNS_ALPN_H3);
  271. net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_ORPHANED);
  272. // Watching for SPDY sessions isn't supported on orphaned jobs.
  273. // TODO(mmenke): Fix that.
  274. spdy_session_request_.reset();
  275. }
  276. void HttpStreamFactory::Job::SetPriority(RequestPriority priority) {
  277. priority_ = priority;
  278. // Ownership of |connection_| is passed to the newly created stream
  279. // or H2 session in DoCreateStream(), and the consumer is not
  280. // notified immediately, so this call may occur when |connection_|
  281. // is null.
  282. //
  283. // Note that streams are created without a priority associated with them,
  284. // and it is up to the consumer to set their priority via
  285. // HttpStream::InitializeStream(). So there is no need for this code
  286. // to propagate priority changes to the newly created stream.
  287. if (connection_ && connection_->is_initialized())
  288. connection_->SetPriority(priority);
  289. // TODO(akalin): Maybe Propagate this to the preconnect state.
  290. }
  291. bool HttpStreamFactory::Job::HasAvailableSpdySession() const {
  292. return !using_quic_ && CanUseExistingSpdySession() &&
  293. session_->spdy_session_pool()->HasAvailableSession(spdy_session_key_,
  294. is_websocket_);
  295. }
  296. bool HttpStreamFactory::Job::HasAvailableQuicSession() const {
  297. if (!using_quic_)
  298. return false;
  299. bool require_dns_https_alpn = (job_type_ == DNS_ALPN_H3);
  300. return quic_request_.CanUseExistingSession(
  301. origin_url_, request_info_.privacy_mode, request_info_.socket_tag,
  302. request_info_.network_isolation_key, request_info_.secure_dns_policy,
  303. require_dns_https_alpn, destination_);
  304. }
  305. bool HttpStreamFactory::Job::TargettedSocketGroupHasActiveSocket() const {
  306. DCHECK(!using_quic_);
  307. DCHECK(!is_websocket_);
  308. ClientSocketPool* pool = session_->GetSocketPool(
  309. HttpNetworkSession::NORMAL_SOCKET_POOL, proxy_info_.proxy_server());
  310. DCHECK(pool);
  311. ClientSocketPool::GroupId connection_group(
  312. destination_, request_info_.privacy_mode,
  313. request_info_.network_isolation_key, request_info_.secure_dns_policy);
  314. return pool->HasActiveSocket(connection_group);
  315. }
  316. bool HttpStreamFactory::Job::was_alpn_negotiated() const {
  317. return was_alpn_negotiated_;
  318. }
  319. NextProto HttpStreamFactory::Job::negotiated_protocol() const {
  320. return negotiated_protocol_;
  321. }
  322. bool HttpStreamFactory::Job::using_spdy() const {
  323. return using_spdy_;
  324. }
  325. const ProxyInfo& HttpStreamFactory::Job::proxy_info() const {
  326. return proxy_info_;
  327. }
  328. ResolveErrorInfo HttpStreamFactory::Job::resolve_error_info() const {
  329. return resolve_error_info_;
  330. }
  331. void HttpStreamFactory::Job::GetSSLInfo(SSLInfo* ssl_info) {
  332. DCHECK(using_ssl_);
  333. DCHECK(!establishing_tunnel_);
  334. DCHECK(connection_.get() && connection_->socket());
  335. connection_->socket()->GetSSLInfo(ssl_info);
  336. }
  337. // static
  338. bool HttpStreamFactory::Job::ShouldForceQuic(
  339. HttpNetworkSession* session,
  340. const url::SchemeHostPort& destination,
  341. const ProxyInfo& proxy_info,
  342. bool using_ssl) {
  343. if (!session->IsQuicEnabled())
  344. return false;
  345. // If this is going through a QUIC proxy, only force QUIC for insecure
  346. // requests. If the request is secure, a tunnel will be needed, and those are
  347. // handled by the socket pools, using an HttpProxyConnectJob.
  348. if (proxy_info.is_quic())
  349. return !using_ssl;
  350. const QuicParams* quic_params = session->context().quic_context->params();
  351. // TODO(crbug.com/1206799): Consider converting `origins_to_force_quic_on` to
  352. // use url::SchemeHostPort.
  353. return (base::Contains(quic_params->origins_to_force_quic_on,
  354. HostPortPair()) ||
  355. base::Contains(quic_params->origins_to_force_quic_on,
  356. HostPortPair::FromSchemeHostPort(destination))) &&
  357. proxy_info.is_direct() &&
  358. base::EqualsCaseInsensitiveASCII(destination.scheme(),
  359. url::kHttpsScheme);
  360. }
  361. // static
  362. SpdySessionKey HttpStreamFactory::Job::GetSpdySessionKey(
  363. const ProxyServer& proxy_server,
  364. const GURL& origin_url,
  365. PrivacyMode privacy_mode,
  366. const SocketTag& socket_tag,
  367. const NetworkIsolationKey& network_isolation_key,
  368. SecureDnsPolicy secure_dns_policy) {
  369. // In the case that we're using an HTTPS proxy for an HTTP url, look for a
  370. // HTTP/2 proxy session *to* the proxy, instead of to the origin server.
  371. if (proxy_server.is_https() && origin_url.SchemeIs(url::kHttpScheme)) {
  372. return SpdySessionKey(proxy_server.host_port_pair(), ProxyServer::Direct(),
  373. PRIVACY_MODE_DISABLED,
  374. SpdySessionKey::IsProxySession::kTrue, socket_tag,
  375. network_isolation_key, secure_dns_policy);
  376. }
  377. return SpdySessionKey(HostPortPair::FromURL(origin_url), proxy_server,
  378. privacy_mode, SpdySessionKey::IsProxySession::kFalse,
  379. socket_tag, network_isolation_key, secure_dns_policy);
  380. }
  381. bool HttpStreamFactory::Job::CanUseExistingSpdySession() const {
  382. DCHECK(!using_quic_);
  383. if (proxy_info_.is_direct() &&
  384. session_->http_server_properties()->RequiresHTTP11(
  385. url::SchemeHostPort(request_info_.url),
  386. request_info_.network_isolation_key)) {
  387. return false;
  388. }
  389. if (is_websocket_)
  390. return try_websocket_over_http2_;
  391. DCHECK(origin_url_.SchemeIsHTTPOrHTTPS());
  392. // We need to make sure that if a HTTP/2 session was created for
  393. // https://somehost/ then we do not use that session for http://somehost:443/.
  394. // The only time we can use an existing session is if the request URL is
  395. // https (the normal case) or if we are connecting to a HTTP/2 proxy.
  396. // https://crbug.com/133176
  397. return origin_url_.SchemeIs(url::kHttpsScheme) ||
  398. proxy_info_.proxy_server().is_https();
  399. }
  400. void HttpStreamFactory::Job::OnStreamReadyCallback() {
  401. DCHECK(stream_.get());
  402. DCHECK_NE(job_type_, PRECONNECT);
  403. DCHECK_NE(job_type_, PRECONNECT_DNS_ALPN_H3);
  404. DCHECK(!is_websocket_ || try_websocket_over_http2_);
  405. MaybeCopyConnectionAttemptsFromHandle();
  406. delegate_->OnStreamReady(this, server_ssl_config_);
  407. // |this| may be deleted after this call.
  408. }
  409. void HttpStreamFactory::Job::OnWebSocketHandshakeStreamReadyCallback() {
  410. DCHECK(websocket_stream_);
  411. DCHECK_NE(job_type_, PRECONNECT);
  412. DCHECK_NE(job_type_, PRECONNECT_DNS_ALPN_H3);
  413. DCHECK(is_websocket_);
  414. MaybeCopyConnectionAttemptsFromHandle();
  415. delegate_->OnWebSocketHandshakeStreamReady(
  416. this, server_ssl_config_, proxy_info_, std::move(websocket_stream_));
  417. // |this| may be deleted after this call.
  418. }
  419. void HttpStreamFactory::Job::OnBidirectionalStreamImplReadyCallback() {
  420. DCHECK(bidirectional_stream_impl_);
  421. MaybeCopyConnectionAttemptsFromHandle();
  422. delegate_->OnBidirectionalStreamImplReady(this, server_ssl_config_,
  423. proxy_info_);
  424. // |this| may be deleted after this call.
  425. }
  426. void HttpStreamFactory::Job::OnStreamFailedCallback(int result) {
  427. DCHECK_NE(job_type_, PRECONNECT);
  428. DCHECK_NE(job_type_, PRECONNECT_DNS_ALPN_H3);
  429. MaybeCopyConnectionAttemptsFromHandle();
  430. delegate_->OnStreamFailed(this, result, server_ssl_config_);
  431. // |this| may be deleted after this call.
  432. }
  433. void HttpStreamFactory::Job::OnCertificateErrorCallback(
  434. int result,
  435. const SSLInfo& ssl_info) {
  436. DCHECK_NE(job_type_, PRECONNECT);
  437. DCHECK_NE(job_type_, PRECONNECT_DNS_ALPN_H3);
  438. DCHECK(!spdy_session_request_);
  439. MaybeCopyConnectionAttemptsFromHandle();
  440. delegate_->OnCertificateError(this, result, server_ssl_config_, ssl_info);
  441. // |this| may be deleted after this call.
  442. }
  443. void HttpStreamFactory::Job::OnNeedsProxyAuthCallback(
  444. const HttpResponseInfo& response,
  445. HttpAuthController* auth_controller,
  446. base::OnceClosure restart_with_auth_callback) {
  447. DCHECK_NE(job_type_, PRECONNECT);
  448. DCHECK_NE(job_type_, PRECONNECT_DNS_ALPN_H3);
  449. DCHECK(establishing_tunnel_);
  450. DCHECK(!restart_with_auth_callback_);
  451. restart_with_auth_callback_ = std::move(restart_with_auth_callback);
  452. // This is called out of band, so need to abort the SpdySessionRequest to
  453. // prevent being passed a new session while waiting on proxy auth credentials.
  454. spdy_session_request_.reset();
  455. delegate_->OnNeedsProxyAuth(this, response, server_ssl_config_, proxy_info_,
  456. auth_controller);
  457. // |this| may be deleted after this call.
  458. }
  459. void HttpStreamFactory::Job::OnNeedsClientAuthCallback(
  460. SSLCertRequestInfo* cert_info) {
  461. DCHECK_NE(job_type_, PRECONNECT);
  462. DCHECK_NE(job_type_, PRECONNECT_DNS_ALPN_H3);
  463. DCHECK(!spdy_session_request_);
  464. delegate_->OnNeedsClientAuth(this, server_ssl_config_, cert_info);
  465. // |this| may be deleted after this call.
  466. }
  467. void HttpStreamFactory::Job::OnPreconnectsComplete(int result) {
  468. delegate_->OnPreconnectsComplete(this, result);
  469. // |this| may be deleted after this call.
  470. }
  471. void HttpStreamFactory::Job::OnIOComplete(int result) {
  472. TRACE_EVENT0(NetTracingCategory(), "HttpStreamFactory::Job::OnIOComplete");
  473. RunLoop(result);
  474. }
  475. void HttpStreamFactory::Job::RunLoop(int result) {
  476. TRACE_EVENT0(NetTracingCategory(), "HttpStreamFactory::Job::RunLoop");
  477. result = DoLoop(result);
  478. if (result == ERR_IO_PENDING)
  479. return;
  480. // Stop watching for new SpdySessions, to avoid receiving a new SPDY session
  481. // while doing anything other than waiting to establish a connection.
  482. spdy_session_request_.reset();
  483. if ((job_type_ == PRECONNECT) || (job_type_ == PRECONNECT_DNS_ALPN_H3)) {
  484. base::ThreadTaskRunnerHandle::Get()->PostTask(
  485. FROM_HERE,
  486. base::BindOnce(&HttpStreamFactory::Job::OnPreconnectsComplete,
  487. ptr_factory_.GetWeakPtr(), result));
  488. return;
  489. }
  490. if (IsCertificateError(result)) {
  491. // Retrieve SSL information from the socket.
  492. SSLInfo ssl_info;
  493. GetSSLInfo(&ssl_info);
  494. next_state_ = STATE_WAITING_USER_ACTION;
  495. base::ThreadTaskRunnerHandle::Get()->PostTask(
  496. FROM_HERE,
  497. base::BindOnce(&HttpStreamFactory::Job::OnCertificateErrorCallback,
  498. ptr_factory_.GetWeakPtr(), result, ssl_info));
  499. return;
  500. }
  501. switch (result) {
  502. case ERR_SSL_CLIENT_AUTH_CERT_NEEDED:
  503. base::ThreadTaskRunnerHandle::Get()->PostTask(
  504. FROM_HERE,
  505. base::BindOnce(
  506. &Job::OnNeedsClientAuthCallback, ptr_factory_.GetWeakPtr(),
  507. base::RetainedRef(connection_->ssl_cert_request_info())));
  508. return;
  509. case OK:
  510. next_state_ = STATE_DONE;
  511. if (is_websocket_) {
  512. DCHECK(websocket_stream_);
  513. base::ThreadTaskRunnerHandle::Get()->PostTask(
  514. FROM_HERE,
  515. base::BindOnce(&Job::OnWebSocketHandshakeStreamReadyCallback,
  516. ptr_factory_.GetWeakPtr()));
  517. } else if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) {
  518. if (!bidirectional_stream_impl_) {
  519. base::ThreadTaskRunnerHandle::Get()->PostTask(
  520. FROM_HERE, base::BindOnce(&Job::OnStreamFailedCallback,
  521. ptr_factory_.GetWeakPtr(), ERR_FAILED));
  522. } else {
  523. base::ThreadTaskRunnerHandle::Get()->PostTask(
  524. FROM_HERE,
  525. base::BindOnce(&Job::OnBidirectionalStreamImplReadyCallback,
  526. ptr_factory_.GetWeakPtr()));
  527. }
  528. } else {
  529. DCHECK(stream_.get());
  530. base::ThreadTaskRunnerHandle::Get()->PostTask(
  531. FROM_HERE, base::BindOnce(&Job::OnStreamReadyCallback,
  532. ptr_factory_.GetWeakPtr()));
  533. }
  534. return;
  535. default:
  536. base::ThreadTaskRunnerHandle::Get()->PostTask(
  537. FROM_HERE, base::BindOnce(&Job::OnStreamFailedCallback,
  538. ptr_factory_.GetWeakPtr(), result));
  539. return;
  540. }
  541. }
  542. int HttpStreamFactory::Job::DoLoop(int result) {
  543. DCHECK_NE(next_state_, STATE_NONE);
  544. int rv = result;
  545. do {
  546. State state = next_state_;
  547. next_state_ = STATE_NONE;
  548. switch (state) {
  549. case STATE_START:
  550. DCHECK_EQ(OK, rv);
  551. rv = DoStart();
  552. break;
  553. case STATE_WAIT:
  554. DCHECK_EQ(OK, rv);
  555. rv = DoWait();
  556. break;
  557. case STATE_WAIT_COMPLETE:
  558. rv = DoWaitComplete(rv);
  559. break;
  560. case STATE_INIT_CONNECTION:
  561. DCHECK_EQ(OK, rv);
  562. rv = DoInitConnection();
  563. break;
  564. case STATE_INIT_CONNECTION_COMPLETE:
  565. rv = DoInitConnectionComplete(rv);
  566. break;
  567. case STATE_WAITING_USER_ACTION:
  568. rv = DoWaitingUserAction(rv);
  569. break;
  570. case STATE_CREATE_STREAM:
  571. DCHECK_EQ(OK, rv);
  572. rv = DoCreateStream();
  573. break;
  574. case STATE_CREATE_STREAM_COMPLETE:
  575. rv = DoCreateStreamComplete(rv);
  576. break;
  577. default:
  578. NOTREACHED() << "bad state";
  579. rv = ERR_FAILED;
  580. break;
  581. }
  582. } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
  583. return rv;
  584. }
  585. int HttpStreamFactory::Job::StartInternal() {
  586. CHECK_EQ(STATE_NONE, next_state_);
  587. next_state_ = STATE_START;
  588. RunLoop(OK);
  589. return ERR_IO_PENDING;
  590. }
  591. int HttpStreamFactory::Job::DoStart() {
  592. const NetLogWithSource* net_log = delegate_->GetNetLog();
  593. if (net_log) {
  594. net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB, [&] {
  595. return NetLogHttpStreamJobParams(net_log->source(), request_info_.url,
  596. origin_url_, expect_spdy_, using_quic_,
  597. job_type_, priority_);
  598. });
  599. net_log->AddEventReferencingSource(
  600. NetLogEventType::HTTP_STREAM_REQUEST_STARTED_JOB, net_log_.source());
  601. }
  602. // Don't connect to restricted ports.
  603. if (!IsPortAllowedForScheme(destination_.port(),
  604. request_info_.url.scheme_piece())) {
  605. return ERR_UNSAFE_PORT;
  606. }
  607. if (!session_->params().enable_quic_proxies_for_https_urls &&
  608. proxy_info_.is_quic() && request_info_.url.SchemeIsCryptographic()) {
  609. return ERR_NOT_IMPLEMENTED;
  610. }
  611. next_state_ = STATE_WAIT;
  612. return OK;
  613. }
  614. int HttpStreamFactory::Job::DoWait() {
  615. next_state_ = STATE_WAIT_COMPLETE;
  616. bool should_wait = delegate_->ShouldWait(this);
  617. net_log_.AddEntryWithBoolParams(NetLogEventType::HTTP_STREAM_JOB_WAITING,
  618. NetLogEventPhase::BEGIN, "should_wait",
  619. should_wait);
  620. if (should_wait)
  621. return ERR_IO_PENDING;
  622. return OK;
  623. }
  624. int HttpStreamFactory::Job::DoWaitComplete(int result) {
  625. net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_WAITING);
  626. DCHECK_EQ(OK, result);
  627. next_state_ = STATE_INIT_CONNECTION;
  628. return OK;
  629. }
  630. void HttpStreamFactory::Job::ResumeInitConnection() {
  631. if (init_connection_already_resumed_)
  632. return;
  633. DCHECK_EQ(next_state_, STATE_INIT_CONNECTION);
  634. net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_RESUME_INIT_CONNECTION);
  635. init_connection_already_resumed_ = true;
  636. OnIOComplete(OK);
  637. }
  638. int HttpStreamFactory::Job::DoInitConnection() {
  639. net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_INIT_CONNECTION);
  640. int result = DoInitConnectionImpl();
  641. if (!expect_on_quic_host_resolution_) {
  642. delegate_->OnConnectionInitialized(this, result);
  643. }
  644. return result;
  645. }
  646. int HttpStreamFactory::Job::DoInitConnectionImpl() {
  647. DCHECK(!connection_->is_initialized());
  648. if (using_quic_ && !proxy_info_.is_quic() && !proxy_info_.is_direct()) {
  649. // QUIC can not be spoken to non-QUIC proxies. This error should not be
  650. // user visible, because the non-alternative Job should be resumed.
  651. return ERR_NO_SUPPORTED_PROXIES;
  652. }
  653. DCHECK(proxy_info_.proxy_server().is_valid());
  654. next_state_ = STATE_INIT_CONNECTION_COMPLETE;
  655. if (proxy_info_.is_secure_http_like()) {
  656. // Disable network fetches for HTTPS proxies, since the network requests
  657. // are probably going to need to go through the proxy too.
  658. proxy_ssl_config_.disable_cert_verification_network_fetches = true;
  659. }
  660. if (using_ssl_) {
  661. // Prior to HTTP/2 and SPDY, some servers use TLS renegotiation to request
  662. // TLS client authentication after the HTTP request was sent. Allow
  663. // renegotiation for only those connections.
  664. //
  665. // Note that this does NOT implement the provision in
  666. // https://http2.github.io/http2-spec/#rfc.section.9.2.1 which allows the
  667. // server to request a renegotiation immediately before sending the
  668. // connection preface as waiting for the preface would cost the round trip
  669. // that False Start otherwise saves.
  670. server_ssl_config_.renego_allowed_default = true;
  671. server_ssl_config_.renego_allowed_for_protos.push_back(kProtoHTTP11);
  672. }
  673. server_ssl_config_.alpn_protos = session_->GetAlpnProtos();
  674. proxy_ssl_config_.alpn_protos = session_->GetAlpnProtos();
  675. server_ssl_config_.application_settings = session_->GetApplicationSettings();
  676. proxy_ssl_config_.application_settings = session_->GetApplicationSettings();
  677. server_ssl_config_.ignore_certificate_errors =
  678. session_->params().ignore_certificate_errors;
  679. proxy_ssl_config_.ignore_certificate_errors =
  680. session_->params().ignore_certificate_errors;
  681. // TODO(https://crbug.com/964642): Also enable 0-RTT for TLS proxies.
  682. server_ssl_config_.early_data_enabled = session_->params().enable_early_data;
  683. if (using_quic_)
  684. return DoInitConnectionImplQuic();
  685. // Check first if there is a pushed stream matching the request, or an HTTP/2
  686. // connection this request can pool to. If so, then go straight to using
  687. // that.
  688. if (CanUseExistingSpdySession()) {
  689. if (!is_websocket_) {
  690. session_->spdy_session_pool()->push_promise_index()->ClaimPushedStream(
  691. spdy_session_key_, origin_url_, request_info_,
  692. &existing_spdy_session_, &pushed_stream_id_);
  693. }
  694. if (!existing_spdy_session_) {
  695. if (!spdy_session_request_) {
  696. // If not currently watching for an H2 session, use
  697. // SpdySessionPool::RequestSession() to check for a session, and start
  698. // watching for one.
  699. bool should_throttle_connect = ShouldThrottleConnectForSpdy();
  700. base::RepeatingClosure resume_callback =
  701. should_throttle_connect
  702. ? base::BindRepeating(
  703. &HttpStreamFactory::Job::ResumeInitConnection,
  704. ptr_factory_.GetWeakPtr())
  705. : base::RepeatingClosure();
  706. bool is_blocking_request_for_session;
  707. existing_spdy_session_ = session_->spdy_session_pool()->RequestSession(
  708. spdy_session_key_, enable_ip_based_pooling_, is_websocket_,
  709. net_log_, resume_callback, this, &spdy_session_request_,
  710. &is_blocking_request_for_session);
  711. if (!existing_spdy_session_ && should_throttle_connect &&
  712. !is_blocking_request_for_session) {
  713. net_log_.AddEvent(NetLogEventType::HTTP_STREAM_JOB_THROTTLED);
  714. next_state_ = STATE_INIT_CONNECTION;
  715. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  716. FROM_HERE, resume_callback, base::Milliseconds(kHTTP2ThrottleMs));
  717. return ERR_IO_PENDING;
  718. }
  719. } else if (enable_ip_based_pooling_) {
  720. // If already watching for an H2 session, still need to check for an
  721. // existing connection that can be reused through IP pooling, as those
  722. // don't post session available notifications.
  723. //
  724. // TODO(mmenke): Make sessions created through IP pooling invoke the
  725. // callback.
  726. existing_spdy_session_ =
  727. session_->spdy_session_pool()->FindAvailableSession(
  728. spdy_session_key_, enable_ip_based_pooling_, is_websocket_,
  729. net_log_);
  730. }
  731. }
  732. if (existing_spdy_session_) {
  733. // Stop watching for SpdySessions.
  734. spdy_session_request_.reset();
  735. // If we're preconnecting, but we already have a SpdySession, we don't
  736. // actually need to preconnect any sockets, so we're done.
  737. if (job_type_ == PRECONNECT)
  738. return OK;
  739. using_spdy_ = true;
  740. next_state_ = STATE_CREATE_STREAM;
  741. return OK;
  742. }
  743. }
  744. if (proxy_info_.is_http_like())
  745. establishing_tunnel_ = using_ssl_;
  746. HttpServerProperties* http_server_properties =
  747. session_->http_server_properties();
  748. if (http_server_properties) {
  749. http_server_properties->MaybeForceHTTP11(
  750. url::SchemeHostPort(request_info_.url),
  751. request_info_.network_isolation_key, &server_ssl_config_);
  752. if (proxy_info_.is_https()) {
  753. http_server_properties->MaybeForceHTTP11(
  754. url::SchemeHostPort(
  755. url::kHttpsScheme,
  756. proxy_info_.proxy_server().host_port_pair().host(),
  757. proxy_info_.proxy_server().host_port_pair().port()),
  758. request_info_.network_isolation_key, &proxy_ssl_config_);
  759. }
  760. }
  761. if (job_type_ == PRECONNECT) {
  762. DCHECK(!is_websocket_);
  763. DCHECK(request_info_.socket_tag == SocketTag());
  764. // The lifeime of the preconnect tasks is not controlled by |connection_|.
  765. // It may outlives |this|. So we can't use |io_callback_| which holds
  766. // base::Unretained(this).
  767. auto callback =
  768. base::BindOnce(&Job::OnIOComplete, ptr_factory_.GetWeakPtr());
  769. return PreconnectSocketsForHttpRequest(
  770. destination_, request_info_.load_flags, priority_, session_,
  771. proxy_info_, server_ssl_config_, proxy_ssl_config_,
  772. request_info_.privacy_mode, request_info_.network_isolation_key,
  773. request_info_.secure_dns_policy, net_log_, num_streams_,
  774. std::move(callback));
  775. }
  776. ClientSocketPool::ProxyAuthCallback proxy_auth_callback =
  777. base::BindRepeating(&HttpStreamFactory::Job::OnNeedsProxyAuthCallback,
  778. base::Unretained(this));
  779. if (is_websocket_) {
  780. DCHECK(request_info_.socket_tag == SocketTag());
  781. DCHECK_EQ(SecureDnsPolicy::kAllow, request_info_.secure_dns_policy);
  782. // Only offer HTTP/1.1 for WebSockets. Although RFC 8441 defines WebSockets
  783. // over HTTP/2, a single WSS/HTTPS origin may support HTTP over HTTP/2
  784. // without supporting WebSockets over HTTP/2. Offering HTTP/2 for a fresh
  785. // connection would break such origins.
  786. //
  787. // However, still offer HTTP/1.1 rather than skipping ALPN entirely. While
  788. // this will not change the application protocol (HTTP/1.1 is default), it
  789. // provides hardens against cross-protocol attacks and allows for the False
  790. // Start (RFC 7918) optimization.
  791. SSLConfig websocket_server_ssl_config = server_ssl_config_;
  792. websocket_server_ssl_config.alpn_protos = {kProtoHTTP11};
  793. return InitSocketHandleForWebSocketRequest(
  794. destination_, request_info_.load_flags, priority_, session_,
  795. proxy_info_, websocket_server_ssl_config, proxy_ssl_config_,
  796. request_info_.privacy_mode, request_info_.network_isolation_key,
  797. net_log_, connection_.get(), io_callback_, proxy_auth_callback);
  798. }
  799. return InitSocketHandleForHttpRequest(
  800. destination_, request_info_.load_flags, priority_, session_, proxy_info_,
  801. server_ssl_config_, proxy_ssl_config_, request_info_.privacy_mode,
  802. request_info_.network_isolation_key, request_info_.secure_dns_policy,
  803. request_info_.socket_tag, net_log_, connection_.get(), io_callback_,
  804. proxy_auth_callback);
  805. }
  806. int HttpStreamFactory::Job::DoInitConnectionImplQuic() {
  807. url::SchemeHostPort destination;
  808. SSLConfig* ssl_config;
  809. GURL url(request_info_.url);
  810. if (proxy_info_.is_quic()) {
  811. ssl_config = &proxy_ssl_config_;
  812. const HostPortPair& proxy_endpoint =
  813. proxy_info_.proxy_server().host_port_pair();
  814. destination = url::SchemeHostPort(url::kHttpsScheme, proxy_endpoint.host(),
  815. proxy_endpoint.port());
  816. url = destination.GetURL();
  817. } else {
  818. DCHECK(using_ssl_);
  819. destination = destination_;
  820. ssl_config = &server_ssl_config_;
  821. }
  822. DCHECK(url.SchemeIs(url::kHttpsScheme));
  823. bool require_dns_https_alpn =
  824. (job_type_ == DNS_ALPN_H3) || (job_type_ == PRECONNECT_DNS_ALPN_H3);
  825. int rv = quic_request_.Request(
  826. std::move(destination), quic_version_, request_info_.privacy_mode,
  827. priority_, request_info_.socket_tag, request_info_.network_isolation_key,
  828. request_info_.secure_dns_policy, proxy_info_.is_direct(),
  829. require_dns_https_alpn, ssl_config->GetCertVerifyFlags(), url, net_log_,
  830. &net_error_details_,
  831. base::BindOnce(&Job::OnFailedOnDefaultNetwork, ptr_factory_.GetWeakPtr()),
  832. io_callback_);
  833. if (rv == OK) {
  834. using_existing_quic_session_ = true;
  835. } else if (rv == ERR_IO_PENDING) {
  836. // There's no available QUIC session. Inform the delegate how long to
  837. // delay the main job.
  838. delegate_->MaybeSetWaitTimeForMainJob(
  839. quic_request_.GetTimeDelayForWaitingJob());
  840. expect_on_quic_host_resolution_ = quic_request_.WaitForHostResolution(
  841. base::BindOnce(&Job::OnQuicHostResolution, base::Unretained(this)));
  842. }
  843. return rv;
  844. }
  845. void HttpStreamFactory::Job::OnQuicHostResolution(int result) {
  846. DCHECK(expect_on_quic_host_resolution_);
  847. expect_on_quic_host_resolution_ = false;
  848. delegate_->OnConnectionInitialized(this, result);
  849. }
  850. void HttpStreamFactory::Job::OnFailedOnDefaultNetwork(int result) {
  851. DCHECK(job_type_ == ALTERNATIVE || job_type_ == DNS_ALPN_H3);
  852. DCHECK(using_quic_);
  853. delegate_->OnFailedOnDefaultNetwork(this);
  854. }
  855. int HttpStreamFactory::Job::DoInitConnectionComplete(int result) {
  856. net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_INIT_CONNECTION);
  857. // No need to continue waiting for a session, once a connection is
  858. // established.
  859. spdy_session_request_.reset();
  860. if ((job_type_ == PRECONNECT) || (job_type_ == PRECONNECT_DNS_ALPN_H3)) {
  861. if (using_quic_)
  862. return result;
  863. DCHECK_EQ(OK, result);
  864. return OK;
  865. }
  866. resolve_error_info_ = connection_->resolve_error_info();
  867. // Determine the protocol (HTTP/1.1, HTTP/2, or HTTP/3). This covers both the
  868. // origin and some proxy cases. First, if the URL is HTTPS (or WSS), we may
  869. // negotiate HTTP/2 or HTTP/3 with the origin. Second, non-tunneled requests
  870. // (i.e. HTTP URLs) through an HTTPS or QUIC proxy work by sending the request
  871. // to the proxy directly. In that case, this logic also handles the proxy's
  872. // negotiated protocol. HTTPS requests are always tunneled, so at most one of
  873. // these applies.
  874. //
  875. // Tunneled requests may also negotiate ALPN at the proxy, but
  876. // HttpProxyConnectJob handles ALPN. The resulting StreamSocket will not
  877. // report an ALPN protocol.
  878. if (result == OK) {
  879. if (using_quic_) {
  880. // TODO(davidben): Record these values consistently between QUIC and TCP
  881. // below. In the QUIC case, we only record it for origin connections. In
  882. // the TCP case, we also record it for non-tunneled, proxied requests.
  883. if (using_ssl_) {
  884. was_alpn_negotiated_ = true;
  885. negotiated_protocol_ = kProtoQUIC;
  886. }
  887. } else if (connection_->socket()->WasAlpnNegotiated()) {
  888. // Only connections that use TLS can negotiate ALPN.
  889. DCHECK(using_ssl_ || proxy_info_.is_secure_http_like());
  890. was_alpn_negotiated_ = true;
  891. negotiated_protocol_ = connection_->socket()->GetNegotiatedProtocol();
  892. net_log_.AddEvent(NetLogEventType::HTTP_STREAM_REQUEST_PROTO, [&] {
  893. return NetLogHttpStreamProtoParams(negotiated_protocol_);
  894. });
  895. if (negotiated_protocol_ == kProtoHTTP2) {
  896. if (is_websocket_) {
  897. // WebSocket is not supported over a fresh HTTP/2 connection. This
  898. // should not be reachable. For the origin, we do not request HTTP/2
  899. // on fresh WebSockets connections, because not all HTTP/2 servers
  900. // implement RFC 8441. For proxies, WebSockets are always tunneled.
  901. //
  902. // TODO(davidben): This isn't a CHECK() because, previously, it was
  903. // reachable in https://crbug.com/828865. However, if reachable, it
  904. // means a bug in the socket pools. The socket pools have since been
  905. // cleaned up, so this may no longer be reachable. Restore the CHECK
  906. // and see if this is still needed.
  907. return ERR_NOT_IMPLEMENTED;
  908. }
  909. using_spdy_ = true;
  910. }
  911. }
  912. }
  913. if (proxy_info_.is_quic() && using_quic_ && result < 0)
  914. return ReconsiderProxyAfterError(result);
  915. if (expect_spdy_ && !using_spdy_)
  916. return ERR_ALPN_NEGOTIATION_FAILED;
  917. // |result| may be the result of any of the stacked protocols. The following
  918. // logic is used when determining how to interpret an error.
  919. // If |result| < 0:
  920. // and connection_->socket() != NULL, then the SSL handshake ran and it
  921. // is a potentially recoverable error.
  922. // and connection_->socket == NULL and connection_->is_ssl_error() is true,
  923. // then the SSL handshake ran with an unrecoverable error.
  924. // otherwise, the error came from one of the other protocols.
  925. bool ssl_started = using_ssl_ && (result == OK || connection_->socket() ||
  926. connection_->is_ssl_error());
  927. if (!ssl_started && result < 0 && (expect_spdy_ || using_quic_))
  928. return result;
  929. if (using_quic_) {
  930. if (result < 0)
  931. return result;
  932. if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) {
  933. std::unique_ptr<QuicChromiumClientSession::Handle> session =
  934. quic_request_.ReleaseSessionHandle();
  935. if (!session) {
  936. // Quic session is closed before stream can be created.
  937. return ERR_CONNECTION_CLOSED;
  938. }
  939. bidirectional_stream_impl_ =
  940. std::make_unique<BidirectionalStreamQuicImpl>(std::move(session));
  941. } else {
  942. std::unique_ptr<QuicChromiumClientSession::Handle> session =
  943. quic_request_.ReleaseSessionHandle();
  944. if (!session) {
  945. // Quic session is closed before stream can be created.
  946. return ERR_CONNECTION_CLOSED;
  947. }
  948. auto dns_aliases =
  949. session->GetDnsAliasesForSessionKey(quic_request_.session_key());
  950. stream_ = std::make_unique<QuicHttpStream>(std::move(session),
  951. std::move(dns_aliases));
  952. }
  953. next_state_ = STATE_NONE;
  954. return OK;
  955. }
  956. if (result < 0 && !ssl_started)
  957. return ReconsiderProxyAfterError(result);
  958. establishing_tunnel_ = false;
  959. // Handle SSL errors below.
  960. if (using_ssl_) {
  961. DCHECK(ssl_started);
  962. if (IsCertificateError(result)) {
  963. SSLInfo ssl_info;
  964. GetSSLInfo(&ssl_info);
  965. if (ssl_info.cert) {
  966. // Add the bad certificate to the set of allowed certificates in the
  967. // SSL config object. This data structure will be consulted after
  968. // calling RestartIgnoringLastError(). And the user will be asked
  969. // interactively before RestartIgnoringLastError() is ever called.
  970. server_ssl_config_.allowed_bad_certs.emplace_back(ssl_info.cert,
  971. ssl_info.cert_status);
  972. }
  973. }
  974. if (result < 0)
  975. return result;
  976. }
  977. next_state_ = STATE_CREATE_STREAM;
  978. return OK;
  979. }
  980. int HttpStreamFactory::Job::DoWaitingUserAction(int result) {
  981. // This state indicates that the stream request is in a partially
  982. // completed state, and we've called back to the delegate for more
  983. // information.
  984. // We're always waiting here for the delegate to call us back.
  985. return ERR_IO_PENDING;
  986. }
  987. int HttpStreamFactory::Job::SetSpdyHttpStreamOrBidirectionalStreamImpl(
  988. base::WeakPtr<SpdySession> session) {
  989. DCHECK(using_spdy_);
  990. auto dns_aliases = session_->spdy_session_pool()->GetDnsAliasesForSessionKey(
  991. spdy_session_key_);
  992. if (is_websocket_) {
  993. DCHECK_NE(job_type_, PRECONNECT);
  994. DCHECK_NE(job_type_, PRECONNECT_DNS_ALPN_H3);
  995. DCHECK(delegate_->websocket_handshake_stream_create_helper());
  996. if (!try_websocket_over_http2_) {
  997. // TODO(davidben): Is this reachable? We shouldn't receive a SpdySession
  998. // if not requested.
  999. return ERR_NOT_IMPLEMENTED;
  1000. }
  1001. websocket_stream_ =
  1002. delegate_->websocket_handshake_stream_create_helper()
  1003. ->CreateHttp2Stream(session, std::move(dns_aliases));
  1004. return OK;
  1005. }
  1006. if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) {
  1007. bidirectional_stream_impl_ = std::make_unique<BidirectionalStreamSpdyImpl>(
  1008. session, net_log_.source());
  1009. return OK;
  1010. }
  1011. // TODO(willchan): Delete this code, because eventually, the HttpStreamFactory
  1012. // will be creating all the SpdyHttpStreams, since it will know when
  1013. // SpdySessions become available.
  1014. stream_ = std::make_unique<SpdyHttpStream>(
  1015. session, pushed_stream_id_, net_log_.source(), std::move(dns_aliases));
  1016. return OK;
  1017. }
  1018. int HttpStreamFactory::Job::DoCreateStream() {
  1019. DCHECK(connection_->socket() || existing_spdy_session_.get());
  1020. DCHECK(!using_quic_);
  1021. next_state_ = STATE_CREATE_STREAM_COMPLETE;
  1022. if (!using_spdy_) {
  1023. DCHECK(!expect_spdy_);
  1024. bool using_proxy = (proxy_info_.is_http_like()) &&
  1025. request_info_.url.SchemeIs(url::kHttpScheme);
  1026. if (is_websocket_) {
  1027. DCHECK_NE(job_type_, PRECONNECT);
  1028. DCHECK_NE(job_type_, PRECONNECT_DNS_ALPN_H3);
  1029. DCHECK(delegate_->websocket_handshake_stream_create_helper());
  1030. websocket_stream_ =
  1031. delegate_->websocket_handshake_stream_create_helper()
  1032. ->CreateBasicStream(std::move(connection_), using_proxy,
  1033. session_->websocket_endpoint_lock_manager());
  1034. } else {
  1035. if (request_info_.upload_data_stream &&
  1036. !request_info_.upload_data_stream->AllowHTTP1()) {
  1037. return ERR_H2_OR_QUIC_REQUIRED;
  1038. }
  1039. stream_ = std::make_unique<HttpBasicStream>(std::move(connection_),
  1040. using_proxy);
  1041. }
  1042. return OK;
  1043. }
  1044. CHECK(!stream_.get());
  1045. // It is possible that a pushed stream has been opened by a server since last
  1046. // time Job checked above.
  1047. if (!existing_spdy_session_) {
  1048. // WebSocket over HTTP/2 is only allowed to use existing HTTP/2 connections.
  1049. // Therefore |using_spdy_| could not have been set unless a connection had
  1050. // already been found.
  1051. DCHECK(!is_websocket_);
  1052. session_->spdy_session_pool()->push_promise_index()->ClaimPushedStream(
  1053. spdy_session_key_, origin_url_, request_info_, &existing_spdy_session_,
  1054. &pushed_stream_id_);
  1055. // It is also possible that an HTTP/2 connection has been established since
  1056. // last time Job checked above.
  1057. if (!existing_spdy_session_) {
  1058. existing_spdy_session_ =
  1059. session_->spdy_session_pool()->FindAvailableSession(
  1060. spdy_session_key_, enable_ip_based_pooling_,
  1061. /* is_websocket = */ false, net_log_);
  1062. }
  1063. }
  1064. if (existing_spdy_session_) {
  1065. // We picked up an existing session, so we don't need our socket.
  1066. if (connection_->socket())
  1067. connection_->socket()->Disconnect();
  1068. connection_->Reset();
  1069. int set_result =
  1070. SetSpdyHttpStreamOrBidirectionalStreamImpl(existing_spdy_session_);
  1071. existing_spdy_session_.reset();
  1072. return set_result;
  1073. }
  1074. // Close idle sockets in this group, since subsequent requests will go over
  1075. // |spdy_session|.
  1076. if (connection_->socket()->IsConnected())
  1077. connection_->CloseIdleSocketsInGroup("Switching to HTTP2 session");
  1078. base::WeakPtr<SpdySession> spdy_session;
  1079. int rv =
  1080. session_->spdy_session_pool()->CreateAvailableSessionFromSocketHandle(
  1081. spdy_session_key_, std::move(connection_), net_log_, &spdy_session);
  1082. if (rv != OK) {
  1083. return rv;
  1084. }
  1085. url::SchemeHostPort scheme_host_port(
  1086. using_ssl_ ? url::kHttpsScheme : url::kHttpScheme,
  1087. spdy_session_key_.host_port_pair().host(),
  1088. spdy_session_key_.host_port_pair().port());
  1089. HttpServerProperties* http_server_properties =
  1090. session_->http_server_properties();
  1091. if (http_server_properties) {
  1092. http_server_properties->SetSupportsSpdy(scheme_host_port,
  1093. request_info_.network_isolation_key,
  1094. true /* supports_spdy */);
  1095. }
  1096. // Create a SpdyHttpStream or a BidirectionalStreamImpl attached to the
  1097. // session.
  1098. return SetSpdyHttpStreamOrBidirectionalStreamImpl(spdy_session);
  1099. }
  1100. int HttpStreamFactory::Job::DoCreateStreamComplete(int result) {
  1101. if (result < 0)
  1102. return result;
  1103. session_->proxy_resolution_service()->ReportSuccess(proxy_info_);
  1104. next_state_ = STATE_NONE;
  1105. return OK;
  1106. }
  1107. void HttpStreamFactory::Job::OnSpdySessionAvailable(
  1108. base::WeakPtr<SpdySession> spdy_session) {
  1109. DCHECK(spdy_session);
  1110. // No need for the connection any more, since |spdy_session| can be used
  1111. // instead, and there's no benefit from keeping the old ConnectJob in the
  1112. // socket pool.
  1113. if (connection_)
  1114. connection_->ResetAndCloseSocket();
  1115. // Once a connection is initialized, or if there's any out-of-band callback,
  1116. // like proxy auth challenge, the SpdySessionRequest is cancelled.
  1117. DCHECK(next_state_ == STATE_INIT_CONNECTION ||
  1118. next_state_ == STATE_INIT_CONNECTION_COMPLETE);
  1119. // Ignore calls to ResumeInitConnection() from either the timer or the
  1120. // SpdySessionPool.
  1121. init_connection_already_resumed_ = true;
  1122. // If this is a preconnect, nothing left do to.
  1123. if (job_type_ == PRECONNECT) {
  1124. OnPreconnectsComplete(OK);
  1125. return;
  1126. }
  1127. using_spdy_ = true;
  1128. existing_spdy_session_ = spdy_session;
  1129. next_state_ = STATE_CREATE_STREAM;
  1130. // This will synchronously close |connection_|, so no need to worry about it
  1131. // calling back into |this|.
  1132. RunLoop(net::OK);
  1133. }
  1134. int HttpStreamFactory::Job::ReconsiderProxyAfterError(int error) {
  1135. // Check if the error was a proxy failure.
  1136. if (!CanFalloverToNextProxy(proxy_info_.proxy_server(), error, &error))
  1137. return error;
  1138. should_reconsider_proxy_ = true;
  1139. return error;
  1140. }
  1141. void HttpStreamFactory::Job::MaybeCopyConnectionAttemptsFromHandle() {
  1142. if (!connection_)
  1143. return;
  1144. delegate_->AddConnectionAttemptsToRequest(this,
  1145. connection_->connection_attempts());
  1146. }
  1147. HttpStreamFactory::JobFactory::JobFactory() = default;
  1148. HttpStreamFactory::JobFactory::~JobFactory() = default;
  1149. std::unique_ptr<HttpStreamFactory::Job>
  1150. HttpStreamFactory::JobFactory::CreateJob(
  1151. HttpStreamFactory::Job::Delegate* delegate,
  1152. HttpStreamFactory::JobType job_type,
  1153. HttpNetworkSession* session,
  1154. const HttpRequestInfo& request_info,
  1155. RequestPriority priority,
  1156. const ProxyInfo& proxy_info,
  1157. const SSLConfig& server_ssl_config,
  1158. const SSLConfig& proxy_ssl_config,
  1159. url::SchemeHostPort destination,
  1160. GURL origin_url,
  1161. bool is_websocket,
  1162. bool enable_ip_based_pooling,
  1163. NetLog* net_log,
  1164. NextProto alternative_protocol,
  1165. quic::ParsedQuicVersion quic_version) {
  1166. return std::make_unique<HttpStreamFactory::Job>(
  1167. delegate, job_type, session, request_info, priority, proxy_info,
  1168. server_ssl_config, proxy_ssl_config, std::move(destination), origin_url,
  1169. alternative_protocol, quic_version, is_websocket, enable_ip_based_pooling,
  1170. net_log);
  1171. }
  1172. bool HttpStreamFactory::Job::ShouldThrottleConnectForSpdy() const {
  1173. DCHECK(!using_quic_);
  1174. DCHECK(!spdy_session_request_);
  1175. // If the job has previously been throttled, don't throttle it again.
  1176. if (init_connection_already_resumed_)
  1177. return false;
  1178. url::SchemeHostPort scheme_host_port(
  1179. using_ssl_ ? url::kHttpsScheme : url::kHttpScheme,
  1180. spdy_session_key_.host_port_pair().host(),
  1181. spdy_session_key_.host_port_pair().port());
  1182. // Only throttle the request if the server is believed to support H2.
  1183. return session_->http_server_properties()->GetSupportsSpdy(
  1184. scheme_host_port, request_info_.network_isolation_key);
  1185. }
  1186. } // namespace net