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