quic_session.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_session.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h" 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/quic/crypto/proof_verifier.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_connection.h" 10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/quic/quic_flags.h" 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/quic/quic_flow_controller.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_headers_stream.h" 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/ssl/ssl_info.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::hash_map; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::hash_set; 182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochusing std::make_pair; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define ENDPOINT (is_server() ? "Server: " : " Client: ") 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// We want to make sure we delete any closed streams in a safe manner. 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// To avoid deleting a stream in mid-operation, we have a simple shim between 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// us and the stream, so we can delete any streams when we return from 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// processing. 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// We could just override the base methods, but this makes it easier to make 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// sure we don't miss any. 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class VisitorShim : public QuicConnectionVisitorInterface { 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit VisitorShim(QuicSession* session) : session_(session) {} 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual void OnStreamFrames(const vector<QuicStreamFrame>& frames) OVERRIDE { 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu session_->OnStreamFrames(frames); 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_->PostProcessAfterData(); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnRstStream(const QuicRstStreamFrame& frame) OVERRIDE { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_->OnRstStream(frame); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_->PostProcessAfterData(); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnGoAway(const QuicGoAwayFrame& frame) OVERRIDE { 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_->OnGoAway(frame); 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_->PostProcessAfterData(); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnWindowUpdateFrames(const vector<QuicWindowUpdateFrame>& frames) 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OVERRIDE { 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) session_->OnWindowUpdateFrames(frames); 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) session_->PostProcessAfterData(); 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnBlockedFrames(const vector<QuicBlockedFrame>& frames) 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OVERRIDE { 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) session_->OnBlockedFrames(frames); 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) session_->PostProcessAfterData(); 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnCanWrite() OVERRIDE { 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) session_->OnCanWrite(); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_->PostProcessAfterData(); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnSuccessfulVersionNegotiation( 68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const QuicVersion& version) OVERRIDE { 69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) session_->OnSuccessfulVersionNegotiation(version); 70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnConnectionClosed( 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicErrorCode error, bool from_peer) OVERRIDE { 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) session_->OnConnectionClosed(error, from_peer); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The session will go away, so don't bother with cleanup. 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnWriteBlocked() OVERRIDE { 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) session_->OnWriteBlocked(); 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual bool WillingAndAbleToWrite() const OVERRIDE { 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return session_->WillingAndAbleToWrite(); 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual bool HasPendingHandshake() const OVERRIDE { 87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return session_->HasPendingHandshake(); 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch virtual bool HasOpenDataStreams() const OVERRIDE { 910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return session_->HasOpenDataStreams(); 920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QuicSession* session_; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : connection_(connection), 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_shim_(new VisitorShim(this)), 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) config_(config), 102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch max_open_streams_(config_.max_streams_per_connection()), 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_stream_id_(is_server() ? 2 : 3), 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) largest_peer_created_stream_id_(0), 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) error_(QUIC_NO_ERROR), 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) goaway_received_(false), 107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) goaway_sent_(false), 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) has_pending_handshake_(false) { 1096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (connection_->version() <= QUIC_VERSION_19) { 1106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) flow_controller_.reset(new QuicFlowController( 1116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) connection_.get(), 0, is_server(), kDefaultFlowControlSendWindow, 1126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) config_.GetInitialFlowControlWindowToSend(), 1136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) config_.GetInitialFlowControlWindowToSend())); 1146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } else { 1156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) flow_controller_.reset(new QuicFlowController( 1166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) connection_.get(), 0, is_server(), kDefaultFlowControlSendWindow, 1176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) config_.GetInitialSessionFlowControlWindowToSend(), 1186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) config_.GetInitialSessionFlowControlWindowToSend())); 1196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) connection_->set_visitor(visitor_shim_.get()); 1220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) connection_->SetFromConfig(config_); 123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (connection_->connected()) { 124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch connection_->SetOverallConnectionTimeout( 125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch config_.max_time_before_crypto_handshake()); 126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) headers_stream_.reset(new QuicHeadersStream(this)); 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!is_server()) { 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // For version above QUIC v12, the headers stream is stream 3, so the 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // next available local stream ID should be 5. 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(kHeadersStreamId, next_stream_id_); 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) next_stream_id_ += 2; 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicSession::~QuicSession() { 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLDeleteElements(&closed_streams_); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLDeleteValues(&stream_map_); 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DLOG_IF(WARNING, 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) locally_closed_streams_highest_offset_.size() > max_open_streams_) 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) << "Surprisingly high number of locally closed streams still waiting for " 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "final byte offset: " << locally_closed_streams_highest_offset_.size(); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid QuicSession::OnStreamFrames(const vector<QuicStreamFrame>& frames) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < frames.size(); ++i) { 1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // TODO(rch) deal with the error case of stream id 0. 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const QuicStreamFrame& frame = frames[i]; 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) QuicStreamId stream_id = frame.stream_id; 151424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ReliableQuicStream* stream = GetStream(stream_id); 152424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!stream) { 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The stream no longer exists, but we may still be interested in the 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // final stream byte offset sent by the peer. A frame with a FIN can give 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // us this offset. 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (frame.fin) { 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) QuicStreamOffset final_byte_offset = 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) frame.offset + frame.data.TotalBufferSize(); 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) UpdateFlowControlOnFinalReceivedByteOffset(stream_id, 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) final_byte_offset); 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) continue; 164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) stream->OnStreamFrame(frames[i]); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeaders(QuicStreamId stream_id, 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) StringPiece headers_data) { 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicDataStream* stream = GetDataStream(stream_id); 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!stream) { 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // It's quite possible to receive headers after a stream has been reset. 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->OnStreamHeaders(headers_data); 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeadersPriority(QuicStreamId stream_id, 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicPriority priority) { 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicDataStream* stream = GetDataStream(stream_id); 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!stream) { 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // It's quite possible to receive headers after a stream has been reset. 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->OnStreamHeadersPriority(priority); 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::OnStreamHeadersComplete(QuicStreamId stream_id, 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool fin, 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t frame_len) { 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicDataStream* stream = GetDataStream(stream_id); 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!stream) { 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // It's quite possible to receive headers after a stream has been reset. 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->OnStreamHeadersComplete(fin, frame_len); 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) { 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (frame.stream_id == kCryptoStreamId) { 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connection()->SendConnectionCloseWithDetails( 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QUIC_INVALID_STREAM_ID, 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Attempt to reset the crypto stream"); 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (frame.stream_id == kHeadersStreamId) { 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connection()->SendConnectionCloseWithDetails( 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QUIC_INVALID_STREAM_ID, 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Attempt to reset the headers stream"); 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicDataStream* stream = GetDataStream(frame.stream_id); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!stream) { 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The RST frame contains the final byte offset for the stream: we can now 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // update the connection level flow controller if needed. 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) UpdateFlowControlOnFinalReceivedByteOffset(frame.stream_id, 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) frame.byte_offset); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Errors are handled by GetStream. 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->OnStreamReset(frame); 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) { 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(frame.last_good_stream_id < next_stream_id_); 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) goaway_received_ = true; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) { 232424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(!connection_->connected()); 233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (error_ == QUIC_NO_ERROR) { 234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) error_ = error; 235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while (!stream_map_.empty()) { 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DataStreamMap::iterator it = stream_map_.begin(); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QuicStreamId id = it->first; 2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) it->second->OnConnectionClosed(error, from_peer); 2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The stream should call CloseStream as part of OnConnectionClosed. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream_map_.find(id) != stream_map_.end()) { 2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) LOG(DFATAL) << ENDPOINT 2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) << "Stream failed to close under OnConnectionClosed"; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseStream(id); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnWindowUpdateFrames( 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const vector<QuicWindowUpdateFrame>& frames) { 252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool connection_window_updated = false; 253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < frames.size(); ++i) { 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Stream may be closed by the time we receive a WINDOW_UPDATE, so we can't 255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // assume that it still exists. 256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) QuicStreamId stream_id = frames[i].stream_id; 257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (stream_id == 0) { 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // This is a window update that applies to the connection, rather than an 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // individual stream. 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(1) << ENDPOINT 261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "Received connection level flow control window update with " 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "byte offset: " << frames[i].byte_offset; 263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (FLAGS_enable_quic_connection_flow_control_2 && 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) flow_controller_->UpdateSendWindowOffset(frames[i].byte_offset)) { 265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) connection_window_updated = true; 266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue; 268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) QuicDataStream* stream = GetDataStream(stream_id); 271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (stream) { 272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stream->OnWindowUpdateFrame(frames[i]); 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 275010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 276010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Connection level flow control window has increased, so blocked streams can 277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // write again. 278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (connection_window_updated) { 279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) OnCanWrite(); 280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnBlockedFrames(const vector<QuicBlockedFrame>& frames) { 284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < frames.size(); ++i) { 285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(rjshade): Compare our flow control receive windows for specified 286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // streams: if we have a large window then maybe something 287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // had gone wrong with the flow control accounting. 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DVLOG(1) << ENDPOINT << "Received BLOCKED frame with stream id: " 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << frames[i].stream_id; 290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicSession::OnCanWrite() { 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // We limit the number of writes to the number of pending streams. If more 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // streams become pending, WillingAndAbleToWrite will be true, which will 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // cause the connection to request resumption before yielding to other 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // connections. 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t num_writes = write_blocked_streams_.NumBlockedStreams(); 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (flow_controller_->IsBlocked()) { 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If we are connection level flow control blocked, then only allow the 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // crypto and headers streams to try writing as all other streams will be 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // blocked. 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) num_writes = 0; 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (write_blocked_streams_.crypto_stream_blocked()) { 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) num_writes += 1; 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (write_blocked_streams_.headers_stream_blocked()) { 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) num_writes += 1; 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 3110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (num_writes == 0) { 3120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 3130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch QuicConnection::ScopedPacketBundler ack_bundler( 3160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch connection_.get(), QuicConnection::NO_ACK); 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < num_writes; ++i) { 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!(write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) write_blocked_streams_.HasWriteBlockedDataStreams())) { 320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Writing one stream removed another!? Something's broken. 321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LOG(DFATAL) << "WriteBlockedStream is missing"; 322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) connection_->CloseConnection(QUIC_INTERNAL_ERROR, false); 323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!connection_->CanWriteStreamData()) { 326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicStreamId stream_id = write_blocked_streams_.PopFront(); 329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (stream_id == kCryptoStreamId) { 330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) has_pending_handshake_ = false; // We just popped it. 331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ReliableQuicStream* stream = GetStream(stream_id); 3330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (stream != NULL && !stream->flow_controller()->IsBlocked()) { 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the stream can't write all bytes, it'll re-add itself to the blocked 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // list. 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->OnCanWrite(); 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool QuicSession::WillingAndAbleToWrite() const { 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If the crypto or headers streams are blocked, we want to schedule a write - 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // they don't get blocked by connection level flow control. Otherwise only 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // schedule a write if we are not flow control blocked at the connection 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // level. 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (!flow_controller_->IsBlocked() && 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) write_blocked_streams_.HasWriteBlockedDataStreams()); 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 351d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool QuicSession::HasPendingHandshake() const { 352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return has_pending_handshake_; 353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 354d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicSession::HasOpenDataStreams() const { 3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return GetNumOpenStreams() > 0; 3570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 3580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)QuicConsumedData QuicSession::WritevData( 360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) QuicStreamId id, 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const IOVector& data, 362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) QuicStreamOffset offset, 363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool fin, 364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FecProtection fec_protection, 365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { 366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return connection_->SendStreamData(id, data, offset, fin, fec_protection, 367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ack_notifier_delegate); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)size_t QuicSession::WriteHeaders( 37123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) QuicStreamId id, 37223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const SpdyHeaderBlock& headers, 37323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) bool fin, 37423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { 37523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return headers_stream_->WriteHeaders(id, headers, fin, ack_notifier_delegate); 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::SendRstStream(QuicStreamId id, 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicRstStreamErrorCode error, 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicStreamOffset bytes_written) { 381c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (connection()->connected()) { 3820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Only send a RST_STREAM frame if still connected. 383c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch connection_->SendRstStream(id, error, bytes_written); 384c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 385424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) CloseStreamInner(id, true); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::SendGoAway(QuicErrorCode error_code, const string& reason) { 389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (goaway_sent_) { 390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) goaway_sent_ = true; 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connection_->SendGoAway(error_code, largest_peer_created_stream_id_, reason); 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::CloseStream(QuicStreamId stream_id) { 397424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) CloseStreamInner(stream_id, false); 398424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 399424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 400424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void QuicSession::CloseStreamInner(QuicStreamId stream_id, 401424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool locally_reset) { 402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DataStreamMap::iterator it = stream_map_.find(stream_id); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == stream_map_.end()) { 406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicDataStream* stream = it->second; 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Tell the stream that a RST has been sent. 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (locally_reset) { 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->set_rst_sent(true); 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closed_streams_.push_back(it->second); 417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If we haven't received a FIN or RST for this stream, we need to keep track 419f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // of the how many bytes the stream's flow controller believes it has 420f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // received, for accurate connection level flow control accounting. 421f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!stream->HasFinalReceivedByteOffset() && 422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) stream->flow_controller()->IsEnabled() && 423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FLAGS_enable_quic_connection_flow_control_2) { 424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) locally_closed_streams_highest_offset_[stream_id] = 425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) stream->flow_controller()->highest_received_byte_offset(); 426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_map_.erase(it); 429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream->OnClose(); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset( 433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) QuicStreamId stream_id, QuicStreamOffset final_byte_offset) { 434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!FLAGS_enable_quic_connection_flow_control_2) { 435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) map<QuicStreamId, QuicStreamOffset>::iterator it = 439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) locally_closed_streams_highest_offset_.find(stream_id); 440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (it == locally_closed_streams_highest_offset_.end()) { 441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 443f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DVLOG(1) << ENDPOINT << "Received final byte offset " << final_byte_offset 445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) << " for stream " << stream_id; 446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint64 offset_diff = final_byte_offset - it->second; 447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (flow_controller_->UpdateHighestReceivedOffset( 448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) flow_controller_->highest_received_byte_offset() + offset_diff)) { 449f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If the final offset violates flow control, close the connection now. 450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (flow_controller_->FlowControlViolation()) { 451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) connection_->SendConnectionClose( 452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA); 453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 454f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 457f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) flow_controller_->AddBytesConsumed(offset_diff); 458f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) locally_closed_streams_highest_offset_.erase(it); 459f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicSession::IsEncryptionEstablished() { 462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GetCryptoStream()->encryption_established(); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicSession::IsCryptoHandshakeConfirmed() { 466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GetCryptoStream()->handshake_confirmed(); 467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void QuicSession::OnConfigNegotiated() { 4700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) connection_->SetFromConfig(config_); 4716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) QuicVersion version = connection()->version(); 4726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (version < QUIC_VERSION_17) { 4736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 4746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 4756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (version <= QUIC_VERSION_19) { 4776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // QUIC_VERSION_17,18,19 don't support independent stream/session flow 4786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // control windows. 4796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (config_.HasReceivedInitialFlowControlWindowBytes()) { 4806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Streams which were created before the SHLO was received (0-RTT 4816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // requests) are now informed of the peer's initial flow control window. 4826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) uint32 new_window = config_.ReceivedInitialFlowControlWindowBytes(); 4836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) OnNewStreamFlowControlWindow(new_window); 4846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) OnNewSessionFlowControlWindow(new_window); 4856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 4866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 4886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 4896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 4906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // QUIC_VERSION_20 and higher can have independent stream and session flow 4916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // control windows. 4926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) { 4936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Streams which were created before the SHLO was received (0-RTT 4946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // requests) are now informed of the peer's initial flow control window. 4956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) OnNewStreamFlowControlWindow( 4966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) config_.ReceivedInitialStreamFlowControlWindowBytes()); 4976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 4986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (config_.HasReceivedInitialSessionFlowControlWindowBytes()) { 4996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) OnNewSessionFlowControlWindow( 5006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) config_.ReceivedInitialSessionFlowControlWindowBytes()); 501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::OnNewStreamFlowControlWindow(uint32 new_window) { 505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (new_window < kDefaultFlowControlSendWindow) { 506f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(ERROR) 507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) << "Peer sent us an invalid stream flow control send window: " 508f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) << new_window << ", below default: " << kDefaultFlowControlSendWindow; 509f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (connection_->connected()) { 51046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW); 511e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 514010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (DataStreamMap::iterator it = stream_map_.begin(); 516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) it != stream_map_.end(); ++it) { 517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) it->second->flow_controller()->UpdateSendWindowOffset(new_window); 518e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 5190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 5200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 521f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicSession::OnNewSessionFlowControlWindow(uint32 new_window) { 522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (new_window < kDefaultFlowControlSendWindow) { 523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(ERROR) 524f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) << "Peer sent us an invalid session flow control send window: " 525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) << new_window << ", below default: " << kDefaultFlowControlSendWindow; 526f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (connection_->connected()) { 527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW); 528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 532f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) flow_controller_->UpdateSendWindowOffset(new_window); 533f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 534f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { 53690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (event) { 53790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter 53890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // to QuicSession since it is the glue. 53990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case ENCRYPTION_FIRST_ESTABLISHED: 54090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 54190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 54290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case ENCRYPTION_REESTABLISHED: 54390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Retransmit originally packets that were sent, since they can't be 54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // decrypted by the peer. 545a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) connection_->RetransmitUnackedPackets(INITIAL_ENCRYPTION_ONLY); 54690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 54790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 54890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case HANDSHAKE_CONFIRMED: 549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG_IF(DFATAL, !config_.negotiated()) << ENDPOINT 55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << "Handshake confirmed without parameter negotiation."; 5515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Discard originally encrypted packets, since they can't be decrypted by 5525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // the peer. 553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) connection_->NeuterUnencryptedPackets(); 554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite()); 55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) max_open_streams_ = config_.max_streams_per_connection(); 55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 55890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) default: 559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event; 560b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageSent( 5643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const CryptoHandshakeMessage& message) { 5653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 5663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 5673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicSession::OnCryptoHandshakeMessageReceived( 5683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const CryptoHandshakeMessage& message) { 5693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 5703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 57190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicConfig* QuicSession::config() { 57290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return &config_; 57390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 57490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSession::ActivateStream(QuicDataStream* stream) { 576f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size() 577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << ". activating " << stream->id(); 578d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_EQ(stream_map_.count(stream->id()), 0u); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_map_[stream->id()] = stream; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicStreamId QuicSession::GetNextStreamId() { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QuicStreamId id = next_stream_id_; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_stream_id_ += 2; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return id; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) { 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream_id == kCryptoStreamId) { 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetCryptoStream(); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 592a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (stream_id == kHeadersStreamId) { 5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return headers_stream_.get(); 5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return GetDataStream(stream_id); 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetDataStream(const QuicStreamId stream_id) { 5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (stream_id == kCryptoStreamId) { 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DLOG(FATAL) << "Attempt to call GetDataStream with the crypto stream id"; 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 603a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (stream_id == kHeadersStreamId) { 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DLOG(FATAL) << "Attempt to call GetDataStream with the headers stream id"; 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DataStreamMap::iterator it = stream_map_.find(stream_id); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != stream_map_.end()) { 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it->second; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsClosedStream(stream_id)) { 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream_id % 2 == next_stream_id_ % 2) { 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We've received a frame for a locally-created stream that is not 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // currently active. This is an error. 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (connection()->connected()) { 6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connection()->SendConnectionClose(QUIC_PACKET_FOR_NONEXISTENT_STREAM); 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return GetIncomingDataStream(stream_id); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream* QuicSession::GetIncomingDataStream(QuicStreamId stream_id) { 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsClosedStream(stream_id)) { 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) implicitly_created_streams_.erase(stream_id); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream_id > largest_peer_created_stream_id_) { 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream_id - largest_peer_created_stream_id_ > kMaxStreamIdDelta) { 637e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // We may already have sent a connection close due to multiple reset 638e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // streams in the same packet. 639e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (connection()->connected()) { 640e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch LOG(ERROR) << "Trying to get stream: " << stream_id 641e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << ", largest peer created stream: " 642e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << largest_peer_created_stream_id_ 643e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch << ", max delta: " << kMaxStreamIdDelta; 644e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID); 645e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 64858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (largest_peer_created_stream_id_ == 0) { 649a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (is_server()) { 6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) largest_peer_created_stream_id_= 3; 6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) largest_peer_created_stream_id_= 1; 6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 65458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 65558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (QuicStreamId id = largest_peer_created_stream_id_ + 2; 65658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) id < stream_id; 65758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) id += 2) { 65858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) implicitly_created_streams_.insert(id); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) largest_peer_created_stream_id_ = stream_id; 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicDataStream* stream = CreateIncomingDataStream(stream_id); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream == NULL) { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ActivateStream(stream); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stream; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool QuicSession::IsClosedStream(QuicStreamId id) { 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(0u, id); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id == kCryptoStreamId) { 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (id == kHeadersStreamId) { 676a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 677424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 678424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (ContainsKey(stream_map_, id)) { 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stream is active 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id % 2 == next_stream_id_ % 2) { 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Locally created streams are strictly in-order. If the id is in the 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // range of created streams and it's not active, it must have been closed. 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return id < next_stream_id_; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For peer created streams, we also need to consider implicitly created 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // streams. 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return id <= largest_peer_created_stream_id_ && 6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) implicitly_created_streams_.count(id) == 0; 6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t QuicSession::GetNumOpenStreams() const { 694a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return stream_map_.size() + implicitly_created_streams_.size(); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 697d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) { 6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef NDEBUG 6995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReliableQuicStream* stream = GetStream(id); 7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (stream != NULL) { 7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG_IF(DFATAL, priority != stream->EffectivePriority()) 7020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch << ENDPOINT << "Stream " << id 7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "Priorities do not match. Got: " << priority 7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " Expected: " << stream->EffectivePriority(); 7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(DFATAL) << "Marking unknown stream " << id << " blocked."; 7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 710d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (id == kCryptoStreamId) { 711d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!has_pending_handshake_); 712d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) has_pending_handshake_ = true; 713d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(jar): Be sure to use the highest priority for the crypto stream, 714d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // perhaps by adding a "special" priority for it that is higher than 715d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // kHighestPriority. 716d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) priority = kHighestPriority; 717d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 718a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) write_blocked_streams_.PushBack(id, priority); 7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicSession::HasDataToWrite() const { 722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || 723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) write_blocked_streams_.HasWriteBlockedDataStreams() || 724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) connection_->HasQueuedData(); 725f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 726f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 72723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const { 7287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch NOTIMPLEMENTED(); 7297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 7307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 7317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicSession::PostProcessAfterData() { 7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLDeleteElements(&closed_streams_); 7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closed_streams_.clear(); 7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) { 738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (version < QUIC_VERSION_19) { 739cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) flow_controller_->Disable(); 740cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 74146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 74246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Inform all streams about the negotiated version. They may have been created 74346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // with a different version. 74446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (DataStreamMap::iterator it = stream_map_.begin(); 74546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != stream_map_.end(); ++it) { 74646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (version < QUIC_VERSION_17) { 74746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it->second->flow_controller()->Disable(); 74846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 74946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 750cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 753