quic_session.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_connection.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece;
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::hash_map;
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::hash_set;
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicSession::QuicSession(QuicConnection* connection, bool is_server)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : connection_(connection),
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_open_streams_(kDefaultMaxStreamsPerConnection),
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_stream_id_(is_server ? 2 : 3),
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_server_(is_server),
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      largest_peer_created_stream_id_(0) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->set_visitor(this);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicSession::~QuicSession() {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool QuicSession::OnPacket(const IPEndPoint& self_address,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const IPEndPoint& peer_address,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const QuicPacketHeader& header,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const vector<QuicStreamFrame>& frames) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header.guid != connection()->guid()) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(INFO) << "Got packet header for invalid GUID: " << header.guid;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(rch) deal with the error case of stream id 0
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsClosedStream(frames[i].stream_id)) continue;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReliableQuicStream* stream = GetStream(frames[i].stream_id);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream == NULL) return false;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!stream->WillAcceptStreamFrame(frames[i])) return false;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(alyssar) check against existing connection address: if changed, make
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sure we update the connection.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < frames.size(); ++i) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReliableQuicStream* stream = GetStream(frames[i].stream_id);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stream->OnStreamFrame(frames[i]);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReliableQuicStream* stream = GetStream(frame.stream_id);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!stream) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Errors are handled by GetStream.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream->OnStreamReset(frame.error_code, frame.offset);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::ConnectionClose(QuicErrorCode error, bool from_peer) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (stream_map_.size() != 0) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReliableStreamMap::iterator it = stream_map_.begin();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuicStreamId id = it->first;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->second->ConnectionClose(error, from_peer);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The stream should call CloseStream as part of ConnectionClose.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream_map_.find(id) != stream_map_.end()) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(DFATAL) << "Stream failed to close under ConnectionClose";
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseStream(id);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int QuicSession::WriteData(QuicStreamId id, StringPiece data,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               QuicStreamOffset offset, bool fin) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return connection_->SendStreamData(id, data, offset, fin, NULL);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::SendRstStream(QuicStreamId id,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                QuicErrorCode error,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                QuicStreamOffset offset) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->SendRstStream(id, error, offset);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseStream(id);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::CloseStream(QuicStreamId stream_id) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DLOG(INFO) << "Closing stream " << stream_id;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReliableStreamMap::iterator it = stream_map_.find(stream_id);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == stream_map_.end()) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(INFO) << "Stream is already closed: " << stream_id;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_map_.erase(it);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool QuicSession::IsHandshakeComplete() {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetCryptoStream()->handshake_complete();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicSession::ActivateStream(ReliableQuicStream* stream) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "num_streams: " << stream_map_.size()
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ". activating " << stream->id();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(stream_map_.count(stream->id()) == 0);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_map_[stream->id()] = stream;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicStreamId QuicSession::GetNextStreamId() {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuicStreamId id = next_stream_id_;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_stream_id_ += 2;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return id;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id == kCryptoStreamId) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetCryptoStream();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReliableStreamMap::iterator it = stream_map_.find(stream_id);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != stream_map_.end()) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return it->second;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id % 2 == next_stream_id_ % 2) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've received a frame for a locally-created stream that is not
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // currently active.  This is an error.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection()->SendConnectionClose(QUIC_PACKET_FOR_NONEXISTENT_STREAM);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetIncomingReliableStream(stream_id);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream* QuicSession::GetIncomingReliableStream(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuicStreamId stream_id) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsClosedStream(stream_id)) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  implicitly_created_streams_.erase(stream_id);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_id > largest_peer_created_stream_id_) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(rch) add unit test for this
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream_id - largest_peer_created_stream_id_ > kMaxStreamIdDelta) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (largest_peer_created_stream_id_ != 0) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (QuicStreamId id = largest_peer_created_stream_id_ + 2;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           id < stream_id;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           id += 2) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        implicitly_created_streams_.insert(id);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    largest_peer_created_stream_id_ = stream_id;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReliableQuicStream* stream = CreateIncomingReliableStream(stream_id);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream == NULL) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection()->SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActivateStream(stream);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return stream;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool QuicSession::IsClosedStream(QuicStreamId id) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(0u, id);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id == kCryptoStreamId) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stream_map_.count(id) != 0) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Stream is active
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id % 2 == next_stream_id_ % 2) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Locally created streams are strictly in-order.  If the id is in the
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // range of created streams and it's not active, it must have been closed.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return id < next_stream_id_;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For peer created streams, we also need to consider implicitly created
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // streams.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return id <= largest_peer_created_stream_id_ &&
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        implicitly_created_streams_.count(id) == 0;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t QuicSession::GetNumOpenStreams() {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return stream_map_.size() + implicitly_created_streams_.size();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
194