quic_session.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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)  }
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void QuicSession::InitializeSession() {
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  connection_->set_visitor(visitor_shim_.get());
1240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  connection_->SetFromConfig(config_);
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (connection_->connected()) {
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    connection_->SetOverallConnectionTimeout(
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        config_.max_time_before_crypto_handshake());
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  headers_stream_.reset(new QuicHeadersStream(this));
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!is_server()) {
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // For version above QUIC v12, the headers stream is stream 3, so the
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // next available local stream ID should be 5.
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK_EQ(kHeadersStreamId, next_stream_id_);
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    next_stream_id_ += 2;
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicSession::~QuicSession() {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteElements(&closed_streams_);
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteValues(&stream_map_);
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DLOG_IF(WARNING,
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          locally_closed_streams_highest_offset_.size() > max_open_streams_)
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "Surprisingly high number of locally closed streams still waiting for "
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)         "final byte offset: " << locally_closed_streams_highest_offset_.size();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid QuicSession::OnStreamFrames(const vector<QuicStreamFrame>& frames) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // TODO(rch) deal with the error case of stream id 0.
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const QuicStreamFrame& frame = frames[i];
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicStreamId stream_id = frame.stream_id;
153424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ReliableQuicStream* stream = GetStream(stream_id);
154424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!stream) {
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // The stream no longer exists, but we may still be interested in the
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // final stream byte offset sent by the peer. A frame with a FIN can give
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // us this offset.
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (frame.fin) {
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        QuicStreamOffset final_byte_offset =
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            frame.offset + frame.data.TotalBufferSize();
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        UpdateFlowControlOnFinalReceivedByteOffset(stream_id,
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                   final_byte_offset);
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      continue;
166424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
167424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    stream->OnStreamFrame(frames[i]);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeaders(QuicStreamId stream_id,
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  StringPiece headers_data) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(stream_id);
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!stream) {
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // It's quite possible to receive headers after a stream has been reset.
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamHeaders(headers_data);
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeadersPriority(QuicStreamId stream_id,
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          QuicPriority priority) {
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(stream_id);
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!stream) {
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // It's quite possible to receive headers after a stream has been reset.
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamHeadersPriority(priority);
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeadersComplete(QuicStreamId stream_id,
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          bool fin,
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          size_t frame_len) {
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(stream_id);
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!stream) {
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // It's quite possible to receive headers after a stream has been reset.
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamHeadersComplete(fin, frame_len);
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (frame.stream_id == kCryptoStreamId) {
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection()->SendConnectionCloseWithDetails(
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        QUIC_INVALID_STREAM_ID,
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "Attempt to reset the crypto stream");
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (frame.stream_id == kHeadersStreamId) {
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection()->SendConnectionCloseWithDetails(
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        QUIC_INVALID_STREAM_ID,
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "Attempt to reset the headers stream");
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(frame.stream_id);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!stream) {
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // The RST frame contains the final byte offset for the stream: we can now
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // update the connection level flow controller if needed.
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    UpdateFlowControlOnFinalReceivedByteOffset(frame.stream_id,
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                               frame.byte_offset);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Errors are handled by GetStream.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamReset(frame);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(frame.last_good_stream_id < next_stream_id_);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  goaway_received_ = true;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) {
234424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(!connection_->connected());
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error_ == QUIC_NO_ERROR) {
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    error_ = error;
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  while (!stream_map_.empty()) {
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DataStreamMap::iterator it = stream_map_.begin();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuicStreamId id = it->first;
2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    it->second->OnConnectionClosed(error, from_peer);
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // The stream should call CloseStream as part of OnConnectionClosed.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream_map_.find(id) != stream_map_.end()) {
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LOG(DFATAL) << ENDPOINT
2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                  << "Stream failed to close under OnConnectionClosed";
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseStream(id);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnWindowUpdateFrames(
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const vector<QuicWindowUpdateFrame>& frames) {
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool connection_window_updated = false;
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Stream may be closed by the time we receive a WINDOW_UPDATE, so we can't
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // assume that it still exists.
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicStreamId stream_id = frames[i].stream_id;
259116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (stream_id == kConnectionLevelId) {
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // This is a window update that applies to the connection, rather than an
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // individual stream.
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DVLOG(1) << ENDPOINT
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               << "Received connection level flow control window update with "
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  "byte offset: " << frames[i].byte_offset;
2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (flow_controller_->UpdateSendWindowOffset(frames[i].byte_offset)) {
266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        connection_window_updated = true;
267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      continue;
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (connection_->version() <= QUIC_VERSION_20 &&
272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        (stream_id == kCryptoStreamId || stream_id == kHeadersStreamId)) {
273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DLOG(DFATAL) << "WindowUpdate for stream " << stream_id << " in version "
274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   << QuicVersionToString(connection_->version());
275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReliableQuicStream* stream = GetStream(stream_id);
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (stream) {
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      stream->OnWindowUpdateFrame(frames[i]);
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Connection level flow control window has increased, so blocked streams can
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // write again.
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (connection_window_updated) {
287010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    OnCanWrite();
288010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnBlockedFrames(const vector<QuicBlockedFrame>& frames) {
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // TODO(rjshade): Compare our flow control receive windows for specified
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    //                streams: if we have a large window then maybe something
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    //                had gone wrong with the flow control accounting.
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(1) << ENDPOINT << "Received BLOCKED frame with stream id: "
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             << frames[i].stream_id;
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnCanWrite() {
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We limit the number of writes to the number of pending streams. If more
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // streams become pending, WillingAndAbleToWrite will be true, which will
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // cause the connection to request resumption before yielding to other
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // connections.
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  size_t num_writes = write_blocked_streams_.NumBlockedStreams();
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (flow_controller_->IsBlocked()) {
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If we are connection level flow control blocked, then only allow the
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // crypto and headers streams to try writing as all other streams will be
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // blocked.
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    num_writes = 0;
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (write_blocked_streams_.crypto_stream_blocked()) {
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      num_writes += 1;
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (write_blocked_streams_.headers_stream_blocked()) {
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      num_writes += 1;
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
3190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (num_writes == 0) {
3200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
3210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  QuicConnection::ScopedPacketBundler ack_bundler(
3240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      connection_.get(), QuicConnection::NO_ACK);
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < num_writes; ++i) {
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!(write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          write_blocked_streams_.HasWriteBlockedDataStreams())) {
328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Writing one stream removed another!? Something's broken.
329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      LOG(DFATAL) << "WriteBlockedStream is missing";
330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      connection_->CloseConnection(QUIC_INTERNAL_ERROR, false);
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!connection_->CanWriteStreamData()) {
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    QuicStreamId stream_id = write_blocked_streams_.PopFront();
337d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (stream_id == kCryptoStreamId) {
338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      has_pending_handshake_ = false;  // We just popped it.
339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ReliableQuicStream* stream = GetStream(stream_id);
3410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (stream != NULL && !stream->flow_controller()->IsBlocked()) {
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the stream can't write all bytes, it'll re-add itself to the blocked
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // list.
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream->OnCanWrite();
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool QuicSession::WillingAndAbleToWrite() const {
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // If the crypto or headers streams are blocked, we want to schedule a write -
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // they don't get blocked by connection level flow control. Otherwise only
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // schedule a write if we are not flow control blocked at the connection
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // level.
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         (!flow_controller_->IsBlocked() &&
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          write_blocked_streams_.HasWriteBlockedDataStreams());
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool QuicSession::HasPendingHandshake() const {
360d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return has_pending_handshake_;
361d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
362d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicSession::HasOpenDataStreams() const {
3640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return GetNumOpenStreams() > 0;
3650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)QuicConsumedData QuicSession::WritevData(
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicStreamId id,
369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const IOVector& data,
370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicStreamOffset offset,
371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool fin,
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    FecProtection fec_protection,
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return connection_->SendStreamData(id, data, offset, fin, fec_protection,
375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     ack_notifier_delegate);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)size_t QuicSession::WriteHeaders(
37923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicStreamId id,
38023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const SpdyHeaderBlock& headers,
38123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    bool fin,
38223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
38323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return headers_stream_->WriteHeaders(id, headers, fin, ack_notifier_delegate);
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::SendRstStream(QuicStreamId id,
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                QuicRstStreamErrorCode error,
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                QuicStreamOffset bytes_written) {
389c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (connection()->connected()) {
3900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Only send a RST_STREAM frame if still connected.
391c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    connection_->SendRstStream(id, error, bytes_written);
392c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
393424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CloseStreamInner(id, true);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::SendGoAway(QuicErrorCode error_code, const string& reason) {
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (goaway_sent_) {
398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  goaway_sent_ = true;
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connection_->SendGoAway(error_code, largest_peer_created_stream_id_, reason);
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::CloseStream(QuicStreamId stream_id) {
405424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CloseStreamInner(stream_id, false);
406424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
407424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
408424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void QuicSession::CloseStreamInner(QuicStreamId stream_id,
409424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   bool locally_reset) {
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DataStreamMap::iterator it = stream_map_.find(stream_id);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == stream_map_.end()) {
414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = it->second;
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Tell the stream that a RST has been sent.
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (locally_reset) {
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stream->set_rst_sent(true);
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  closed_streams_.push_back(it->second);
425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If we haven't received a FIN or RST for this stream, we need to keep track
427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // of the how many bytes the stream's flow controller believes it has
428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // received, for accurate connection level flow control accounting.
429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!stream->HasFinalReceivedByteOffset() &&
4306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      stream->flow_controller()->IsEnabled()) {
431f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    locally_closed_streams_highest_offset_[stream_id] =
432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        stream->flow_controller()->highest_received_byte_offset();
4336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (FLAGS_close_quic_connection_unfinished_streams &&
4346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        connection()->connected() &&
4356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        locally_closed_streams_highest_offset_.size() > max_open_streams_) {
4366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // A buggy client may fail to send FIN/RSTs. Don't tolerate this.
4376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      connection_->SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS);
4386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_map_.erase(it);
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->OnClose();
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset(
446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    QuicStreamId stream_id, QuicStreamOffset final_byte_offset) {
447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  map<QuicStreamId, QuicStreamOffset>::iterator it =
448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      locally_closed_streams_highest_offset_.find(stream_id);
449f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (it == locally_closed_streams_highest_offset_.end()) {
450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DVLOG(1) << ENDPOINT << "Received final byte offset " << final_byte_offset
454f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           << " for stream " << stream_id;
455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uint64 offset_diff = final_byte_offset - it->second;
456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (flow_controller_->UpdateHighestReceivedOffset(
457f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      flow_controller_->highest_received_byte_offset() + offset_diff)) {
458f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // If the final offset violates flow control, close the connection now.
459f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (flow_controller_->FlowControlViolation()) {
460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      connection_->SendConnectionClose(
461f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA);
462f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return;
463f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
464f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
465f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
466f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  flow_controller_->AddBytesConsumed(offset_diff);
467f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  locally_closed_streams_highest_offset_.erase(it);
468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicSession::IsEncryptionEstablished() {
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetCryptoStream()->encryption_established();
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicSession::IsCryptoHandshakeConfirmed() {
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetCryptoStream()->handshake_confirmed();
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void QuicSession::OnConfigNegotiated() {
4790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  connection_->SetFromConfig(config_);
4806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  QuicVersion version = connection()->version();
481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (version <= QUIC_VERSION_16) {
4826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
4836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
4846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
4856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (version <= QUIC_VERSION_19) {
4866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // QUIC_VERSION_17,18,19 don't support independent stream/session flow
4876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // control windows.
4886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (config_.HasReceivedInitialFlowControlWindowBytes()) {
4896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // Streams which were created before the SHLO was received (0-RTT
4906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // requests) are now informed of the peer's initial flow control window.
4916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      uint32 new_window = config_.ReceivedInitialFlowControlWindowBytes();
4926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      OnNewStreamFlowControlWindow(new_window);
4936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      OnNewSessionFlowControlWindow(new_window);
4946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
4956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
4966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
4976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
4986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
4996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // QUIC_VERSION_20 and higher can have independent stream and session flow
5006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // control windows.
5016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) {
5026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // Streams which were created before the SHLO was received (0-RTT
5036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // requests) are now informed of the peer's initial flow control window.
5046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    OnNewStreamFlowControlWindow(
5056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.ReceivedInitialStreamFlowControlWindowBytes());
5066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
5076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (config_.HasReceivedInitialSessionFlowControlWindowBytes()) {
5086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    OnNewSessionFlowControlWindow(
5096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        config_.ReceivedInitialSessionFlowControlWindowBytes());
510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
511f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::OnNewStreamFlowControlWindow(uint32 new_window) {
514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (new_window < kDefaultFlowControlSendWindow) {
515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(ERROR)
516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << "Peer sent us an invalid stream flow control send window: "
517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << new_window << ", below default: " << kDefaultFlowControlSendWindow;
518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (connection_->connected()) {
51946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW);
520e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
521f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
523010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
524116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Inform all existing streams about the new window.
525116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (connection_->version() > QUIC_VERSION_20) {
526116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetCryptoStream()->flow_controller()->UpdateSendWindowOffset(new_window);
527116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    headers_stream_->flow_controller()->UpdateSendWindowOffset(new_window);
528116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (DataStreamMap::iterator it = stream_map_.begin();
530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       it != stream_map_.end(); ++it) {
531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    it->second->flow_controller()->UpdateSendWindowOffset(new_window);
532e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
5330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
535f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::OnNewSessionFlowControlWindow(uint32 new_window) {
536f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (new_window < kDefaultFlowControlSendWindow) {
537f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(ERROR)
538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << "Peer sent us an invalid session flow control send window: "
539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        << new_window << ", below default: " << kDefaultFlowControlSendWindow;
540f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (connection_->connected()) {
541f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW);
542f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
543f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
544f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
545f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
546f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  flow_controller_->UpdateSendWindowOffset(new_window);
547f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
548f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (event) {
55190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter
55290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // to QuicSession since it is the glue.
55390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case ENCRYPTION_FIRST_ESTABLISHED:
55490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case ENCRYPTION_REESTABLISHED:
55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Retransmit originally packets that were sent, since they can't be
55890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // decrypted by the peer.
559a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      connection_->RetransmitUnackedPackets(INITIAL_ENCRYPTION_ONLY);
56090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
56190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
56290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case HANDSHAKE_CONFIRMED:
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG_IF(DFATAL, !config_.negotiated()) << ENDPOINT
56490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          << "Handshake confirmed without parameter negotiation.";
5655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // Discard originally encrypted packets, since they can't be decrypted by
5665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // the peer.
567cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      connection_->NeuterUnencryptedPackets();
568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite());
56990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      max_open_streams_ = config_.max_streams_per_connection();
57090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
57190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
57290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event;
574b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageSent(
5783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const CryptoHandshakeMessage& message) {
5793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageReceived(
5823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const CryptoHandshakeMessage& message) {
5833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
58590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicConfig* QuicSession::config() {
58690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return &config_;
58790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
58890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::ActivateStream(QuicDataStream* stream) {
590f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size()
591a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << ". activating " << stream->id();
592d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(stream_map_.count(stream->id()), 0u);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_map_[stream->id()] = stream;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicStreamId QuicSession::GetNextStreamId() {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicStreamId id = next_stream_id_;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_stream_id_ += 2;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return id;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) {
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id == kCryptoStreamId) {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetCryptoStream();
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
606a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (stream_id == kHeadersStreamId) {
6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return headers_stream_.get();
6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return GetDataStream(stream_id);
6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetDataStream(const QuicStreamId stream_id) {
6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream_id == kCryptoStreamId) {
6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(FATAL) << "Attempt to call GetDataStream with the crypto stream id";
6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
617a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (stream_id == kHeadersStreamId) {
6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(FATAL) << "Attempt to call GetDataStream with the headers stream id";
6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DataStreamMap::iterator it = stream_map_.find(stream_id);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != stream_map_.end()) {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return it->second;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsClosedStream(stream_id)) {
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id % 2 == next_stream_id_ % 2) {
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've received a frame for a locally-created stream that is not
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // currently active.  This is an error.
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (connection()->connected()) {
6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      connection()->SendConnectionClose(QUIC_PACKET_FOR_NONEXISTENT_STREAM);
6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return GetIncomingDataStream(stream_id);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetIncomingDataStream(QuicStreamId stream_id) {
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsClosedStream(stream_id)) {
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  implicitly_created_streams_.erase(stream_id);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id > largest_peer_created_stream_id_) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream_id - largest_peer_created_stream_id_ > kMaxStreamIdDelta) {
651e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      // We may already have sent a connection close due to multiple reset
652e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      // streams in the same packet.
653e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (connection()->connected()) {
654e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        LOG(ERROR) << "Trying to get stream: " << stream_id
655e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   << ", largest peer created stream: "
656e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   << largest_peer_created_stream_id_
657e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   << ", max delta: " << kMaxStreamIdDelta;
658e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID);
659e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
66258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (largest_peer_created_stream_id_ == 0) {
663a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (is_server()) {
6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        largest_peer_created_stream_id_= 3;
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        largest_peer_created_stream_id_= 1;
6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
66858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
66958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (QuicStreamId id = largest_peer_created_stream_id_ + 2;
67058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         id < stream_id;
67158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         id += 2) {
67258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      implicitly_created_streams_.insert(id);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    largest_peer_created_stream_id_ = stream_id;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = CreateIncomingDataStream(stream_id);
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream == NULL) {
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActivateStream(stream);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return stream;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool QuicSession::IsClosedStream(QuicStreamId id) {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(0u, id);
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id == kCryptoStreamId) {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
689a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (id == kHeadersStreamId) {
690a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
691424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
692424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (ContainsKey(stream_map_, id)) {
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Stream is active
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id % 2 == next_stream_id_ % 2) {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Locally created streams are strictly in-order.  If the id is in the
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // range of created streams and it's not active, it must have been closed.
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return id < next_stream_id_;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For peer created streams, we also need to consider implicitly created
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // streams.
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return id <= largest_peer_created_stream_id_ &&
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      implicitly_created_streams_.count(id) == 0;
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t QuicSession::GetNumOpenStreams() const {
708a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return stream_map_.size() + implicitly_created_streams_.size();
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
711d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) {
7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef NDEBUG
7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ReliableQuicStream* stream = GetStream(id);
7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream != NULL) {
7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG_IF(DFATAL, priority != stream->EffectivePriority())
7160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        << ENDPOINT << "Stream " << id
7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << "Priorities do not match.  Got: " << priority
7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << " Expected: " << stream->EffectivePriority();
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(DFATAL) << "Marking unknown stream " << id << " blocked.";
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
724d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (id == kCryptoStreamId) {
725d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(!has_pending_handshake_);
726d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    has_pending_handshake_ = true;
727d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // TODO(jar): Be sure to use the highest priority for the crypto stream,
728d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // perhaps by adding a "special" priority for it that is higher than
729d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // kHighestPriority.
730d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    priority = kHighestPriority;
731d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
732a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  write_blocked_streams_.PushBack(id, priority);
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicSession::HasDataToWrite() const {
736cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         write_blocked_streams_.HasWriteBlockedDataStreams() ||
738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         connection_->HasQueuedData();
739f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
740f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
74123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const {
7427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NOTIMPLEMENTED();
7437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return false;
7447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::PostProcessAfterData() {
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteElements(&closed_streams_);
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  closed_streams_.clear();
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) {
752cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (version < QUIC_VERSION_19) {
753cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    flow_controller_->Disable();
754cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
75546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
756116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Disable stream level flow control based on negotiated version. Streams may
757116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // have been created with a different version.
758116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (version <= QUIC_VERSION_20) {
759116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetCryptoStream()->flow_controller()->Disable();
760116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    headers_stream_->flow_controller()->Disable();
761116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
76246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (DataStreamMap::iterator it = stream_map_.begin();
76346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       it != stream_map_.end(); ++it) {
764116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (version <= QUIC_VERSION_16) {
76546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      it->second->flow_controller()->Disable();
76646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
76746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
768cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
769cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
771