[email protected] | 9c0b135 | 2012-11-04 00:03:27 | [diff] [blame^] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "net/quic/reliable_quic_stream.h" |
| 6 | |
| 7 | #include "net/quic/quic_session.h" |
| 8 | |
| 9 | using base::StringPiece; |
| 10 | |
| 11 | namespace net { |
| 12 | |
| 13 | ReliableQuicStream::ReliableQuicStream(QuicStreamId id, |
| 14 | QuicSession* session) |
| 15 | : sequencer_(this), |
| 16 | id_(id), |
| 17 | offset_(0), |
| 18 | session_(session), |
| 19 | error_(QUIC_NO_ERROR), |
| 20 | read_side_closed_(false), |
| 21 | write_side_closed_(false) { |
| 22 | } |
| 23 | |
| 24 | ReliableQuicStream::~ReliableQuicStream() { |
| 25 | } |
| 26 | |
| 27 | bool ReliableQuicStream::WillAcceptStreamFrame( |
| 28 | const QuicStreamFrame& frame) const { |
| 29 | if (read_side_closed_) { |
| 30 | return false; |
| 31 | } |
| 32 | if (frame.stream_id != id_) { |
| 33 | LOG(ERROR) << "Error!"; |
| 34 | return false; |
| 35 | } |
| 36 | return sequencer_.WillAcceptStreamFrame(frame); |
| 37 | } |
| 38 | |
| 39 | bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) { |
| 40 | DCHECK_EQ(frame.stream_id, id_); |
| 41 | if (read_side_closed_) { |
| 42 | // This can only happen if a client sends data after sending a fin or stream |
| 43 | // reset. |
| 44 | Close(QUIC_STREAM_DATA_AFTER_TERMINATION); |
| 45 | return false; |
| 46 | } |
| 47 | |
| 48 | bool accepted = sequencer_.OnStreamFrame(frame); |
| 49 | |
| 50 | if (frame.fin) { |
| 51 | sequencer_.CloseStreamAtOffset(frame.offset + frame.data.size(), |
| 52 | true); |
| 53 | } |
| 54 | |
| 55 | return accepted; |
| 56 | } |
| 57 | |
| 58 | void ReliableQuicStream::OnStreamReset(QuicErrorCode error, |
| 59 | QuicStreamOffset offset) { |
| 60 | error_ = error; |
| 61 | sequencer_.CloseStreamAtOffset(offset, false); // Full close |
| 62 | } |
| 63 | |
| 64 | void ReliableQuicStream::ConnectionClose(QuicErrorCode error, bool from_peer) { |
| 65 | error_ = error; |
| 66 | if (from_peer) { |
| 67 | TerminateFromPeer(false); |
| 68 | } else { |
| 69 | CloseWriteSide(); |
| 70 | CloseReadSide(); |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | void ReliableQuicStream::TerminateFromPeer(bool half_close) { |
| 75 | if (!half_close) { |
| 76 | CloseWriteSide(); |
| 77 | } |
| 78 | CloseReadSide(); |
| 79 | } |
| 80 | |
| 81 | void ReliableQuicStream::Close(QuicErrorCode error) { |
| 82 | error_ = error; |
| 83 | session()->SendRstStream(id(), error, offset_); |
| 84 | } |
| 85 | |
| 86 | bool ReliableQuicStream::IsHalfClosed() { |
| 87 | return sequencer_.IsHalfClosed(); |
| 88 | } |
| 89 | |
| 90 | bool ReliableQuicStream::HasBytesToRead() { |
| 91 | return sequencer_.HasBytesToRead(); |
| 92 | } |
| 93 | |
| 94 | int ReliableQuicStream::WriteData(StringPiece data, bool fin) { |
| 95 | if (write_side_closed_) { |
| 96 | DLOG(ERROR) << "Attempt to write when the write side is closed"; |
| 97 | return 0; |
| 98 | } |
| 99 | |
| 100 | session()->WriteData(id(), data, offset_, fin); |
| 101 | offset_ += data.length(); |
| 102 | if (fin) { |
| 103 | CloseWriteSide(); |
| 104 | } |
| 105 | return data.length(); |
| 106 | } |
| 107 | |
| 108 | void ReliableQuicStream::CloseReadSide() { |
| 109 | DLOG(INFO) << "Done reading from stream " << id(); |
| 110 | |
| 111 | read_side_closed_ = true; |
| 112 | if (write_side_closed_) { |
| 113 | session_->CloseStream(id()); |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | void ReliableQuicStream::CloseWriteSide() { |
| 118 | DLOG(INFO) << "Done writing to stream " << id(); |
| 119 | |
| 120 | write_side_closed_ = true; |
| 121 | if (read_side_closed_) { |
| 122 | session_->CloseStream(id()); |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | } // namespace net |