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