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/quic/quic_client_session.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/callback_helpers.h"
8ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/metrics/histogram.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/metrics/sparse_histogram.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h"
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "net/http/transport_security_state.h"
1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "net/quic/crypto/proof_verifier_chromium.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/quic/crypto/quic_server_info.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_connection_helper.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_crypto_client_stream_factory.h"
21e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "net/quic/quic_server_id.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_stream_factory.h"
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "net/spdy/spdy_session.h"
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/ssl/channel_id_service.h"
2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "net/ssl/ssl_connection_status_flags.h"
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/ssl/ssl_info.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/udp/datagram_client_socket.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// The length of time to wait for a 0-RTT handshake to complete
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// before allowing the requests to possibly proceed over TCP.
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const int k0RttHandshakeTimeoutMs = 300;
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Histograms for tracking down the crashes from http://crbug.com/354669
38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Note: these values must be kept in sync with the corresponding values in:
39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// tools/metrics/histograms/histograms.xml
40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochenum Location {
41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DESTRUCTOR = 0,
42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ADD_OBSERVER = 1,
43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  TRY_CREATE_STREAM = 2,
44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  CREATE_OUTGOING_RELIABLE_STREAM = 3,
45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER = 4,
46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  NOTIFY_FACTORY_OF_SESSION_CLOSED = 5,
47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  NUM_LOCATIONS = 6,
48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch};
49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid RecordUnexpectedOpenStreams(Location location) {
51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.UnexpectedOpenStreams", location,
52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            NUM_LOCATIONS);
53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid RecordUnexpectedObservers(Location location) {
56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.UnexpectedObservers", location,
57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            NUM_LOCATIONS);
58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid RecordUnexpectedNotGoingAway(Location location) {
61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.UnexpectedNotGoingAway", location,
62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            NUM_LOCATIONS);
63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Histogram for recording the different reasons that a QUIC session is unable
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// to complete the handshake.
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)enum HandshakeFailureReason {
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  HANDSHAKE_FAILURE_UNKNOWN = 0,
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  HANDSHAKE_FAILURE_BLACK_HOLE = 1,
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  HANDSHAKE_FAILURE_PUBLIC_RESET = 2,
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NUM_HANDSHAKE_FAILURE_REASONS = 3,
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RecordHandshakeFailureReason(HandshakeFailureReason reason) {
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "Net.QuicSession.ConnectionClose.HandshakeNotConfirmed.Reason",
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      reason, NUM_HANDSHAKE_FAILURE_REASONS);
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Note: these values must be kept in sync with the corresponding values in:
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// tools/metrics/histograms/histograms.xml
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)enum HandshakeState {
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  STATE_STARTED = 0,
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  STATE_ENCRYPTION_ESTABLISHED = 1,
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  STATE_HANDSHAKE_CONFIRMED = 2,
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  STATE_FAILED = 3,
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NUM_HANDSHAKE_STATES = 4
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void RecordHandshakeState(HandshakeState state) {
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("Net.QuicHandshakeState", state,
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            NUM_HANDSHAKE_STATES);
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)QuicClientSession::StreamRequest::StreamRequest() : stream_(NULL) {}
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)QuicClientSession::StreamRequest::~StreamRequest() {
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  CancelRequest();
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int QuicClientSession::StreamRequest::StartRequest(
1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const base::WeakPtr<QuicClientSession>& session,
105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    QuicReliableClientStream** stream,
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const CompletionCallback& callback) {
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  session_ = session;
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  stream_ = stream;
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int rv = session_->TryCreateStream(this, stream_);
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    callback_ = callback;
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return rv;
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void QuicClientSession::StreamRequest::CancelRequest() {
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (session_)
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    session_->CancelRequest(this);
120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  session_.reset();
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  callback_.Reset();
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void QuicClientSession::StreamRequest::OnRequestCompleteSuccess(
125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    QuicReliableClientStream* stream) {
126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  session_.reset();
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  *stream_ = stream;
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ResetAndReturn(&callback_).Run(OK);
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void QuicClientSession::StreamRequest::OnRequestCompleteFailure(int rv) {
132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  session_.reset();
133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ResetAndReturn(&callback_).Run(rv);
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)QuicClientSession::QuicClientSession(
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    QuicConnection* connection,
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<DatagramClientSocket> socket,
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    QuicStreamFactory* stream_factory,
14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    TransportSecurityState* transport_security_state,
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<QuicServerInfo> server_info,
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const QuicConfig& config,
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::TaskRunner* task_runner,
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NetLog* net_log)
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : QuicClientSessionBase(connection, config),
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      require_confirmation_(false),
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream_factory_(stream_factory),
1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      socket_(socket.Pass()),
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      read_buffer_(new IOBufferWithSize(kMaxPacketSize)),
15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      transport_security_state_(transport_security_state),
15123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      server_info_(server_info.Pass()),
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      read_pending_(false),
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      num_total_streams_(0),
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      task_runner_(task_runner),
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_QUIC_SESSION)),
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      logger_(new QuicConnectionLogger(net_log_)),
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      num_packets_read_(0),
158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      going_away_(false),
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      weak_factory_(this) {
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  connection->set_debug_visitor(logger_);
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid QuicClientSession::InitializeSession(
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const QuicServerId& server_id,
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    QuicCryptoClientConfig* crypto_config,
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    QuicCryptoClientStreamFactory* crypto_client_stream_factory) {
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  server_host_port_ = server_id.host_port_pair();
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  crypto_stream_.reset(
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      crypto_client_stream_factory ?
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          crypto_client_stream_factory->CreateQuicCryptoClientStream(
171e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              server_id, this, crypto_config) :
172e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          new QuicCryptoClientStream(server_id, this,
173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                     new ProofVerifyContextChromium(net_log_),
174effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                     crypto_config));
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  QuicClientSessionBase::InitializeSession();
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(rch): pass in full host port proxy pair
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net_log_.BeginEvent(
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NetLog::TYPE_QUIC_SESSION,
179e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      NetLog::StringCallback("host", &server_id.host()));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicClientSession::~QuicClientSession() {
183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!streams()->empty())
184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    RecordUnexpectedOpenStreams(DESTRUCTOR);
185effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!observers_.empty())
186effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    RecordUnexpectedObservers(DESTRUCTOR);
187effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!going_away_)
188effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    RecordUnexpectedNotGoingAway(DESTRUCTOR);
189effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
190e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  while (!streams()->empty() ||
191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch         !observers_.empty() ||
192e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch         !stream_requests_.empty()) {
193e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // The session must be closed before it is destroyed.
194e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(streams()->empty());
195e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    CloseAllStreams(ERR_UNEXPECTED);
196e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(observers_.empty());
197e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    CloseAllObservers(ERR_UNEXPECTED);
198e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
199e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    connection()->set_debug_visitor(NULL);
200e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    net_log_.EndEvent(NetLog::TYPE_QUIC_SESSION);
201e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
202e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    while (!stream_requests_.empty()) {
203e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      StreamRequest* request = stream_requests_.front();
204e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      stream_requests_.pop_front();
205e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      request->OnRequestCompleteFailure(ERR_ABORTED);
206e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (connection()->connected()) {
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Ensure that the connection is closed by the time the session is
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // destroyed.
212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    connection()->CloseConnection(QUIC_INTERNAL_ERROR, false);
213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsEncryptionEstablished())
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RecordHandshakeState(STATE_ENCRYPTION_ESTABLISHED);
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsCryptoHandshakeConfirmed())
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RecordHandshakeState(STATE_HANDSHAKE_CONFIRMED);
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  else
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RecordHandshakeState(STATE_FAILED);
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("Net.QuicSession.NumTotalStreams", num_total_streams_);
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("Net.QuicNumSentClientHellos",
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       crypto_stream_->num_sent_client_hellos());
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!IsCryptoHandshakeConfirmed())
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Sending one client_hello means we had zero handshake-round-trips.
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int round_trip_handshakes = crypto_stream_->num_sent_client_hellos() - 1;
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Don't bother with these histogram during tests, which mock out
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // num_sent_client_hellos().
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (round_trip_handshakes < 0 || !stream_factory_)
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool port_selected = stream_factory_->enable_port_selection();
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SSLInfo ssl_info;
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!GetSSLInfo(&ssl_info) || !ssl_info.cert.get()) {
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (port_selected) {
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectSelectPortForHTTP",
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  round_trip_handshakes, 0, 3, 4);
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectRandomPortForHTTP",
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  round_trip_handshakes, 0, 3, 4);
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (require_confirmation_) {
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        UMA_HISTOGRAM_CUSTOM_COUNTS(
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "Net.QuicSession.ConnectRandomPortRequiringConfirmationForHTTP",
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            round_trip_handshakes, 0, 3, 4);
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (port_selected) {
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectSelectPortForHTTPS",
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  round_trip_handshakes, 0, 3, 4);
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectRandomPortForHTTPS",
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  round_trip_handshakes, 0, 3, 4);
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (require_confirmation_) {
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        UMA_HISTOGRAM_CUSTOM_COUNTS(
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            "Net.QuicSession.ConnectRandomPortRequiringConfirmationForHTTPS",
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            round_trip_handshakes, 0, 3, 4);
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const QuicConnectionStats stats = connection()->GetStats();
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (stats.max_sequence_reordering == 0)
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const uint64 kMaxReordering = 100;
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  uint64 reordering = kMaxReordering;
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (stats.min_rtt_us > 0 ) {
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    reordering =
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        GG_UINT64_C(100) * stats.max_time_reordering_us / stats.min_rtt_us;
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.MaxReorderingTime",
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                reordering, 0, kMaxReordering, 50);
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (stats.min_rtt_us > 100 * 1000) {
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.MaxReorderingTimeLongRtt",
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                reordering, 0, kMaxReordering, 50);
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("Net.QuicSession.MaxReordering",
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       stats.max_sequence_reordering);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid QuicClientSession::OnStreamFrames(
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::vector<QuicStreamFrame>& frames) {
28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Record total number of stream frames.
28768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("Net.QuicNumStreamFramesInPacket", frames.size());
28868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
28968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Record number of frames per stream in packet.
29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  typedef std::map<QuicStreamId, size_t> FrameCounter;
29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FrameCounter frames_per_stream;
29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
29368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    frames_per_stream[frames[i].stream_id]++;
29468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
29568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (FrameCounter::const_iterator it = frames_per_stream.begin();
29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       it != frames_per_stream.end(); ++it) {
29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS("Net.QuicNumStreamFramesPerStreamInPacket",
29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                         it->second);
29968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
30168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return QuicSession::OnStreamFrames(frames);
30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
30368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void QuicClientSession::AddObserver(Observer* observer) {
305e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (going_away_) {
306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    RecordUnexpectedObservers(ADD_OBSERVER);
307e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    observer->OnSessionClosed(ERR_UNEXPECTED);
308e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return;
309e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(!ContainsKey(observers_, observer));
3128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  observers_.insert(observer);
3138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void QuicClientSession::RemoveObserver(Observer* observer) {
3168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(ContainsKey(observers_, observer));
3178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  observers_.erase(observer);
3188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int QuicClientSession::TryCreateStream(StreamRequest* request,
321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                       QuicReliableClientStream** stream) {
322a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!crypto_stream_->encryption_established()) {
323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    DLOG(DFATAL) << "Encryption not established.";
324a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return ERR_CONNECTION_CLOSED;
325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (goaway_received()) {
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << "Going away.";
329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return ERR_CONNECTION_CLOSED;
330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!connection()->connected()) {
333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << "Already closed.";
334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return ERR_CONNECTION_CLOSED;
335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (going_away_) {
338effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    RecordUnexpectedOpenStreams(TRY_CREATE_STREAM);
339effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return ERR_CONNECTION_CLOSED;
340effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
341effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (GetNumOpenStreams() < get_max_open_streams()) {
343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *stream = CreateOutgoingReliableStreamImpl();
344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return OK;
345a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  stream_requests_.push_back(request);
348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return ERR_IO_PENDING;
349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void QuicClientSession::CancelRequest(StreamRequest* request) {
352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Remove |request| from the queue while preserving the order of the
353a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // other elements.
354a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StreamRequestQueue::iterator it =
355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      std::find(stream_requests_.begin(), stream_requests_.end(), request);
356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (it != stream_requests_.end()) {
357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    it = stream_requests_.erase(it);
358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicReliableClientStream* QuicClientSession::CreateOutgoingDataStream() {
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!crypto_stream_->encryption_established()) {
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << "Encryption not active so no outgoing stream created.";
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetNumOpenStreams() >= get_max_open_streams()) {
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << "Failed to create a new outgoing stream. "
368e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch             << "Already " << GetNumOpenStreams() << " open.";
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (goaway_received()) {
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << "Failed to create a new outgoing stream. "
373e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch             << "Already received goaway.";
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
376effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (going_away_) {
377effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    RecordUnexpectedOpenStreams(CREATE_OUTGOING_RELIABLE_STREAM);
378effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return NULL;
379effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return CreateOutgoingReliableStreamImpl();
381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
382a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
383a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)QuicReliableClientStream*
384a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)QuicClientSession::CreateOutgoingReliableStreamImpl() {
385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(connection()->connected());
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicReliableClientStream* stream =
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new QuicReliableClientStream(GetNextStreamId(), this, net_log_);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActivateStream(stream);
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ++num_total_streams_;
3908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  UMA_HISTOGRAM_COUNTS("Net.QuicSession.NumOpenStreams", GetNumOpenStreams());
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return stream;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicCryptoClientStream* QuicClientSession::GetCryptoStream() {
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return crypto_stream_.get();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// TODO(rtenneti): Add unittests for GetSSLInfo which exercise the various ways
39923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// we learn about SSL info (sync vs async vs cached).
40023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool QuicClientSession::GetSSLInfo(SSLInfo* ssl_info) const {
40123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ssl_info->Reset();
40223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!cert_verify_result_) {
40323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
40423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
40523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
40623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ssl_info->cert_status = cert_verify_result_->cert_status;
40723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ssl_info->cert = cert_verify_result_->verified_cert;
40823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
409c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // TODO(wtc): Define QUIC "cipher suites".
410c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Report the TLS cipher suite that most closely resembles the crypto
411c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // parameters of the QUIC connection.
412c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  QuicTag aead = crypto_stream_->crypto_negotiated_params().aead;
413c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int cipher_suite;
414c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int security_bits;
415c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  switch (aead) {
416c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case kAESG:
417c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      cipher_suite = 0xc02f;  // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
418c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      security_bits = 128;
419c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
420c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case kCC12:
421c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      cipher_suite = 0xcc13;  // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
422c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      security_bits = 256;
423c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
424c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    default:
425c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      NOTREACHED();
426c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return false;
427c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
42823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int ssl_connection_status = 0;
42923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ssl_connection_status |=
43023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      (cipher_suite & SSL_CONNECTION_CIPHERSUITE_MASK) <<
43123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)       SSL_CONNECTION_CIPHERSUITE_SHIFT;
43223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ssl_connection_status |=
433c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      (SSL_CONNECTION_VERSION_QUIC & SSL_CONNECTION_VERSION_MASK) <<
43423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)       SSL_CONNECTION_VERSION_SHIFT;
43523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
43623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ssl_info->public_key_hashes = cert_verify_result_->public_key_hashes;
43723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ssl_info->is_issued_by_known_root =
43823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      cert_verify_result_->is_issued_by_known_root;
43923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
44023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ssl_info->connection_status = ssl_connection_status;
44123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ssl_info->client_cert_sent = false;
442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ssl_info->channel_id_sent = crypto_stream_->WasChannelIDSent();
443c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ssl_info->security_bits = security_bits;
44423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ssl_info->handshake_type = SSLInfo::HANDSHAKE_FULL;
4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ssl_info->pinning_failure_log = pinning_failure_log_;
44623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return true;
4477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
4487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int QuicClientSession::CryptoConnect(bool require_confirmation,
4503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     const CompletionCallback& callback) {
4513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  require_confirmation_ = require_confirmation;
452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  handshake_start_ = base::TimeTicks::Now();
453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RecordHandshakeState(STATE_STARTED);
454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(flow_controller());
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!crypto_stream_->CryptoConnect()) {
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(wtc): change crypto_stream_.CryptoConnect() to return a
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // QuicErrorCode and map it to a net error code.
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ERR_CONNECTION_FAILED;
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
46146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsCryptoHandshakeConfirmed())
46246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return OK;
46346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
46446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Unless we require handshake confirmation, activate the session if
46546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // we have established initial encryption.
46646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!require_confirmation_ && IsEncryptionEstablished()) {
46746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // To mitigate the effects of hanging 0-RTT connections, set up a timer to
46846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // cancel any requests, if the handshake takes too long.
46946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    task_runner_->PostDelayedTask(
47046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        FROM_HERE,
47146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::Bind(&QuicClientSession::OnConnectTimeout,
47246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   weak_factory_.GetWeakPtr()),
47346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(k0RttHandshakeTimeoutMs));
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return OK;
47546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_ = callback;
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ERR_IO_PENDING;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int QuicClientSession::ResumeCryptoConnect(const CompletionCallback& callback) {
48346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
48446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsCryptoHandshakeConfirmed())
48546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return OK;
48646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
48746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!connection()->connected())
48846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return ERR_QUIC_HANDSHAKE_FAILED;
48946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
49046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  callback_ = callback;
49146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return ERR_IO_PENDING;
49246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
49346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
49458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int QuicClientSession::GetNumSentClientHellos() const {
49558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return crypto_stream_->num_sent_client_hellos();
49658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
49758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicClientSession::CanPool(const std::string& hostname) const {
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(connection()->connected());
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SSLInfo ssl_info;
5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!GetSSLInfo(&ssl_info) || !ssl_info.cert.get()) {
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // We can always pool with insecure QUIC sessions.
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
505116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
50603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return SpdySession::CanPool(transport_security_state_, ssl_info,
50703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                              server_host_port_.host(), hostname);
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicClientSession::CreateIncomingDataStream(
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuicStreamId id) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DLOG(ERROR) << "Server push not supported";
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicClientSession::CloseStream(QuicStreamId stream_id) {
517c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ReliableQuicStream* stream = GetStream(stream_id);
518c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (stream) {
5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    logger_->UpdateReceivedFrameCounts(
520c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        stream_id, stream->num_frames_received(),
521c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        stream->num_duplicate_frames_received());
522c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicSession::CloseStream(stream_id);
524424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  OnClosedStream();
525424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
526424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
527424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void QuicClientSession::SendRstStream(QuicStreamId id,
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      QuicRstStreamErrorCode error,
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      QuicStreamOffset bytes_written) {
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicSession::SendRstStream(id, error, bytes_written);
531424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  OnClosedStream();
532424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
534424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void QuicClientSession::OnClosedStream() {
535a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (GetNumOpenStreams() < get_max_open_streams() &&
536a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      !stream_requests_.empty() &&
537a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      crypto_stream_->encryption_established() &&
538a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      !goaway_received() &&
539effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      !going_away_ &&
540a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      connection()->connected()) {
541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    StreamRequest* request = stream_requests_.front();
542a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    stream_requests_.pop_front();
543a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    request->OnRequestCompleteSuccess(CreateOutgoingReliableStreamImpl());
544a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
545a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (GetNumOpenStreams() == 0) {
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    stream_factory_->OnIdleSession(this);
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicClientSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
5523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!callback_.is_null() &&
5533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      (!require_confirmation_ || event == HANDSHAKE_CONFIRMED)) {
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // TODO(rtenneti): Currently for all CryptoHandshakeEvent events, callback_
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // could be called because there are no error events in CryptoHandshakeEvent
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // enum. If error events are added to CryptoHandshakeEvent, then the
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // following code needs to changed.
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::ResetAndReturn(&callback_).Run(OK);
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
5608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (event == HANDSHAKE_CONFIRMED) {
561f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    UMA_HISTOGRAM_TIMES("Net.QuicSession.HandshakeConfirmedTime",
562f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        base::TimeTicks::Now() - handshake_start_);
5638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ObserverSet::iterator it = observers_.begin();
5648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    while (it != observers_.end()) {
5658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      Observer* observer = *it;
5668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ++it;
5678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      observer->OnCryptoHandshakeConfirmed();
5688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
570ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  QuicSession::OnCryptoHandshakeEvent(event);
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicClientSession::OnCryptoHandshakeMessageSent(
5743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const CryptoHandshakeMessage& message) {
5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  logger_->OnCryptoHandshakeMessageSent(message);
5763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicClientSession::OnCryptoHandshakeMessageReceived(
5793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const CryptoHandshakeMessage& message) {
5805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  logger_->OnCryptoHandshakeMessageReceived(message);
5813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void QuicClientSession::OnConnectionClosed(QuicErrorCode error,
5841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                           bool from_peer) {
5854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!connection()->connected());
5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  logger_->OnConnectionClosed(error, from_peer);
5873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (from_peer) {
5883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    UMA_HISTOGRAM_SPARSE_SLOWLY(
5893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        "Net.QuicSession.ConnectionCloseErrorCodeServer", error);
5903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else {
5913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    UMA_HISTOGRAM_SPARSE_SLOWLY(
5923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        "Net.QuicSession.ConnectionCloseErrorCodeClient", error);
5933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
594424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
595424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (error == QUIC_CONNECTION_TIMED_OUT) {
5961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS(
597424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        "Net.QuicSession.ConnectionClose.NumOpenStreams.TimedOut",
598424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        GetNumOpenStreams());
59903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (IsCryptoHandshakeConfirmed()) {
60003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      if (GetNumOpenStreams() > 0) {
60103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        UMA_HISTOGRAM_BOOLEAN(
60203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            "Net.QuicSession.TimedOutWithOpenStreams.HasUnackedPackets",
60303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            connection()->sent_packet_manager().HasUnackedPackets());
60403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        UMA_HISTOGRAM_COUNTS(
60503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            "Net.QuicSession.TimedOutWithOpenStreams.ConsecutiveRTOCount",
60603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            connection()->sent_packet_manager().consecutive_rto_count());
60703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        UMA_HISTOGRAM_COUNTS(
60803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            "Net.QuicSession.TimedOutWithOpenStreams.ConsecutiveTLPCount",
60903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            connection()->sent_packet_manager().consecutive_tlp_count());
61003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      }
61103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } else {
612f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      UMA_HISTOGRAM_COUNTS(
613f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "Net.QuicSession.ConnectionClose.NumOpenStreams.HandshakeTimedOut",
614f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          GetNumOpenStreams());
6151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      UMA_HISTOGRAM_COUNTS(
6161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          "Net.QuicSession.ConnectionClose.NumTotalStreams.HandshakeTimedOut",
6171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          num_total_streams_);
6181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
619424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
620424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
621cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!IsCryptoHandshakeConfirmed()) {
622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (error == QUIC_PUBLIC_RESET) {
623cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      RecordHandshakeFailureReason(HANDSHAKE_FAILURE_PUBLIC_RESET);
624cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else if (connection()->GetStats().packets_received == 0) {
625cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      RecordHandshakeFailureReason(HANDSHAKE_FAILURE_BLACK_HOLE);
626cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      UMA_HISTOGRAM_SPARSE_SLOWLY(
627cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          "Net.QuicSession.ConnectionClose.HandshakeFailureBlackHole.QuicError",
628cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          error);
629cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
630cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      RecordHandshakeFailureReason(HANDSHAKE_FAILURE_UNKNOWN);
631cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      UMA_HISTOGRAM_SPARSE_SLOWLY(
632cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          "Net.QuicSession.ConnectionClose.HandshakeFailureUnknown.QuicError",
633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          error);
634cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
636cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
637ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.QuicVersion",
638ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                              connection()->version());
6398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  NotifyFactoryOfSessionGoingAway();
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!callback_.is_null()) {
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::ResetAndReturn(&callback_).Run(ERR_QUIC_PROTOCOL_ERROR);
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  socket_->Close();
6441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  QuicSession::OnConnectionClosed(error, from_peer);
645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(streams()->empty());
646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CloseAllStreams(ERR_UNEXPECTED);
647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CloseAllObservers(ERR_UNEXPECTED);
6488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  NotifyFactoryOfSessionClosedLater();
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
651d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void QuicClientSession::OnSuccessfulVersionNegotiation(
652d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const QuicVersion& version) {
6535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  logger_->OnSuccessfulVersionNegotiation(version);
654d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  QuicSession::OnSuccessfulVersionNegotiation(version);
655d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
656d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
65723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void QuicClientSession::OnProofValid(
65823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const QuicCryptoClientConfig::CachedState& cached) {
65923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(cached.proof_valid());
66023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
66123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!server_info_ || !server_info_->IsReadyToPersist()) {
66223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
66323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
66423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
66523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  QuicServerInfo::State* state = server_info_->mutable_state();
66623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
66723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  state->server_config = cached.server_config();
66823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  state->source_address_token = cached.source_address_token();
66923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  state->server_config_sig = cached.signature();
67023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  state->certs = cached.certs();
67123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
67223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  server_info_->Persist();
67323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
67423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
67523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void QuicClientSession::OnProofVerifyDetailsAvailable(
67623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const ProofVerifyDetails& verify_details) {
6775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const ProofVerifyDetailsChromium* verify_details_chromium =
6785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      reinterpret_cast<const ProofVerifyDetailsChromium*>(&verify_details);
67923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  CertVerifyResult* result_copy = new CertVerifyResult;
6805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  result_copy->CopyFrom(verify_details_chromium->cert_verify_result);
68123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  cert_verify_result_.reset(result_copy);
6825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  pinning_failure_log_ = verify_details_chromium->pinning_failure_log;
6835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  logger_->OnCertificateVerified(*cert_verify_result_);
68423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
68523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicClientSession::StartReading() {
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (read_pending_) {
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_pending_ = true;
691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int rv = socket_->Read(read_buffer_.get(),
692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         read_buffer_->size(),
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         base::Bind(&QuicClientSession::OnReadComplete,
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    weak_factory_.GetWeakPtr()));
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv == ERR_IO_PENDING) {
6961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    num_packets_read_ = 0;
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (++num_packets_read_ > 32) {
7011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    num_packets_read_ = 0;
7021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Data was read, process it.
703f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Schedule the work through the message loop to 1) prevent infinite
704f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // recursion and 2) avoid blocking the thread for too long.
7051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::MessageLoop::current()->PostTask(
7061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        FROM_HERE,
7071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        base::Bind(&QuicClientSession::OnReadComplete,
7081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                   weak_factory_.GetWeakPtr(), rv));
7091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else {
7101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OnReadComplete(rv);
7111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicClientSession::CloseSessionOnError(int error) {
715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.CloseSessionOnError", -error);
71658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CloseSessionOnErrorInner(error, QUIC_INTERNAL_ERROR);
7178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  NotifyFactoryOfSessionClosed();
718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
72058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void QuicClientSession::CloseSessionOnErrorInner(int net_error,
72158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                                 QuicErrorCode quic_error) {
722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!callback_.is_null()) {
72358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    base::ResetAndReturn(&callback_).Run(net_error);
724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
7258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  CloseAllStreams(net_error);
7268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  CloseAllObservers(net_error);
7278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  net_log_.AddEvent(
7288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      NetLog::TYPE_QUIC_SESSION_CLOSE_ON_ERROR,
7298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      NetLog::IntegerCallback("net_error", net_error));
7308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (connection()->connected())
732cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    connection()->CloseConnection(quic_error, false);
7338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(!connection()->connected());
7348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void QuicClientSession::CloseAllStreams(int net_error) {
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!streams()->empty()) {
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ReliableQuicStream* stream = streams()->begin()->second;
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    QuicStreamId id = stream->id();
74058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    static_cast<QuicReliableClientStream*>(stream)->OnError(net_error);
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CloseStream(id);
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
744a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
7458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void QuicClientSession::CloseAllObservers(int net_error) {
7468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  while (!observers_.empty()) {
7478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    Observer* observer = *observers_.begin();
7488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    observers_.erase(observer);
7498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    observer->OnSessionClosed(net_error);
7508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::Value* QuicClientSession::GetInfoAsValue(
754cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::set<HostPortPair>& aliases) {
7557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
756ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  dict->SetString("version", QuicVersionToString(connection()->version()));
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetInteger("open_streams", GetNumOpenStreams());
758cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::ListValue* stream_list = new base::ListValue();
759cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (base::hash_map<QuicStreamId, QuicDataStream*>::const_iterator it
760cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)           = streams()->begin();
761cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       it != streams()->end();
762cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       ++it) {
763cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    stream_list->Append(new base::StringValue(
764cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Uint64ToString(it->second->id())));
765cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
766cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  dict->Set("active_streams", stream_list);
767cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetInteger("total_streams", num_total_streams_);
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetString("peer_address", peer_address().ToString());
770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  dict->SetString("connection_id", base::Uint64ToString(connection_id()));
7711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  dict->SetBoolean("connected", connection()->connected());
772cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const QuicConnectionStats& stats = connection()->GetStats();
773cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  dict->SetInteger("packets_sent", stats.packets_sent);
774cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  dict->SetInteger("packets_received", stats.packets_received);
775cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  dict->SetInteger("packets_lost", stats.packets_lost);
776a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SSLInfo ssl_info;
7771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  dict->SetBoolean("secure", GetSSLInfo(&ssl_info) && ssl_info.cert.get());
7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* alias_list = new base::ListValue();
780a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (std::set<HostPortPair>::const_iterator it = aliases.begin();
7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != aliases.end(); it++) {
782a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    alias_list->Append(new base::StringValue(it->ToString()));
7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dict->Set("aliases", alias_list);
7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dict;
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
789a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)base::WeakPtr<QuicClientSession> QuicClientSession::GetWeakPtr() {
790a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return weak_factory_.GetWeakPtr();
791a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
792a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicClientSession::OnReadComplete(int result) {
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_pending_ = false;
795b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (result == 0)
796b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    result = ERR_CONNECTION_CLOSED;
797b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
798b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (result < 0) {
799f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << "Closing session on read error: " << result;
80058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.ReadError", -result);
8018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    NotifyFactoryOfSessionGoingAway();
80258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    CloseSessionOnErrorInner(result, QUIC_PACKET_READ_ERROR);
8038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    NotifyFactoryOfSessionClosedLater();
804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
807f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  QuicEncryptedPacket packet(read_buffer_->data(), result);
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPEndPoint local_address;
809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPEndPoint peer_address;
810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  socket_->GetLocalAddress(&local_address);
811c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  socket_->GetPeerAddress(&peer_address);
812c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // ProcessUdpPacket might result in |this| being deleted, so we
813c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // use a weak pointer to be safe.
814c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  connection()->ProcessUdpPacket(local_address, peer_address, packet);
815c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!connection()->connected()) {
8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    NotifyFactoryOfSessionClosedLater();
817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartReading();
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void QuicClientSession::NotifyFactoryOfSessionGoingAway() {
823effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  going_away_ = true;
8248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (stream_factory_)
8258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    stream_factory_->OnSessionGoingAway(this);
8268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
8278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void QuicClientSession::NotifyFactoryOfSessionClosedLater() {
829effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!streams()->empty())
830effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    RecordUnexpectedOpenStreams(NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER);
831effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
832effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!going_away_)
833effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    RecordUnexpectedNotGoingAway(NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER);
834effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
835effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  going_away_ = true;
836a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK_EQ(0u, GetNumOpenStreams());
837a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(!connection()->connected());
838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->PostTask(
839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      FROM_HERE,
8408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Bind(&QuicClientSession::NotifyFactoryOfSessionClosed,
841eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 weak_factory_.GetWeakPtr()));
842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
8448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void QuicClientSession::NotifyFactoryOfSessionClosed() {
845effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!streams()->empty())
846effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    RecordUnexpectedOpenStreams(NOTIFY_FACTORY_OF_SESSION_CLOSED);
847effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
848effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!going_away_)
849effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    RecordUnexpectedNotGoingAway(NOTIFY_FACTORY_OF_SESSION_CLOSED);
850effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
851effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  going_away_ = true;
852a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK_EQ(0u, GetNumOpenStreams());
853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Will delete |this|.
8548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (stream_factory_)
8558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    stream_factory_->OnSessionClosed(this);
856eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
857eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
85846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void QuicClientSession::OnConnectTimeout() {
85946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(callback_.is_null());
86046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(IsEncryptionEstablished());
86146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
86246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsCryptoHandshakeConfirmed())
86346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
86446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
8656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // TODO(rch): re-enable this code once beta is cut.
8666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  //  if (stream_factory_)
8676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  //    stream_factory_->OnSessionConnectTimeout(this);
8686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  //  CloseAllStreams(ERR_QUIC_HANDSHAKE_FAILED);
8696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  //  DCHECK_EQ(0u, GetNumOpenStreams());
87046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
87146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
873