1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef QUICHE_QUIC_CORE_QUIC_STREAM_SEQUENCER_H_
#define QUICHE_QUIC_CORE_QUIC_STREAM_SEQUENCER_H_
#include <cstddef>
#include <map>
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
namespace quic {
namespace test {
class QuicStreamSequencerPeer;
} // namespace test
// Buffers frames until we have something which can be passed
// up to the next layer.
class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
public:
// Interface that thie Sequencer uses to communicate with the Stream.
class QUIC_EXPORT_PRIVATE StreamInterface {
public:
virtual ~StreamInterface() = default;
// Called when new data is available to be read from the sequencer.
virtual void OnDataAvailable() = 0;
// Called when the end of the stream has been read.
virtual void OnFinRead() = 0;
// Called when bytes have been consumed from the sequencer.
virtual void AddBytesConsumed(QuicByteCount bytes) = 0;
// TODO(rch): Clean up this interface via OnUnrecoverableError and
// remove PeerAddressOfLatestPacket().
// Called when an error has occurred which should result in the stream
// being reset.
virtual void Reset(QuicRstStreamErrorCode error) = 0;
// Called when an error has occurred which should result in the connection
// being closed.
virtual void CloseConnectionWithDetails(QuicErrorCode error,
const std::string& details) = 0;
// Returns the stream id of this stream.
virtual QuicStreamId id() const = 0;
// Returns the peer address of the last packet received for this stream.
virtual const QuicSocketAddress& PeerAddressOfLatestPacket() const = 0;
};
explicit QuicStreamSequencer(StreamInterface* quic_stream);
QuicStreamSequencer(const QuicStreamSequencer&) = delete;
QuicStreamSequencer(QuicStreamSequencer&&) = default;
QuicStreamSequencer& operator=(const QuicStreamSequencer&) = delete;
virtual ~QuicStreamSequencer();
// If the frame is the next one we need in order to process in-order data,
// ProcessData will be immediately called on the stream until all buffered
// data is processed or the stream fails to consume data. Any unconsumed
// data will be buffered. If the frame is not the next in line, it will be
// buffered.
void OnStreamFrame(const QuicStreamFrame& frame);
// If the frame is the next one we need in order to process in-order data,
// ProcessData will be immediately called on the crypto stream until all
// buffered data is processed or the crypto stream fails to consume data. Any
// unconsumed data will be buffered. If the frame is not the next in line, it
// will be buffered.
void OnCryptoFrame(const QuicCryptoFrame& frame);
// Once data is buffered, it's up to the stream to read it when the stream
// can handle more data. The following three functions make that possible.
// Fills in up to iov_len iovecs with the next readable regions. Returns the
// number of iovs used. Non-destructive of the underlying data.
int GetReadableRegions(iovec* iov, size_t iov_len) const;
// Fills in one iovec with the next readable region. Returns false if there
// is no readable region available.
bool GetReadableRegion(iovec* iov) const;
// Fills in one iovec with the region starting at |offset| and returns true.
// Returns false if no readable region is available, either because data has
// not been received yet or has already been consumed.
bool PeekRegion(QuicStreamOffset offset, iovec* iov) const;
// Copies the data into the iov_len buffers provided. Returns the number of
// bytes read. Any buffered data no longer in use will be released.
// TODO(rch): remove this method and instead implement it as a helper method
// based on GetReadableRegions and MarkConsumed.
int Readv(const struct iovec* iov, size_t iov_len);
// Consumes |num_bytes| data. Used in conjunction with |GetReadableRegions|
// to do zero-copy reads.
void MarkConsumed(size_t num_bytes);
// Appends all of the readable data to |buffer| and marks all of the appended
// data as consumed.
void Read(std::string* buffer);
// Returns true if the sequncer has bytes available for reading.
bool HasBytesToRead() const;
// Number of bytes available to read.
size_t ReadableBytes() const;
// Returns true if the sequencer has delivered the fin.
bool IsClosed() const;
// Calls |OnDataAvailable| on |stream_| if there is buffered data that can
// be processed, and causes |OnDataAvailable| to be called as new data
// arrives.
void SetUnblocked();
// Blocks processing of frames until |SetUnblocked| is called.
void SetBlockedUntilFlush();
// Sets the sequencer to discard all incoming data itself and not call
// |stream_->OnDataAvailable()|. |stream_->OnFinRead()| will be called
// automatically when the FIN is consumed (which may be immediately).
void StopReading();
// Free the memory of underlying buffer.
void ReleaseBuffer();
// Free the memory of underlying buffer when no bytes remain in it.
void ReleaseBufferIfEmpty();
// Number of bytes in the buffer right now.
size_t NumBytesBuffered() const;
// Number of bytes has been consumed.
QuicStreamOffset NumBytesConsumed() const;
QuicStreamOffset close_offset() const { return close_offset_; }
int num_frames_received() const { return num_frames_received_; }
int num_duplicate_frames_received() const {
return num_duplicate_frames_received_;
}
bool ignore_read_data() const { return ignore_read_data_; }
void set_level_triggered(bool level_triggered) {
level_triggered_ = level_triggered;
}
bool level_triggered() const { return level_triggered_; }
void set_stream(StreamInterface* stream) { stream_ = stream; }
// Returns string describing internal state.
const std::string DebugString() const;
private:
friend class test::QuicStreamSequencerPeer;
// Deletes and records as consumed any buffered data that is now in-sequence.
// (To be called only after StopReading has been called.)
void FlushBufferedFrames();
// Wait until we've seen 'offset' bytes, and then terminate the stream.
// Returns true if |stream_| is still available to receive data, and false if
// |stream_| is reset.
bool CloseStreamAtOffset(QuicStreamOffset offset);
// If we've received a FIN and have processed all remaining data, then inform
// the stream of FIN, and clear buffers.
void MaybeCloseStream();
// Shared implementation between OnStreamFrame and OnCryptoFrame.
void OnFrameData(QuicStreamOffset byte_offset,
size_t data_len,
const char* data_buffer);
// The stream which owns this sequencer.
StreamInterface* stream_;
// Stores received data in offset order.
QuicStreamSequencerBuffer buffered_frames_;
// The highest offset that is received so far.
QuicStreamOffset highest_offset_;
// The offset, if any, we got a stream termination for. When this many bytes
// have been processed, the sequencer will be closed.
QuicStreamOffset close_offset_;
// If true, the sequencer is blocked from passing data to the stream and will
// buffer all new incoming data until FlushBufferedFrames is called.
bool blocked_;
// Count of the number of frames received.
int num_frames_received_;
// Count of the number of duplicate frames received.
int num_duplicate_frames_received_;
// If true, all incoming data will be discarded.
bool ignore_read_data_;
// If false, only call OnDataAvailable() when it becomes newly unblocked.
// Otherwise, call OnDataAvailable() when number of readable bytes changes.
bool level_triggered_;
// Latched value of quic_stop_reading_when_level_triggered flag. When true,
// the sequencer will discard incoming data (but not FIN bits) after
// StopReading is called, even in level_triggered_ mode.
const bool stop_reading_when_level_triggered_;
// Latched value of quic_close_connection_and_discard_data_on_wrong_offset.
// When true, the sequencer will inform the stream to close connection when
// wrong offset is received. And the stream frame's data will be discarded.
const bool close_connection_and_discard_data_on_wrong_offset_;
};
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_STREAM_SEQUENCER_H_
|