reliable_quic_stream.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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/reliable_quic_stream.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_session.h"
8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/quic/quic_spdy_decompressor.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece;
11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using std::min;
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream::ReliableQuicStream(QuicStreamId id,
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       QuicSession* session)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : sequencer_(this),
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      id_(id),
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_(session),
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      visitor_(NULL),
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream_bytes_read_(0),
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream_bytes_written_(0),
23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      headers_decompressed_(false),
24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      headers_id_(0),
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      stream_error_(QUIC_STREAM_NO_ERROR),
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      connection_error_(QUIC_NO_ERROR),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_side_closed_(false),
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      write_side_closed_(false),
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin_buffered_(false),
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin_sent_(false) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream::~ReliableQuicStream() {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReliableQuicStream::WillAcceptStreamFrame(
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const QuicStreamFrame& frame) const {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_side_closed_) {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame.stream_id != id_) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Error!";
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sequencer_.WillAcceptStreamFrame(frame);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(frame.stream_id, id_);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_side_closed_) {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(INFO) << "Ignoring frame " << frame.stream_id;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We don't want to be reading: blackhole the data.
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note: This count include duplicate data received.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream_bytes_read_ += frame.data.length();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool accepted = sequencer_.OnStreamFrame(frame);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame.fin) {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sequencer_.CloseStreamAtOffset(frame.offset + frame.data.size(), true);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return accepted;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ReliableQuicStream::OnStreamReset(QuicRstStreamErrorCode error) {
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream_error_ = error;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TerminateFromPeer(false);  // Full close.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReliableQuicStream::ConnectionClose(QuicErrorCode error, bool from_peer) {
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsClosed()) {
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != QUIC_NO_ERROR) {
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    stream_error_ = QUIC_STREAM_CONNECTION_ERROR;
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    connection_error_ = error;
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (from_peer) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TerminateFromPeer(false);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseWriteSide();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseReadSide();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReliableQuicStream::TerminateFromPeer(bool half_close) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!half_close) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseWriteSide();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseReadSide();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ReliableQuicStream::Close(QuicRstStreamErrorCode error) {
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream_error_ = error;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session()->SendRstStream(id(), error);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)int ReliableQuicStream::Readv(const struct iovec* iov, int iov_len) {
102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_decompressed_ && decompressed_headers_.empty()) {
103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return sequencer_.Readv(iov, iov_len);
104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  size_t bytes_consumed = 0;
106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  int iov_index = 0;
107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  while (iov_index < iov_len &&
108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)         decompressed_headers_.length() > bytes_consumed) {
109b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    int bytes_to_read = min(iov[iov_index].iov_len,
110b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                            decompressed_headers_.length() - bytes_consumed);
111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base);
112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    memcpy(iov_ptr,
113b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)           decompressed_headers_.data() + bytes_consumed, bytes_to_read);
114b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bytes_consumed += bytes_to_read;
115b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    ++iov_index;
116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
117b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  decompressed_headers_.erase(0, bytes_consumed);
118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return bytes_consumed;
119b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
121b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)int ReliableQuicStream::GetReadableRegions(iovec* iov, int iov_len) {
122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_decompressed_ && decompressed_headers_.empty()) {
123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return sequencer_.GetReadableRegions(iov, iov_len);
124b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
125b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (iov_len == 0) {
126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return 0;
127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
128b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  iov[0].iov_base = static_cast<void*>(
129b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      const_cast<char*>(decompressed_headers_.data()));
130b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  iov[0].iov_len = decompressed_headers_.length();
131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return 1;
132b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReliableQuicStream::IsHalfClosed() const {
135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!headers_decompressed_ || !decompressed_headers_.empty()) {
136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sequencer_.IsHalfClosed();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ReliableQuicStream::IsClosed() const {
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return write_side_closed_ && (read_side_closed_ || IsHalfClosed());
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReliableQuicStream::HasBytesToRead() const {
146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return !decompressed_headers_.empty() || sequencer_.HasBytesToRead();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const IPEndPoint& ReliableQuicStream::GetPeerAddress() const {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return session_->peer_address();
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicSpdyCompressor* ReliableQuicStream::compressor() {
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return session_->compressor();
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicConsumedData ReliableQuicStream::WriteData(StringPiece data, bool fin) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return WriteOrBuffer(data, fin);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicConsumedData ReliableQuicStream::WriteOrBuffer(StringPiece data, bool fin) {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!fin_buffered_);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicConsumedData consumed_data(0, false);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fin_buffered_ = fin;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (queued_data_.empty()) {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    consumed_data = WriteDataInternal(string(data.data(), data.length()), fin);
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_LE(consumed_data.bytes_consumed, data.length());
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there's unconsumed data or an unconsumed fin, queue it.
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (consumed_data.bytes_consumed < data.length() ||
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (fin && !consumed_data.fin_consumed)) {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    queued_data_.push_back(
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        string(data.data() + consumed_data.bytes_consumed,
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               data.length() - consumed_data.bytes_consumed));
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return QuicConsumedData(data.size(), true);
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReliableQuicStream::OnCanWrite() {
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool fin = false;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!queued_data_.empty()) {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const string& data = queued_data_.front();
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (queued_data_.size() == 1 && fin_buffered_) {
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin = true;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    QuicConsumedData consumed_data = WriteDataInternal(data, fin);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (consumed_data.bytes_consumed == data.size() &&
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fin == consumed_data.fin_consumed) {
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      queued_data_.pop_front();
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      queued_data_.front().erase(0, consumed_data.bytes_consumed);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicConsumedData ReliableQuicStream::WriteDataInternal(
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StringPiece data, bool fin) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (write_side_closed_) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Attempt to write when the write side is closed";
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return QuicConsumedData(0, false);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicConsumedData consumed_data =
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session()->WriteData(id(), data, stream_bytes_written_, fin);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream_bytes_written_ += consumed_data.bytes_consumed;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (consumed_data.bytes_consumed == data.length()) {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (fin && consumed_data.fin_consumed) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin_sent_ = true;
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CloseWriteSide();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_->MarkWriteBlocked(id());
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return consumed_data;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReliableQuicStream::CloseReadSide() {
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (read_side_closed_) {
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DLOG(INFO) << "Done reading from stream " << id();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_side_closed_ = true;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (write_side_closed_) {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(INFO) << "Closing stream: " << id();
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_->CloseStream(id());
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) {
236b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (id() == kCryptoStreamId) {
237b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // The crypto stream does not use compression.
238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return ProcessData(data, data_len);
239b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  uint32 total_bytes_consumed = 0;
241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_id_ == 0u) {
242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // The headers ID has not yet been read.  Strip it from the beginning of
243b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // the data stream.
244b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    DCHECK_GT(4u, headers_id_buffer_.length());
245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    size_t missing_size = 4 - headers_id_buffer_.length();
246b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (data_len < missing_size) {
247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      StringPiece(data, data_len).AppendToString(&headers_id_buffer_);
248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return data_len;
249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    total_bytes_consumed += missing_size;
251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    StringPiece(data, missing_size).AppendToString(&headers_id_buffer_);
252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    DCHECK_EQ(4u, headers_id_buffer_.length());
253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    memcpy(&headers_id_, headers_id_buffer_.data(), 4);
254b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    headers_id_buffer_.clear();
255b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    data += missing_size;
256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    data_len -= missing_size;
257b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
258b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK_NE(0u, headers_id_);
259b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
260b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Once the headers are finished, we simply pass the data through.
261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_decompressed_) {
262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // Some buffered header data remains.
263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!decompressed_headers_.empty()) {
264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      ProcessHeaderData();
265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (decompressed_headers_.empty()) {
267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      DVLOG(1) << "Delegating procesing to ProcessData";
268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      total_bytes_consumed += ProcessData(data, data_len);
269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return total_bytes_consumed;
271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  QuicHeaderId current_header_id =
274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      session_->decompressor()->current_header_id();
275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Ensure that this header id looks sane.
276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_id_ < current_header_id ||
277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      headers_id_ > kMaxHeaderIdDelta + current_header_id) {
278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    DVLOG(1) << "Invalid headers for stream: " << id()
279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             << " header_id: " << headers_id_
280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             << " current_header_id: " << current_header_id;
281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    session_->connection()->SendConnectionClose(QUIC_INVALID_HEADER_ID);
282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return total_bytes_consumed;
283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // If we are head-of-line blocked on decompression, then back up.
286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (current_header_id != headers_id_) {
287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    session_->MarkDecompressionBlocked(headers_id_, id());
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DVLOG(1) << "Unable to decompress header data for stream: " << id()
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)             << " header_id: " << headers_id_;
290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return total_bytes_consumed;
291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
293b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Decompressed data will be delivered to decompressed_headers_.
294b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  size_t bytes_consumed = session_->decompressor()->DecompressData(
295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      StringPiece(data, data_len), this);
296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  total_bytes_consumed += bytes_consumed;
297b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
298b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Headers are complete if the decompressor has moved on to the
299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // next stream.
300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  headers_decompressed_ =
301b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      session_->decompressor()->current_header_id() != headers_id_;
302b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
303b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProcessHeaderData();
304b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
305b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // We have processed all of the decompressed data but we might
306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // have some more raw data to process.
307b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (decompressed_headers_.empty() || total_bytes_consumed < data_len) {
308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    total_bytes_consumed += ProcessData(data + bytes_consumed,
309b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                        data_len - bytes_consumed);
310b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // The sequencer will push any additional buffered frames if this data
313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // has been completely consumed.
314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return total_bytes_consumed;
315b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
316b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)uint32 ReliableQuicStream::ProcessHeaderData() {
318b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (decompressed_headers_.empty()) {
319b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return 0;
320b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
321b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
322b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  size_t bytes_processed = ProcessData(decompressed_headers_.data(),
323b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                       decompressed_headers_.length());
324b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (bytes_processed == decompressed_headers_.length()) {
325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    decompressed_headers_.clear();
326b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  } else {
327b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    decompressed_headers_ = decompressed_headers_.erase(0, bytes_processed);
328b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return bytes_processed;
330b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ReliableQuicStream::OnDecompressorAvailable() {
333b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK_EQ(headers_id_,
334b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            session_->decompressor()->current_header_id());
335b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(!headers_decompressed_);
336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK_EQ(0u, decompressed_headers_.length());
337b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
338b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  size_t total_bytes_consumed = 0;
339b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  struct iovec iovecs[5];
340b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  while (!headers_decompressed_) {
341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    size_t num_iovecs =
342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        sequencer_.GetReadableRegions(iovecs, arraysize(iovecs));
343b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
344b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (num_iovecs == 0) {
345b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return;
346b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
347b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    for (size_t i = 0; i < num_iovecs && !headers_decompressed_; i++) {
348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      total_bytes_consumed += session_->decompressor()->DecompressData(
349b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          StringPiece(static_cast<char*>(iovecs[i].iov_base),
350b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                      iovecs[i].iov_len), this);
351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
352b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      headers_decompressed_ =
353b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          session_->decompressor()->current_header_id() != headers_id_;
354b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
356b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
357b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Either the headers are complete, or the all data as been consumed.
358b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  sequencer_.MarkConsumed(total_bytes_consumed);
359b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
360b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProcessHeaderData();  // Unprocessed headers remain in decompressed_headers_.
361b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
362b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_decompressed_ && decompressed_headers_.empty()) {
363b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    sequencer_.FlushBufferedFrames();
364b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
365b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
366b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
367b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool ReliableQuicStream::OnDecompressedData(StringPiece data) {
368b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  data.AppendToString(&decompressed_headers_);
369b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return true;
370b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
371b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ReliableQuicStream::OnDecompressionError() {
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  session_->connection()->SendConnectionClose(QUIC_DECOMPRESSION_FAILURE);
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReliableQuicStream::CloseWriteSide() {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (write_side_closed_) {
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DLOG(INFO) << "Done writing to stream " << id();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_side_closed_ = true;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_side_closed_) {
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(INFO) << "Closing stream: " << id();
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_->CloseStream(id());
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReliableQuicStream::OnClose() {
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CloseReadSide();
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CloseWriteSide();
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (visitor_) {
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Visitor* visitor = visitor_;
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Calling Visitor::OnClose() may result the destruction of the visitor,
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // so we need to ensure we don't call it again.
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    visitor_ = NULL;
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    visitor->OnClose(this);
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
404