quic_session.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
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); 283e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (stream != NULL && !stream->IsFlowControlBlocked()) { 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_); 367e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Tell all streams about the newly received peer receive window. 368e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (connection()->version() >= QUIC_VERSION_17) { 369e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Streams which were created before the SHLO was received (0RTT requests) 370e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // are now informed of the peer's initial flow control window. 371e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch uint32 new_flow_control_send_window = 372e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch config_.peer_initial_flow_control_window_bytes(); 373e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (new_flow_control_send_window < kDefaultFlowControlSendWindow) { 374e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch LOG(DFATAL) 375e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << "Peer sent us an invalid flow control send window: " 376e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << new_flow_control_send_window 377e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << ", below default: " << kDefaultFlowControlSendWindow; 378e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch connection_->SendConnectionClose(QUIC_FLOW_CONTROL_ERROR); 379e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 380e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 381e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DataStreamMap::iterator it = stream_map_.begin(); 382e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch while (it != stream_map_.end()) { 383e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch it->second->UpdateFlowControlSendLimit(new_flow_control_send_window); 384e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch it++; 385e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 386e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 3870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 3880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { 39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (event) { 39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter 39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // to QuicSession since it is the glue. 39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case ENCRYPTION_FIRST_ESTABLISHED: 39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case ENCRYPTION_REESTABLISHED: 39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Retransmit originally packets that were sent, since they can't be 39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // decrypted by the peer. 399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) connection_->RetransmitUnackedPackets(INITIAL_ENCRYPTION_ONLY); 40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case HANDSHAKE_CONFIRMED: 403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG_IF(DFATAL, !config_.negotiated()) << ENDPOINT 40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << "Handshake confirmed without parameter negotiation."; 405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite()); 40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) max_open_streams_ = config_.max_streams_per_connection(); 40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) default: 410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event; 411b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageSent( 4153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const CryptoHandshakeMessage& message) { 4163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 4173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageReceived( 4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const CryptoHandshakeMessage& message) { 4203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 4213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicConfig* QuicSession::config() { 42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return &config_; 42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::ActivateStream(QuicDataStream* stream) { 427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size() 428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << ". activating " << stream->id(); 429d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_EQ(stream_map_.count(stream->id()), 0u); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_map_[stream->id()] = stream; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicStreamId QuicSession::GetNextStreamId() { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QuicStreamId id = next_stream_id_; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_stream_id_ += 2; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return id; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) { 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream_id == kCryptoStreamId) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetCryptoStream(); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (stream_id == kHeadersStreamId) { 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return headers_stream_.get(); 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return GetDataStream(stream_id); 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetDataStream(const QuicStreamId stream_id) { 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (stream_id == kCryptoStreamId) { 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DLOG(FATAL) << "Attempt to call GetDataStream with the crypto stream id"; 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (stream_id == kHeadersStreamId) { 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DLOG(FATAL) << "Attempt to call GetDataStream with the headers stream id"; 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DataStreamMap::iterator it = stream_map_.find(stream_id); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != stream_map_.end()) { 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it->second; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsClosedStream(stream_id)) { 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream_id % 2 == next_stream_id_ % 2) { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We've received a frame for a locally-created stream that is not 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // currently active. This is an error. 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (connection()->connected()) { 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connection()->SendConnectionClose(QUIC_PACKET_FOR_NONEXISTENT_STREAM); 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return GetIncomingDataStream(stream_id); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetIncomingDataStream(QuicStreamId stream_id) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsClosedStream(stream_id)) { 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) implicitly_created_streams_.erase(stream_id); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream_id > largest_peer_created_stream_id_) { 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream_id - largest_peer_created_stream_id_ > kMaxStreamIdDelta) { 488e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // We may already have sent a connection close due to multiple reset 489e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // streams in the same packet. 490e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (connection()->connected()) { 491e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch LOG(ERROR) << "Trying to get stream: " << stream_id 492e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << ", largest peer created stream: " 493e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << largest_peer_created_stream_id_ 494e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << ", max delta: " << kMaxStreamIdDelta; 495e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID); 496e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 49958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (largest_peer_created_stream_id_ == 0) { 500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (is_server()) { 5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) largest_peer_created_stream_id_= 3; 5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) largest_peer_created_stream_id_= 1; 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 50558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 50658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (QuicStreamId id = largest_peer_created_stream_id_ + 2; 50758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) id < stream_id; 50858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) id += 2) { 50958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) implicitly_created_streams_.insert(id); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) largest_peer_created_stream_id_ = stream_id; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicDataStream* stream = CreateIncomingDataStream(stream_id); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream == NULL) { 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ActivateStream(stream); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stream; 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool QuicSession::IsClosedStream(QuicStreamId id) { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(0u, id); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id == kCryptoStreamId) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (id == kHeadersStreamId) { 527a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 528424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 529424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (ContainsKey(stream_map_, id)) { 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stream is active 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id % 2 == next_stream_id_ % 2) { 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Locally created streams are strictly in-order. If the id is in the 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // range of created streams and it's not active, it must have been closed. 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return id < next_stream_id_; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For peer created streams, we also need to consider implicitly created 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // streams. 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return id <= largest_peer_created_stream_id_ && 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) implicitly_created_streams_.count(id) == 0; 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t QuicSession::GetNumOpenStreams() const { 545a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return stream_map_.size() + implicitly_created_streams_.size(); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 548d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) { 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef NDEBUG 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReliableQuicStream* stream = GetStream(id); 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (stream != NULL) { 552e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (stream->IsFlowControlBlocked()) { 553e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch LOG(DFATAL) << "Stream " << id << " is flow control blocked."; 554e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG_IF(DFATAL, priority != stream->EffectivePriority()) 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "Priorities do not match. Got: " << priority 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " Expected: " << stream->EffectivePriority(); 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(DFATAL) << "Marking unknown stream " << id << " blocked."; 5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 563d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (id == kCryptoStreamId) { 564d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!has_pending_handshake_); 565d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) has_pending_handshake_ = true; 566d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(jar): Be sure to use the highest priority for the crypto stream, 567d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // perhaps by adding a "special" priority for it that is higher than 568d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // kHighestPriority. 569d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) priority = kHighestPriority; 570d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) write_blocked_streams_.PushBack(id, priority); 5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicSession::HasDataToWrite() const { 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return write_blocked_streams_.HasWriteBlockedStreams() || 576f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) connection_->HasQueuedData(); 577f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 578f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 57923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const { 5807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch NOTIMPLEMENTED(); 5817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 5827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 5837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::PostProcessAfterData() { 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLDeleteElements(&closed_streams_); 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closed_streams_.clear(); 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 590