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_session.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/quic/crypto/proof_verifier.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_connection.h"
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/quic/quic_flags.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/quic/quic_flow_controller.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_headers_stream.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/ssl/ssl_info.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::hash_map;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::hash_set;
182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochusing std::make_pair;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define ENDPOINT (is_server() ? "Server: " : " Client: ")
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// We want to make sure we delete any closed streams in a safe manner.
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// To avoid deleting a stream in mid-operation, we have a simple shim between
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// us and the stream, so we can delete any streams when we return from
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// processing.
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// We could just override the base methods, but this makes it easier to make
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// sure we don't miss any.
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class VisitorShim : public QuicConnectionVisitorInterface {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit VisitorShim(QuicSession* session) : session_(session) {}
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual void OnStreamFrames(const vector<QuicStreamFrame>& frames) OVERRIDE {
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    session_->OnStreamFrames(frames);
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->PostProcessAfterData();
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnRstStream(const QuicRstStreamFrame& frame) OVERRIDE {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->OnRstStream(frame);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->PostProcessAfterData();
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnGoAway(const QuicGoAwayFrame& frame) OVERRIDE {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->OnGoAway(frame);
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->PostProcessAfterData();
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnWindowUpdateFrames(const vector<QuicWindowUpdateFrame>& frames)
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OVERRIDE {
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    session_->OnWindowUpdateFrames(frames);
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    session_->PostProcessAfterData();
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnBlockedFrames(const vector<QuicBlockedFrame>& frames)
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OVERRIDE {
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    session_->OnBlockedFrames(frames);
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    session_->PostProcessAfterData();
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnCanWrite() OVERRIDE {
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    session_->OnCanWrite();
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->PostProcessAfterData();
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  virtual void OnCongestionWindowChange(QuicTime now) OVERRIDE {
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    session_->OnCongestionWindowChange(now);
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void OnSuccessfulVersionNegotiation(
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const QuicVersion& version) OVERRIDE {
73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    session_->OnSuccessfulVersionNegotiation(version);
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnConnectionClosed(
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      QuicErrorCode error, bool from_peer) OVERRIDE {
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    session_->OnConnectionClosed(error, from_peer);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The session will go away, so don't bother with cleanup.
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnWriteBlocked() OVERRIDE {
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    session_->OnWriteBlocked();
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual bool WillingAndAbleToWrite() const OVERRIDE {
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return session_->WillingAndAbleToWrite();
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual bool HasPendingHandshake() const OVERRIDE {
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return session_->HasPendingHandshake();
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual bool HasOpenDataStreams() const OVERRIDE {
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return session_->HasOpenDataStreams();
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicSession* session_;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : connection_(connection),
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      visitor_shim_(new VisitorShim(this)),
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      config_(config),
106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      max_open_streams_(config_.max_streams_per_connection()),
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      next_stream_id_(is_server() ? 2 : 5),
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      largest_peer_created_stream_id_(0),
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      error_(QUIC_NO_ERROR),
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      goaway_received_(false),
111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      goaway_sent_(false),
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      has_pending_handshake_(false) {
1136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (connection_->version() <= QUIC_VERSION_19) {
1146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    flow_controller_.reset(new QuicFlowController(
1156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        connection_.get(), 0, is_server(), kDefaultFlowControlSendWindow,
1166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.GetInitialFlowControlWindowToSend(),
1176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.GetInitialFlowControlWindowToSend()));
1186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  } else {
1196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    flow_controller_.reset(new QuicFlowController(
1206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        connection_.get(), 0, is_server(), kDefaultFlowControlSendWindow,
1216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.GetInitialSessionFlowControlWindowToSend(),
1226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.GetInitialSessionFlowControlWindowToSend()));
1236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void QuicSession::InitializeSession() {
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  connection_->set_visitor(visitor_shim_.get());
1280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  connection_->SetFromConfig(config_);
129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (connection_->connected()) {
130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    connection_->SetOverallConnectionTimeout(
131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        config_.max_time_before_crypto_handshake());
132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  headers_stream_.reset(new QuicHeadersStream(this));
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicSession::~QuicSession() {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteElements(&closed_streams_);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteValues(&stream_map_);
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DLOG_IF(WARNING,
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          locally_closed_streams_highest_offset_.size() > max_open_streams_)
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "Surprisingly high number of locally closed streams still waiting for "
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)         "final byte offset: " << locally_closed_streams_highest_offset_.size();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid QuicSession::OnStreamFrames(const vector<QuicStreamFrame>& frames) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // TODO(rch) deal with the error case of stream id 0.
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const QuicStreamFrame& frame = frames[i];
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicStreamId stream_id = frame.stream_id;
151424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ReliableQuicStream* stream = GetStream(stream_id);
152424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!stream) {
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // The stream no longer exists, but we may still be interested in the
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // final stream byte offset sent by the peer. A frame with a FIN can give
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // us this offset.
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (frame.fin) {
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        QuicStreamOffset final_byte_offset =
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            frame.offset + frame.data.TotalBufferSize();
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        UpdateFlowControlOnFinalReceivedByteOffset(stream_id,
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                   final_byte_offset);
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      continue;
164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    stream->OnStreamFrame(frames[i]);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeaders(QuicStreamId stream_id,
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  StringPiece headers_data) {
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(stream_id);
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!stream) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // It's quite possible to receive headers after a stream has been reset.
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamHeaders(headers_data);
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeadersPriority(QuicStreamId stream_id,
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          QuicPriority priority) {
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(stream_id);
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!stream) {
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // It's quite possible to receive headers after a stream has been reset.
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamHeadersPriority(priority);
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeadersComplete(QuicStreamId stream_id,
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          bool fin,
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          size_t frame_len) {
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(stream_id);
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!stream) {
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // It's quite possible to receive headers after a stream has been reset.
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamHeadersComplete(fin, frame_len);
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (frame.stream_id == kCryptoStreamId) {
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection()->SendConnectionCloseWithDetails(
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        QUIC_INVALID_STREAM_ID,
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "Attempt to reset the crypto stream");
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (frame.stream_id == kHeadersStreamId) {
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection()->SendConnectionCloseWithDetails(
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        QUIC_INVALID_STREAM_ID,
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "Attempt to reset the headers stream");
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(frame.stream_id);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!stream) {
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // The RST frame contains the final byte offset for the stream: we can now
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // update the connection level flow controller if needed.
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    UpdateFlowControlOnFinalReceivedByteOffset(frame.stream_id,
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                               frame.byte_offset);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Errors are handled by GetStream.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamReset(frame);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) {
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(frame.last_good_stream_id < next_stream_id_);
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  goaway_received_ = true;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) {
232424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(!connection_->connected());
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error_ == QUIC_NO_ERROR) {
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    error_ = error;
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  while (!stream_map_.empty()) {
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DataStreamMap::iterator it = stream_map_.begin();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuicStreamId id = it->first;
2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    it->second->OnConnectionClosed(error, from_peer);
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // The stream should call CloseStream as part of OnConnectionClosed.
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream_map_.find(id) != stream_map_.end()) {
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LOG(DFATAL) << ENDPOINT
2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                  << "Stream failed to close under OnConnectionClosed";
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseStream(id);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnWindowUpdateFrames(
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const vector<QuicWindowUpdateFrame>& frames) {
252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool connection_window_updated = false;
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Stream may be closed by the time we receive a WINDOW_UPDATE, so we can't
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // assume that it still exists.
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicStreamId stream_id = frames[i].stream_id;
257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (stream_id == kConnectionLevelId) {
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // This is a window update that applies to the connection, rather than an
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // individual stream.
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DVLOG(1) << ENDPOINT
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               << "Received connection level flow control window update with "
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  "byte offset: " << frames[i].byte_offset;
2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (flow_controller_->UpdateSendWindowOffset(frames[i].byte_offset)) {
264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        connection_window_updated = true;
265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      continue;
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (connection_->version() < QUIC_VERSION_21 &&
270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        (stream_id == kCryptoStreamId || stream_id == kHeadersStreamId)) {
271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DLOG(DFATAL) << "WindowUpdate for stream " << stream_id << " in version "
272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   << QuicVersionToString(connection_->version());
273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReliableQuicStream* stream = GetStream(stream_id);
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (stream) {
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      stream->OnWindowUpdateFrame(frames[i]);
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Connection level flow control window has increased, so blocked streams can
283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // write again.
284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (connection_window_updated) {
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    OnCanWrite();
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnBlockedFrames(const vector<QuicBlockedFrame>& frames) {
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // TODO(rjshade): Compare our flow control receive windows for specified
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    //                streams: if we have a large window then maybe something
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    //                had gone wrong with the flow control accounting.
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(1) << ENDPOINT << "Received BLOCKED frame with stream id: "
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             << frames[i].stream_id;
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnCanWrite() {
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We limit the number of writes to the number of pending streams. If more
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // streams become pending, WillingAndAbleToWrite will be true, which will
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // cause the connection to request resumption before yielding to other
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // connections.
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  size_t num_writes = write_blocked_streams_.NumBlockedStreams();
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (flow_controller_->IsBlocked()) {
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If we are connection level flow control blocked, then only allow the
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // crypto and headers streams to try writing as all other streams will be
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // blocked.
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    num_writes = 0;
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (write_blocked_streams_.crypto_stream_blocked()) {
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      num_writes += 1;
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (write_blocked_streams_.headers_stream_blocked()) {
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      num_writes += 1;
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
3170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (num_writes == 0) {
3180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
3190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  QuicConnection::ScopedPacketBundler ack_bundler(
3220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      connection_.get(), QuicConnection::NO_ACK);
323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < num_writes; ++i) {
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!(write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          write_blocked_streams_.HasWriteBlockedDataStreams())) {
326010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Writing one stream removed another!? Something's broken.
327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      LOG(DFATAL) << "WriteBlockedStream is missing";
328d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      connection_->CloseConnection(QUIC_INTERNAL_ERROR, false);
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!connection_->CanWriteStreamData()) {
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    QuicStreamId stream_id = write_blocked_streams_.PopFront();
335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (stream_id == kCryptoStreamId) {
336d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      has_pending_handshake_ = false;  // We just popped it.
337d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ReliableQuicStream* stream = GetStream(stream_id);
3390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (stream != NULL && !stream->flow_controller()->IsBlocked()) {
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the stream can't write all bytes, it'll re-add itself to the blocked
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // list.
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream->OnCanWrite();
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool QuicSession::WillingAndAbleToWrite() const {
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // If the crypto or headers streams are blocked, we want to schedule a write -
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // they don't get blocked by connection level flow control. Otherwise only
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // schedule a write if we are not flow control blocked at the connection
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // level.
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         (!flow_controller_->IsBlocked() &&
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          write_blocked_streams_.HasWriteBlockedDataStreams());
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
357d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool QuicSession::HasPendingHandshake() const {
358d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return has_pending_handshake_;
359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
360d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicSession::HasOpenDataStreams() const {
3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return GetNumOpenStreams() > 0;
3630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)QuicConsumedData QuicSession::WritevData(
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicStreamId id,
367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const IOVector& data,
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicStreamOffset offset,
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool fin,
370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    FecProtection fec_protection,
371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return connection_->SendStreamData(id, data, offset, fin, fec_protection,
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     ack_notifier_delegate);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)size_t QuicSession::WriteHeaders(
37723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicStreamId id,
37823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const SpdyHeaderBlock& headers,
37923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    bool fin,
38023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
38123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return headers_stream_->WriteHeaders(id, headers, fin, ack_notifier_delegate);
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::SendRstStream(QuicStreamId id,
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                QuicRstStreamErrorCode error,
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                QuicStreamOffset bytes_written) {
387c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (connection()->connected()) {
3880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Only send a RST_STREAM frame if still connected.
389c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    connection_->SendRstStream(id, error, bytes_written);
390c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
391424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CloseStreamInner(id, true);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::SendGoAway(QuicErrorCode error_code, const string& reason) {
395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (goaway_sent_) {
396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  goaway_sent_ = true;
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connection_->SendGoAway(error_code, largest_peer_created_stream_id_, reason);
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::CloseStream(QuicStreamId stream_id) {
403424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CloseStreamInner(stream_id, false);
404424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
405424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
406424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void QuicSession::CloseStreamInner(QuicStreamId stream_id,
407424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   bool locally_reset) {
408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DataStreamMap::iterator it = stream_map_.find(stream_id);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == stream_map_.end()) {
412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = it->second;
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Tell the stream that a RST has been sent.
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (locally_reset) {
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stream->set_rst_sent(true);
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  closed_streams_.push_back(it->second);
423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If we haven't received a FIN or RST for this stream, we need to keep track
425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // of the how many bytes the stream's flow controller believes it has
426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // received, for accurate connection level flow control accounting.
427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!stream->HasFinalReceivedByteOffset() &&
4286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      stream->flow_controller()->IsEnabled()) {
429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    locally_closed_streams_highest_offset_[stream_id] =
430f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        stream->flow_controller()->highest_received_byte_offset();
431f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_map_.erase(it);
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->OnClose();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset(
438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicStreamId stream_id, QuicStreamOffset final_byte_offset) {
439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  map<QuicStreamId, QuicStreamOffset>::iterator it =
440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      locally_closed_streams_highest_offset_.find(stream_id);
441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (it == locally_closed_streams_highest_offset_.end()) {
442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
443f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DVLOG(1) << ENDPOINT << "Received final byte offset " << final_byte_offset
446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           << " for stream " << stream_id;
447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uint64 offset_diff = final_byte_offset - it->second;
448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (flow_controller_->UpdateHighestReceivedOffset(
449f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      flow_controller_->highest_received_byte_offset() + offset_diff)) {
450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // If the final offset violates flow control, close the connection now.
451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (flow_controller_->FlowControlViolation()) {
452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      connection_->SendConnectionClose(
453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA);
454f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return;
455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
457f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
458f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  flow_controller_->AddBytesConsumed(offset_diff);
459f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  locally_closed_streams_highest_offset_.erase(it);
460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
461f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicSession::IsEncryptionEstablished() {
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetCryptoStream()->encryption_established();
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicSession::IsCryptoHandshakeConfirmed() {
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetCryptoStream()->handshake_confirmed();
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void QuicSession::OnConfigNegotiated() {
4710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  connection_->SetFromConfig(config_);
4726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  QuicVersion version = connection()->version();
4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // A server should accept a small number of additional streams beyond the
4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // limit sent to the client. This helps avoid early connection termination
4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // when FIN/RSTs for old streams are lost or arrive out of order.
4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (FLAGS_quic_allow_more_open_streams) {
4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    set_max_open_streams((is_server() ? kMaxStreamsMultiplier : 1.0) *
4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         config_.max_streams_per_connection());
4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (version <= QUIC_VERSION_16) {
4836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
4846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
4856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
4866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (version <= QUIC_VERSION_19) {
4876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // QUIC_VERSION_17,18,19 don't support independent stream/session flow
4886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // control windows.
4896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (config_.HasReceivedInitialFlowControlWindowBytes()) {
4906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // Streams which were created before the SHLO was received (0-RTT
4916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // requests) are now informed of the peer's initial flow control window.
4926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      uint32 new_window = config_.ReceivedInitialFlowControlWindowBytes();
4936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      OnNewStreamFlowControlWindow(new_window);
4946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      OnNewSessionFlowControlWindow(new_window);
4956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
4966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
4976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
4986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
4996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // QUIC_VERSION_21 and higher can have independent stream and session flow
5016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // control windows.
5026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) {
5036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // Streams which were created before the SHLO was received (0-RTT
5046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // requests) are now informed of the peer's initial flow control window.
5056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    OnNewStreamFlowControlWindow(
5066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.ReceivedInitialStreamFlowControlWindowBytes());
5076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
5086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (config_.HasReceivedInitialSessionFlowControlWindowBytes()) {
5096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    OnNewSessionFlowControlWindow(
5106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.ReceivedInitialSessionFlowControlWindowBytes());
511f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::OnNewStreamFlowControlWindow(uint32 new_window) {
515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (new_window < kDefaultFlowControlSendWindow) {
516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(ERROR)
517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << "Peer sent us an invalid stream flow control send window: "
518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << new_window << ", below default: " << kDefaultFlowControlSendWindow;
519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (connection_->connected()) {
52046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW);
521e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
524010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
525116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Inform all existing streams about the new window.
5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (connection_->version() >= QUIC_VERSION_21) {
5271675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    GetCryptoStream()->UpdateSendWindowOffset(new_window);
5281675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    headers_stream_->UpdateSendWindowOffset(new_window);
529116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (DataStreamMap::iterator it = stream_map_.begin();
531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       it != stream_map_.end(); ++it) {
5321675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    it->second->UpdateSendWindowOffset(new_window);
533e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
5340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
536f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::OnNewSessionFlowControlWindow(uint32 new_window) {
537f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (new_window < kDefaultFlowControlSendWindow) {
538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(ERROR)
539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << "Peer sent us an invalid session flow control send window: "
540f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << new_window << ", below default: " << kDefaultFlowControlSendWindow;
541f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (connection_->connected()) {
542f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW);
543f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
544f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
545f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
546f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
547f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  flow_controller_->UpdateSendWindowOffset(new_window);
548f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
55190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (event) {
55290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter
55390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // to QuicSession since it is the glue.
55490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case ENCRYPTION_FIRST_ESTABLISHED:
55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case ENCRYPTION_REESTABLISHED:
55890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Retransmit originally packets that were sent, since they can't be
55990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // decrypted by the peer.
5601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      connection_->RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION);
56190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
56290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case HANDSHAKE_CONFIRMED:
564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG_IF(DFATAL, !config_.negotiated()) << ENDPOINT
56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          << "Handshake confirmed without parameter negotiation.";
5665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // Discard originally encrypted packets, since they can't be decrypted by
5675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // the peer.
568cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      connection_->NeuterUnencryptedPackets();
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite());
5701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!FLAGS_quic_allow_more_open_streams) {
5711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        max_open_streams_ = config_.max_streams_per_connection();
5721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
57390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
57490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
57590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event;
577b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageSent(
5813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const CryptoHandshakeMessage& message) {
5823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageReceived(
5853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const CryptoHandshakeMessage& message) {
5863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
58890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicConfig* QuicSession::config() {
58990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return &config_;
59090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
59190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::ActivateStream(QuicDataStream* stream) {
593f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size()
594a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << ". activating " << stream->id();
595d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(stream_map_.count(stream->id()), 0u);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_map_[stream->id()] = stream;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicStreamId QuicSession::GetNextStreamId() {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicStreamId id = next_stream_id_;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_stream_id_ += 2;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return id;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id == kCryptoStreamId) {
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetCryptoStream();
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
609a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (stream_id == kHeadersStreamId) {
6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return headers_stream_.get();
6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return GetDataStream(stream_id);
6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetDataStream(const QuicStreamId stream_id) {
6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream_id == kCryptoStreamId) {
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(FATAL) << "Attempt to call GetDataStream with the crypto stream id";
6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (stream_id == kHeadersStreamId) {
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(FATAL) << "Attempt to call GetDataStream with the headers stream id";
6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DataStreamMap::iterator it = stream_map_.find(stream_id);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != stream_map_.end()) {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return it->second;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsClosedStream(stream_id)) {
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id % 2 == next_stream_id_ % 2) {
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've received a frame for a locally-created stream that is not
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // currently active.  This is an error.
6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (connection()->connected()) {
6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      connection()->SendConnectionClose(QUIC_PACKET_FOR_NONEXISTENT_STREAM);
6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return GetIncomingDataStream(stream_id);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetIncomingDataStream(QuicStreamId stream_id) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsClosedStream(stream_id)) {
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  implicitly_created_streams_.erase(stream_id);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id > largest_peer_created_stream_id_) {
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream_id - largest_peer_created_stream_id_ > kMaxStreamIdDelta) {
654e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      // We may already have sent a connection close due to multiple reset
655e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      // streams in the same packet.
656e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (connection()->connected()) {
657e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        LOG(ERROR) << "Trying to get stream: " << stream_id
658e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   << ", largest peer created stream: "
659e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   << largest_peer_created_stream_id_
660e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   << ", max delta: " << kMaxStreamIdDelta;
661e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID);
662e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      }
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
66558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (largest_peer_created_stream_id_ == 0) {
666a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (is_server()) {
6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        largest_peer_created_stream_id_= 3;
6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        largest_peer_created_stream_id_= 1;
6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
67158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
67258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (QuicStreamId id = largest_peer_created_stream_id_ + 2;
67358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         id < stream_id;
67458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         id += 2) {
67558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      implicitly_created_streams_.insert(id);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    largest_peer_created_stream_id_ = stream_id;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = CreateIncomingDataStream(stream_id);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream == NULL) {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActivateStream(stream);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return stream;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid QuicSession::set_max_open_streams(size_t max_open_streams) {
6881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DVLOG(1) << "Setting max_open_streams_ to " << max_open_streams;
6891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  max_open_streams_ = max_open_streams;
6901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool QuicSession::IsClosedStream(QuicStreamId id) {
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(0u, id);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id == kCryptoStreamId) {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
697a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (id == kHeadersStreamId) {
698a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
699424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
700424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (ContainsKey(stream_map_, id)) {
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Stream is active
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id % 2 == next_stream_id_ % 2) {
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Locally created streams are strictly in-order.  If the id is in the
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // range of created streams and it's not active, it must have been closed.
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return id < next_stream_id_;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For peer created streams, we also need to consider implicitly created
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // streams.
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return id <= largest_peer_created_stream_id_ &&
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      implicitly_created_streams_.count(id) == 0;
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t QuicSession::GetNumOpenStreams() const {
716a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return stream_map_.size() + implicitly_created_streams_.size();
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
719d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) {
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef NDEBUG
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ReliableQuicStream* stream = GetStream(id);
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream != NULL) {
7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG_IF(DFATAL, priority != stream->EffectivePriority())
7240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        << ENDPOINT << "Stream " << id
7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << "Priorities do not match.  Got: " << priority
7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << " Expected: " << stream->EffectivePriority();
7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(DFATAL) << "Marking unknown stream " << id << " blocked.";
7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
732d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (id == kCryptoStreamId) {
733d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(!has_pending_handshake_);
734d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    has_pending_handshake_ = true;
735d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // TODO(jar): Be sure to use the highest priority for the crypto stream,
736d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // perhaps by adding a "special" priority for it that is higher than
737d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // kHighestPriority.
738d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    priority = kHighestPriority;
739d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
740a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  write_blocked_streams_.PushBack(id, priority);
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicSession::HasDataToWrite() const {
744cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
745cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         write_blocked_streams_.HasWriteBlockedDataStreams() ||
746cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         connection_->HasQueuedData();
747f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
748f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
74923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const {
7507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NOTIMPLEMENTED();
7517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return false;
7527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::PostProcessAfterData() {
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteElements(&closed_streams_);
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  closed_streams_.clear();
7571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (FLAGS_close_quic_connection_unfinished_streams_2 &&
7591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      connection()->connected() &&
7601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      locally_closed_streams_highest_offset_.size() > max_open_streams_) {
7611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // A buggy client may fail to send FIN/RSTs. Don't tolerate this.
7621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    connection_->SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS);
7631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
766cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) {
767cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (version < QUIC_VERSION_19) {
768cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    flow_controller_->Disable();
769cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
77046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
771116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Disable stream level flow control based on negotiated version. Streams may
772116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // have been created with a different version.
7731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (version < QUIC_VERSION_21) {
774116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetCryptoStream()->flow_controller()->Disable();
775116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    headers_stream_->flow_controller()->Disable();
776116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
77746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (DataStreamMap::iterator it = stream_map_.begin();
77846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       it != stream_map_.end(); ++it) {
779116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (version <= QUIC_VERSION_16) {
78046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      it->second->flow_controller()->Disable();
78146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
78246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
783cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
784cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
786