quic_session.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
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)
67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void OnSuccessfulVersionNegotiation(
68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const QuicVersion& version) OVERRIDE {
69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    session_->OnSuccessfulVersionNegotiation(version);
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnConnectionClosed(
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      QuicErrorCode error, bool from_peer) OVERRIDE {
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    session_->OnConnectionClosed(error, from_peer);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The session will go away, so don't bother with cleanup.
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnWriteBlocked() OVERRIDE {
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    session_->OnWriteBlocked();
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual bool WillingAndAbleToWrite() const OVERRIDE {
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return session_->WillingAndAbleToWrite();
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual bool HasPendingHandshake() const OVERRIDE {
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return session_->HasPendingHandshake();
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual bool HasOpenDataStreams() const OVERRIDE {
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return session_->HasOpenDataStreams();
920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicSession* session_;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : connection_(connection),
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      visitor_shim_(new VisitorShim(this)),
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      config_(config),
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      max_open_streams_(config_.max_streams_per_connection()),
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      next_stream_id_(is_server() ? 2 : 3),
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      largest_peer_created_stream_id_(0),
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      error_(QUIC_NO_ERROR),
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      goaway_received_(false),
107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      goaway_sent_(false),
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      has_pending_handshake_(false) {
1096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (connection_->version() <= QUIC_VERSION_19) {
1106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    flow_controller_.reset(new QuicFlowController(
1116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        connection_.get(), 0, is_server(), kDefaultFlowControlSendWindow,
1126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.GetInitialFlowControlWindowToSend(),
1136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.GetInitialFlowControlWindowToSend()));
1146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  } else {
1156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    flow_controller_.reset(new QuicFlowController(
1166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        connection_.get(), 0, is_server(), kDefaultFlowControlSendWindow,
1176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.GetInitialSessionFlowControlWindowToSend(),
1186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.GetInitialSessionFlowControlWindowToSend()));
1196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  connection_->set_visitor(visitor_shim_.get());
1220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  connection_->SetFromConfig(config_);
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (connection_->connected()) {
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    connection_->SetOverallConnectionTimeout(
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        config_.max_time_before_crypto_handshake());
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  headers_stream_.reset(new QuicHeadersStream(this));
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!is_server()) {
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // For version above QUIC v12, the headers stream is stream 3, so the
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // next available local stream ID should be 5.
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK_EQ(kHeadersStreamId, next_stream_id_);
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    next_stream_id_ += 2;
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
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;
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (stream_id == 0) {
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;
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (FLAGS_enable_quic_connection_flow_control_2 &&
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          flow_controller_->UpdateSendWindowOffset(frames[i].byte_offset)) {
265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        connection_window_updated = true;
266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      continue;
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicDataStream* stream = GetDataStream(stream_id);
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (stream) {
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      stream->OnWindowUpdateFrame(frames[i]);
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
275010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
276010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Connection level flow control window has increased, so blocked streams can
277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // write again.
278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (connection_window_updated) {
279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    OnCanWrite();
280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnBlockedFrames(const vector<QuicBlockedFrame>& frames) {
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // TODO(rjshade): Compare our flow control receive windows for specified
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    //                streams: if we have a large window then maybe something
287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    //                had gone wrong with the flow control accounting.
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(1) << ENDPOINT << "Received BLOCKED frame with stream id: "
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             << frames[i].stream_id;
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnCanWrite() {
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We limit the number of writes to the number of pending streams. If more
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // streams become pending, WillingAndAbleToWrite will be true, which will
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // cause the connection to request resumption before yielding to other
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // connections.
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  size_t num_writes = write_blocked_streams_.NumBlockedStreams();
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (flow_controller_->IsBlocked()) {
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If we are connection level flow control blocked, then only allow the
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // crypto and headers streams to try writing as all other streams will be
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // blocked.
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    num_writes = 0;
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (write_blocked_streams_.crypto_stream_blocked()) {
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      num_writes += 1;
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (write_blocked_streams_.headers_stream_blocked()) {
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      num_writes += 1;
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
3110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (num_writes == 0) {
3120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
3130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  QuicConnection::ScopedPacketBundler ack_bundler(
3160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      connection_.get(), QuicConnection::NO_ACK);
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < num_writes; ++i) {
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!(write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          write_blocked_streams_.HasWriteBlockedDataStreams())) {
320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Writing one stream removed another!? Something's broken.
321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      LOG(DFATAL) << "WriteBlockedStream is missing";
322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      connection_->CloseConnection(QUIC_INTERNAL_ERROR, false);
323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!connection_->CanWriteStreamData()) {
326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    QuicStreamId stream_id = write_blocked_streams_.PopFront();
329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (stream_id == kCryptoStreamId) {
330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      has_pending_handshake_ = false;  // We just popped it.
331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ReliableQuicStream* stream = GetStream(stream_id);
3330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (stream != NULL && !stream->flow_controller()->IsBlocked()) {
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the stream can't write all bytes, it'll re-add itself to the blocked
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // list.
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream->OnCanWrite();
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool QuicSession::WillingAndAbleToWrite() const {
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // If the crypto or headers streams are blocked, we want to schedule a write -
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // they don't get blocked by connection level flow control. Otherwise only
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // schedule a write if we are not flow control blocked at the connection
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // level.
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         (!flow_controller_->IsBlocked() &&
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          write_blocked_streams_.HasWriteBlockedDataStreams());
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
351d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool QuicSession::HasPendingHandshake() const {
352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return has_pending_handshake_;
353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
354d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicSession::HasOpenDataStreams() const {
3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return GetNumOpenStreams() > 0;
3570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)QuicConsumedData QuicSession::WritevData(
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicStreamId id,
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const IOVector& data,
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicStreamOffset offset,
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool fin,
364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    FecProtection fec_protection,
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return connection_->SendStreamData(id, data, offset, fin, fec_protection,
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     ack_notifier_delegate);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)size_t QuicSession::WriteHeaders(
37123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicStreamId id,
37223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const SpdyHeaderBlock& headers,
37323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    bool fin,
37423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
37523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return headers_stream_->WriteHeaders(id, headers, fin, ack_notifier_delegate);
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::SendRstStream(QuicStreamId id,
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                QuicRstStreamErrorCode error,
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                QuicStreamOffset bytes_written) {
381c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (connection()->connected()) {
3820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Only send a RST_STREAM frame if still connected.
383c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    connection_->SendRstStream(id, error, bytes_written);
384c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
385424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CloseStreamInner(id, true);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::SendGoAway(QuicErrorCode error_code, const string& reason) {
389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (goaway_sent_) {
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  goaway_sent_ = true;
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connection_->SendGoAway(error_code, largest_peer_created_stream_id_, reason);
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::CloseStream(QuicStreamId stream_id) {
397424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CloseStreamInner(stream_id, false);
398424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
399424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
400424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void QuicSession::CloseStreamInner(QuicStreamId stream_id,
401424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   bool locally_reset) {
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DataStreamMap::iterator it = stream_map_.find(stream_id);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == stream_map_.end()) {
406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = it->second;
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Tell the stream that a RST has been sent.
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (locally_reset) {
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stream->set_rst_sent(true);
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  closed_streams_.push_back(it->second);
417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If we haven't received a FIN or RST for this stream, we need to keep track
419f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // of the how many bytes the stream's flow controller believes it has
420f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // received, for accurate connection level flow control accounting.
421f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!stream->HasFinalReceivedByteOffset() &&
422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      stream->flow_controller()->IsEnabled() &&
423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      FLAGS_enable_quic_connection_flow_control_2) {
424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    locally_closed_streams_highest_offset_[stream_id] =
425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        stream->flow_controller()->highest_received_byte_offset();
426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_map_.erase(it);
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->OnClose();
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset(
433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicStreamId stream_id, QuicStreamOffset final_byte_offset) {
434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!FLAGS_enable_quic_connection_flow_control_2) {
435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  map<QuicStreamId, QuicStreamOffset>::iterator it =
439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      locally_closed_streams_highest_offset_.find(stream_id);
440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (it == locally_closed_streams_highest_offset_.end()) {
441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
443f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DVLOG(1) << ENDPOINT << "Received final byte offset " << final_byte_offset
445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           << " for stream " << stream_id;
446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uint64 offset_diff = final_byte_offset - it->second;
447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (flow_controller_->UpdateHighestReceivedOffset(
448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      flow_controller_->highest_received_byte_offset() + offset_diff)) {
449f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // If the final offset violates flow control, close the connection now.
450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (flow_controller_->FlowControlViolation()) {
451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      connection_->SendConnectionClose(
452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA);
453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return;
454f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
457f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  flow_controller_->AddBytesConsumed(offset_diff);
458f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  locally_closed_streams_highest_offset_.erase(it);
459f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicSession::IsEncryptionEstablished() {
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetCryptoStream()->encryption_established();
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicSession::IsCryptoHandshakeConfirmed() {
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetCryptoStream()->handshake_confirmed();
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void QuicSession::OnConfigNegotiated() {
4700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  connection_->SetFromConfig(config_);
4716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  QuicVersion version = connection()->version();
4726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (version < QUIC_VERSION_17) {
4736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
4746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
4756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
4766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (version <= QUIC_VERSION_19) {
4776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // QUIC_VERSION_17,18,19 don't support independent stream/session flow
4786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // control windows.
4796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (config_.HasReceivedInitialFlowControlWindowBytes()) {
4806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // Streams which were created before the SHLO was received (0-RTT
4816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // requests) are now informed of the peer's initial flow control window.
4826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      uint32 new_window = config_.ReceivedInitialFlowControlWindowBytes();
4836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      OnNewStreamFlowControlWindow(new_window);
4846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      OnNewSessionFlowControlWindow(new_window);
4856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
4866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
4876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
4886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
4896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
4906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // QUIC_VERSION_20 and higher can have independent stream and session flow
4916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // control windows.
4926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) {
4936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // Streams which were created before the SHLO was received (0-RTT
4946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // requests) are now informed of the peer's initial flow control window.
4956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    OnNewStreamFlowControlWindow(
4966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.ReceivedInitialStreamFlowControlWindowBytes());
4976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
4986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (config_.HasReceivedInitialSessionFlowControlWindowBytes()) {
4996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    OnNewSessionFlowControlWindow(
5006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.ReceivedInitialSessionFlowControlWindowBytes());
501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::OnNewStreamFlowControlWindow(uint32 new_window) {
505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (new_window < kDefaultFlowControlSendWindow) {
506f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(ERROR)
507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << "Peer sent us an invalid stream flow control send window: "
508f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << new_window << ", below default: " << kDefaultFlowControlSendWindow;
509f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (connection_->connected()) {
51046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW);
511e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
514010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (DataStreamMap::iterator it = stream_map_.begin();
516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       it != stream_map_.end(); ++it) {
517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    it->second->flow_controller()->UpdateSendWindowOffset(new_window);
518e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
5190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
521f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::OnNewSessionFlowControlWindow(uint32 new_window) {
522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (new_window < kDefaultFlowControlSendWindow) {
523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(ERROR)
524f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << "Peer sent us an invalid session flow control send window: "
525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << new_window << ", below default: " << kDefaultFlowControlSendWindow;
526f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (connection_->connected()) {
527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW);
528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
532f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  flow_controller_->UpdateSendWindowOffset(new_window);
533f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
534f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
53690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (event) {
53790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter
53890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // to QuicSession since it is the glue.
53990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case ENCRYPTION_FIRST_ESTABLISHED:
54090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
54190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
54290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case ENCRYPTION_REESTABLISHED:
54390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Retransmit originally packets that were sent, since they can't be
54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // decrypted by the peer.
545a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      connection_->RetransmitUnackedPackets(INITIAL_ENCRYPTION_ONLY);
54690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
54790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
54890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case HANDSHAKE_CONFIRMED:
549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG_IF(DFATAL, !config_.negotiated()) << ENDPOINT
55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          << "Handshake confirmed without parameter negotiation.";
5515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // Discard originally encrypted packets, since they can't be decrypted by
5525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // the peer.
553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      connection_->NeuterUnencryptedPackets();
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite());
55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      max_open_streams_ = config_.max_streams_per_connection();
55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
55890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event;
560b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageSent(
5643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const CryptoHandshakeMessage& message) {
5653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageReceived(
5683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const CryptoHandshakeMessage& message) {
5693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
57190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicConfig* QuicSession::config() {
57290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return &config_;
57390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
57490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::ActivateStream(QuicDataStream* stream) {
576f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size()
577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << ". activating " << stream->id();
578d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(stream_map_.count(stream->id()), 0u);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_map_[stream->id()] = stream;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicStreamId QuicSession::GetNextStreamId() {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicStreamId id = next_stream_id_;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_stream_id_ += 2;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return id;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id == kCryptoStreamId) {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetCryptoStream();
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
592a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (stream_id == kHeadersStreamId) {
5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return headers_stream_.get();
5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return GetDataStream(stream_id);
5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetDataStream(const QuicStreamId stream_id) {
5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream_id == kCryptoStreamId) {
6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(FATAL) << "Attempt to call GetDataStream with the crypto stream id";
6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
603a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (stream_id == kHeadersStreamId) {
6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(FATAL) << "Attempt to call GetDataStream with the headers stream id";
6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DataStreamMap::iterator it = stream_map_.find(stream_id);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != stream_map_.end()) {
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return it->second;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsClosedStream(stream_id)) {
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id % 2 == next_stream_id_ % 2) {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've received a frame for a locally-created stream that is not
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // currently active.  This is an error.
6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (connection()->connected()) {
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      connection()->SendConnectionClose(QUIC_PACKET_FOR_NONEXISTENT_STREAM);
6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return GetIncomingDataStream(stream_id);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetIncomingDataStream(QuicStreamId stream_id) {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsClosedStream(stream_id)) {
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  implicitly_created_streams_.erase(stream_id);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id > largest_peer_created_stream_id_) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream_id - largest_peer_created_stream_id_ > kMaxStreamIdDelta) {
637e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      // We may already have sent a connection close due to multiple reset
638e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      // streams in the same packet.
639e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (connection()->connected()) {
640e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        LOG(ERROR) << "Trying to get stream: " << stream_id
641e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   << ", largest peer created stream: "
642e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   << largest_peer_created_stream_id_
643e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   << ", max delta: " << kMaxStreamIdDelta;
644e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID);
645e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
64858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (largest_peer_created_stream_id_ == 0) {
649a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (is_server()) {
6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        largest_peer_created_stream_id_= 3;
6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        largest_peer_created_stream_id_= 1;
6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
65458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
65558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (QuicStreamId id = largest_peer_created_stream_id_ + 2;
65658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         id < stream_id;
65758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         id += 2) {
65858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      implicitly_created_streams_.insert(id);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    largest_peer_created_stream_id_ = stream_id;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = CreateIncomingDataStream(stream_id);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream == NULL) {
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActivateStream(stream);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return stream;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool QuicSession::IsClosedStream(QuicStreamId id) {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(0u, id);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id == kCryptoStreamId) {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (id == kHeadersStreamId) {
676a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
677424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
678424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (ContainsKey(stream_map_, id)) {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Stream is active
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id % 2 == next_stream_id_ % 2) {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Locally created streams are strictly in-order.  If the id is in the
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // range of created streams and it's not active, it must have been closed.
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return id < next_stream_id_;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For peer created streams, we also need to consider implicitly created
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // streams.
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return id <= largest_peer_created_stream_id_ &&
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      implicitly_created_streams_.count(id) == 0;
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t QuicSession::GetNumOpenStreams() const {
694a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return stream_map_.size() + implicitly_created_streams_.size();
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
697d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) {
6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef NDEBUG
6995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ReliableQuicStream* stream = GetStream(id);
7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream != NULL) {
7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG_IF(DFATAL, priority != stream->EffectivePriority())
7020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        << ENDPOINT << "Stream " << id
7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << "Priorities do not match.  Got: " << priority
7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << " Expected: " << stream->EffectivePriority();
7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(DFATAL) << "Marking unknown stream " << id << " blocked.";
7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
710d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (id == kCryptoStreamId) {
711d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(!has_pending_handshake_);
712d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    has_pending_handshake_ = true;
713d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // TODO(jar): Be sure to use the highest priority for the crypto stream,
714d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // perhaps by adding a "special" priority for it that is higher than
715d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // kHighestPriority.
716d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    priority = kHighestPriority;
717d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
718a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  write_blocked_streams_.PushBack(id, priority);
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicSession::HasDataToWrite() const {
722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         write_blocked_streams_.HasWriteBlockedDataStreams() ||
724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         connection_->HasQueuedData();
725f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
726f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
72723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const {
7287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NOTIMPLEMENTED();
7297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return false;
7307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::PostProcessAfterData() {
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteElements(&closed_streams_);
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  closed_streams_.clear();
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) {
738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (version < QUIC_VERSION_19) {
739cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    flow_controller_->Disable();
740cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
74146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
74246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Inform all streams about the negotiated version. They may have been created
74346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // with a different version.
74446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (DataStreamMap::iterator it = stream_map_.begin();
74546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       it != stream_map_.end(); ++it) {
74646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (version < QUIC_VERSION_17) {
74746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      it->second->flow_controller()->Disable();
74846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
74946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
750cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
753