quic_session.cc revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
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"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_headers_stream.h"
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/ssl/ssl_info.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::hash_map;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::hash_set;
162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochusing std::make_pair;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define ENDPOINT (is_server() ? "Server: " : " Client: ")
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// We want to make sure we delete any closed streams in a safe manner.
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// To avoid deleting a stream in mid-operation, we have a simple shim between
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// us and the stream, so we can delete any streams when we return from
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// processing.
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// We could just override the base methods, but this makes it easier to make
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// sure we don't miss any.
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class VisitorShim : public QuicConnectionVisitorInterface {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit VisitorShim(QuicSession* session) : session_(session) {}
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual bool OnStreamFrames(const vector<QuicStreamFrame>& frames) OVERRIDE {
35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    bool accepted = session_->OnStreamFrames(frames);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->PostProcessAfterData();
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return accepted;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnRstStream(const QuicRstStreamFrame& frame) OVERRIDE {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->OnRstStream(frame);
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->PostProcessAfterData();
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnGoAway(const QuicGoAwayFrame& frame) OVERRIDE {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->OnGoAway(frame);
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->PostProcessAfterData();
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnWindowUpdateFrames(const vector<QuicWindowUpdateFrame>& frames)
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OVERRIDE {
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    session_->OnWindowUpdateFrames(frames);
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    session_->PostProcessAfterData();
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnBlockedFrames(const vector<QuicBlockedFrame>& frames)
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OVERRIDE {
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    session_->OnBlockedFrames(frames);
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    session_->PostProcessAfterData();
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnCanWrite() OVERRIDE {
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    session_->OnCanWrite();
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->PostProcessAfterData();
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void OnSuccessfulVersionNegotiation(
67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const QuicVersion& version) OVERRIDE {
68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    session_->OnSuccessfulVersionNegotiation(version);
69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnConnectionClosed(
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      QuicErrorCode error, bool from_peer) OVERRIDE {
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    session_->OnConnectionClosed(error, from_peer);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The session will go away, so don't bother with cleanup.
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnWriteBlocked() OVERRIDE {
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    session_->OnWriteBlocked();
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual bool HasPendingWrites() const OVERRIDE {
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return session_->HasPendingWrites();
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual bool HasPendingHandshake() const OVERRIDE {
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return session_->HasPendingHandshake();
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicSession* session_;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicSession::QuicSession(QuicConnection* connection,
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         const QuicConfig& config)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : connection_(connection),
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      visitor_shim_(new VisitorShim(this)),
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      config_(config),
98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      max_open_streams_(config_.max_streams_per_connection()),
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      next_stream_id_(is_server() ? 2 : 3),
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      largest_peer_created_stream_id_(0),
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      error_(QUIC_NO_ERROR),
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      goaway_received_(false),
103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      goaway_sent_(false),
104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      has_pending_handshake_(false) {
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  connection_->set_visitor(visitor_shim_.get());
1070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  connection_->SetFromConfig(config_);
108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (connection_->connected()) {
109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    connection_->SetOverallConnectionTimeout(
110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        config_.max_time_before_crypto_handshake());
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  headers_stream_.reset(new QuicHeadersStream(this));
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!is_server()) {
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // For version above QUIC v12, the headers stream is stream 3, so the
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // next available local stream ID should be 5.
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK_EQ(kHeadersStreamId, next_stream_id_);
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    next_stream_id_ += 2;
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicSession::~QuicSession() {
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteElements(&closed_streams_);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteValues(&stream_map_);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool QuicSession::OnStreamFrames(const vector<QuicStreamFrame>& frames) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(rch) deal with the error case of stream id 0
1292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    if (IsClosedStream(frames[i].stream_id)) {
1302385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      continue;
1312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReliableQuicStream* stream = GetStream(frames[i].stream_id);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream == NULL) return false;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!stream->WillAcceptStreamFrame(frames[i])) return false;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(alyssar) check against existing connection address: if changed, make
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sure we update the connection.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
142424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    QuicStreamId stream_id = frames[i].stream_id;
143424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ReliableQuicStream* stream = GetStream(stream_id);
144424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!stream) {
145424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      continue;
146424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
147424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    stream->OnStreamFrame(frames[i]);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeaders(QuicStreamId stream_id,
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  StringPiece headers_data) {
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(stream_id);
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!stream) {
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // It's quite possible to receive headers after a stream has been reset.
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamHeaders(headers_data);
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeadersPriority(QuicStreamId stream_id,
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          QuicPriority priority) {
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(stream_id);
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!stream) {
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // It's quite possible to receive headers after a stream has been reset.
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamHeadersPriority(priority);
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeadersComplete(QuicStreamId stream_id,
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          bool fin,
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          size_t frame_len) {
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(stream_id);
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!stream) {
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // It's quite possible to receive headers after a stream has been reset.
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamHeadersComplete(fin, frame_len);
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (frame.stream_id == kCryptoStreamId) {
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection()->SendConnectionCloseWithDetails(
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        QUIC_INVALID_STREAM_ID,
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "Attempt to reset the crypto stream");
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (frame.stream_id == kHeadersStreamId) {
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    connection()->SendConnectionCloseWithDetails(
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        QUIC_INVALID_STREAM_ID,
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "Attempt to reset the headers stream");
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = GetDataStream(frame.stream_id);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!stream) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Errors are handled by GetStream.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream->OnStreamReset(frame);
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(frame.last_good_stream_id < next_stream_id_);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  goaway_received_ = true;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) {
211424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(!connection_->connected());
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error_ == QUIC_NO_ERROR) {
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    error_ = error;
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  while (!stream_map_.empty()) {
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DataStreamMap::iterator it = stream_map_.begin();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuicStreamId id = it->first;
2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    it->second->OnConnectionClosed(error, from_peer);
2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // The stream should call CloseStream as part of OnConnectionClosed.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream_map_.find(id) != stream_map_.end()) {
2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LOG(DFATAL) << ENDPOINT
2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                  << "Stream failed to close under OnConnectionClosed";
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseStream(id);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnWindowUpdateFrames(
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const vector<QuicWindowUpdateFrame>& frames) {
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Stream may be closed by the time we receive a WINDOW_UPDATE, so we can't
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // assume that it still exists.
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicStreamId stream_id = frames[i].stream_id;
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (stream_id == 0) {
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // This is a window update that applies to the connection, rather than an
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // individual stream.
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // TODO(rjshade): Adjust connection level flow control window.
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DVLOG(1) << ENDPOINT
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               << "Received connection level flow control window update with "
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  "byte offset: " << frames[i].byte_offset;
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      continue;
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    QuicDataStream* stream = GetDataStream(stream_id);
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (stream) {
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      stream->OnWindowUpdateFrame(frames[i]);
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnBlockedFrames(const vector<QuicBlockedFrame>& frames) {
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // TODO(rjshade): Compare our flow control receive windows for specified
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    //                streams: if we have a large window then maybe something
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    //                had gone wrong with the flow control accounting.
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVLOG(1) << ENDPOINT << "Received BLOCKED frame with stream id: "
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             << frames[i].stream_id;
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnCanWrite() {
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We limit the number of writes to the number of pending streams. If more
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // streams become pending, HasPendingWrites will be true, which will cause
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // the connection to request resumption before yielding to other connections.
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  size_t num_writes = write_blocked_streams_.NumBlockedStreams();
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < num_writes; ++i) {
269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!write_blocked_streams_.HasWriteBlockedStreams()) {
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Writing one stream removed another?! Something's broken.
271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      LOG(DFATAL) << "WriteBlockedStream is missing";
272d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      connection_->CloseConnection(QUIC_INTERNAL_ERROR, false);
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!connection_->CanWriteStreamData()) {
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    QuicStreamId stream_id = write_blocked_streams_.PopFront();
279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (stream_id == kCryptoStreamId) {
280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      has_pending_handshake_ = false;  // We just popped it.
281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
282d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ReliableQuicStream* stream = GetStream(stream_id);
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (stream != NULL) {
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the stream can't write all bytes, it'll re-add itself to the blocked
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // list.
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream->OnCanWrite();
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool QuicSession::HasPendingWrites() const {
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return write_blocked_streams_.HasWriteBlockedStreams();
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
295d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool QuicSession::HasPendingHandshake() const {
296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return has_pending_handshake_;
297d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)QuicConsumedData QuicSession::WritevData(
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicStreamId id,
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const IOVector& data,
302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicStreamOffset offset,
303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool fin,
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return connection_->SendStreamData(id, data, offset, fin,
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     ack_notifier_delegate);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)size_t QuicSession::WriteHeaders(
31023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicStreamId id,
31123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const SpdyHeaderBlock& headers,
31223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    bool fin,
31323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
31423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return headers_stream_->WriteHeaders(id, headers, fin, ack_notifier_delegate);
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::SendRstStream(QuicStreamId id,
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                QuicRstStreamErrorCode error,
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                QuicStreamOffset bytes_written) {
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  connection_->SendRstStream(id, error, bytes_written);
321424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CloseStreamInner(id, true);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::SendGoAway(QuicErrorCode error_code, const string& reason) {
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (goaway_sent_) {
326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  goaway_sent_ = true;
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connection_->SendGoAway(error_code, largest_peer_created_stream_id_, reason);
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::CloseStream(QuicStreamId stream_id) {
333424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CloseStreamInner(stream_id, false);
334424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
335424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
336424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void QuicSession::CloseStreamInner(QuicStreamId stream_id,
337424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   bool locally_reset) {
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DataStreamMap::iterator it = stream_map_.find(stream_id);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == stream_map_.end()) {
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = it->second;
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Tell the stream that a RST has been sent.
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (locally_reset) {
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stream->set_rst_sent(true);
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  closed_streams_.push_back(it->second);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_map_.erase(it);
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream->OnClose();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicSession::IsEncryptionEstablished() {
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetCryptoStream()->encryption_established();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicSession::IsCryptoHandshakeConfirmed() {
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetCryptoStream()->handshake_confirmed();
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void QuicSession::OnConfigNegotiated() {
3660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  connection_->SetFromConfig(config_);
3670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
3680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (event) {
37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter
37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // to QuicSession since it is the glue.
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case ENCRYPTION_FIRST_ESTABLISHED:
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case ENCRYPTION_REESTABLISHED:
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Retransmit originally packets that were sent, since they can't be
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // decrypted by the peer.
379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      connection_->RetransmitUnackedPackets(INITIAL_ENCRYPTION_ONLY);
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case HANDSHAKE_CONFIRMED:
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG_IF(DFATAL, !config_.negotiated()) << ENDPOINT
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          << "Handshake confirmed without parameter negotiation.";
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite());
38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      max_open_streams_ = config_.max_streams_per_connection();
38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event;
391b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageSent(
3953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const CryptoHandshakeMessage& message) {
3963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageReceived(
3993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const CryptoHandshakeMessage& message) {
4003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicConfig* QuicSession::config() {
40390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return &config_;
40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::ActivateStream(QuicDataStream* stream) {
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size()
408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << ". activating " << stream->id();
409d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(stream_map_.count(stream->id()), 0u);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_map_[stream->id()] = stream;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicStreamId QuicSession::GetNextStreamId() {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicStreamId id = next_stream_id_;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_stream_id_ += 2;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return id;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id == kCryptoStreamId) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetCryptoStream();
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (stream_id == kHeadersStreamId) {
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return headers_stream_.get();
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return GetDataStream(stream_id);
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetDataStream(const QuicStreamId stream_id) {
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream_id == kCryptoStreamId) {
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(FATAL) << "Attempt to call GetDataStream with the crypto stream id";
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (stream_id == kHeadersStreamId) {
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(FATAL) << "Attempt to call GetDataStream with the headers stream id";
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DataStreamMap::iterator it = stream_map_.find(stream_id);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != stream_map_.end()) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return it->second;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsClosedStream(stream_id)) {
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id % 2 == next_stream_id_ % 2) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've received a frame for a locally-created stream that is not
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // currently active.  This is an error.
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (connection()->connected()) {
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      connection()->SendConnectionClose(QUIC_PACKET_FOR_NONEXISTENT_STREAM);
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return GetIncomingDataStream(stream_id);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetIncomingDataStream(QuicStreamId stream_id) {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsClosedStream(stream_id)) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  implicitly_created_streams_.erase(stream_id);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id > largest_peer_created_stream_id_) {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(rch) add unit test for this
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream_id - largest_peer_created_stream_id_ > kMaxStreamIdDelta) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
47258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (largest_peer_created_stream_id_ == 0) {
473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (is_server()) {
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        largest_peer_created_stream_id_= 3;
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        largest_peer_created_stream_id_= 1;
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
47858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
47958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (QuicStreamId id = largest_peer_created_stream_id_ + 2;
48058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         id < stream_id;
48158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         id += 2) {
48258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      implicitly_created_streams_.insert(id);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    largest_peer_created_stream_id_ = stream_id;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream* stream = CreateIncomingDataStream(stream_id);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream == NULL) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActivateStream(stream);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return stream;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool QuicSession::IsClosedStream(QuicStreamId id) {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(0u, id);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id == kCryptoStreamId) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (id == kHeadersStreamId) {
500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
501424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
502424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (ContainsKey(stream_map_, id)) {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Stream is active
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id % 2 == next_stream_id_ % 2) {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Locally created streams are strictly in-order.  If the id is in the
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // range of created streams and it's not active, it must have been closed.
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return id < next_stream_id_;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For peer created streams, we also need to consider implicitly created
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // streams.
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return id <= largest_peer_created_stream_id_ &&
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      implicitly_created_streams_.count(id) == 0;
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t QuicSession::GetNumOpenStreams() const {
518a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return stream_map_.size() + implicitly_created_streams_.size();
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
521d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) {
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef NDEBUG
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ReliableQuicStream* stream = GetStream(id);
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream != NULL) {
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG_IF(DFATAL, priority != stream->EffectivePriority())
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << "Priorities do not match.  Got: " << priority
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << " Expected: " << stream->EffectivePriority();
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(DFATAL) << "Marking unknown stream " << id << " blocked.";
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
533d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (id == kCryptoStreamId) {
534d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(!has_pending_handshake_);
535d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    has_pending_handshake_ = true;
536d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // TODO(jar): Be sure to use the highest priority for the crypto stream,
537d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // perhaps by adding a "special" priority for it that is higher than
538d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // kHighestPriority.
539d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    priority = kHighestPriority;
540d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  write_blocked_streams_.PushBack(id, priority);
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicSession::HasDataToWrite() const {
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return write_blocked_streams_.HasWriteBlockedStreams() ||
546f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      connection_->HasQueuedData();
547f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
548f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
54923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const {
5507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NOTIMPLEMENTED();
5517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return false;
5527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
5537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::PostProcessAfterData() {
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteElements(&closed_streams_);
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  closed_streams_.clear();
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
560