blob: 34bf4461243beb06d0009d8320bfecc3f0415c1c [file] [log] [blame]
// Copyright (c) 2018 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_HTTP_QUIC_SPDY_STREAM_BODY_MANAGER_H_
#define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_MANAGER_H_
#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/quic_constants.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"
#include "quiche/quic/platform/api/quic_export.h"
#include "quiche/common/platform/api/quiche_iovec.h"
#include "quiche/common/quiche_circular_deque.h"
namespace quic {
// All data that a request stream receives falls into one of two categories:
// * "body", that is, DATA frame payload, which the QuicStreamSequencer must
// buffer until it is read;
// * everything else, which QuicSpdyStream immediately processes and thus could
// be marked as consumed with QuicStreamSequencer, unless there is some piece
// of body received prior that still needs to be buffered.
// QuicSpdyStreamBodyManager does two things: it keeps references to body
// fragments (owned by QuicStreamSequencer) and offers methods to read them; and
// it calculates the total number of bytes (including non-body bytes) the caller
// needs to mark consumed (with QuicStreamSequencer) when non-body bytes are
// received or when body is consumed.
class QUIC_EXPORT_PRIVATE QuicSpdyStreamBodyManager {
public:
QuicSpdyStreamBodyManager();
~QuicSpdyStreamBodyManager() = default;
// One of the following two methods must be called every time data is received
// on the request stream.
// Called when data that could immediately be marked consumed with the
// sequencer (provided that all previous body fragments are consumed) is
// received. |length| must be positive. Returns number of bytes the caller
// must mark consumed, which might be zero.
ABSL_MUST_USE_RESULT size_t OnNonBody(QuicByteCount length);
// Called when body is received. |body| is added to |fragments_|. The data
// pointed to by |body| must be kept alive until an OnBodyConsumed() or
// ReadBody() call consumes it. |body| must not be empty.
void OnBody(absl::string_view body);
// Internally marks |num_bytes| of body consumed. |num_bytes| might be zero.
// Returns the number of bytes that the caller should mark consumed with the
// sequencer, which is the sum of |num_bytes| for body, and the number of any
// interleaving or immediately trailing non-body bytes.
ABSL_MUST_USE_RESULT size_t OnBodyConsumed(size_t num_bytes);
// Set up to |iov_len| elements of iov[] to point to available bodies: each
// iov[i].iov_base will point to a body fragment, and iov[i].iov_len will be
// set to its length. No data is copied, no data is consumed. Returns the
// number of iov set.
int PeekBody(iovec* iov, size_t iov_len) const;
// Copies data from available bodies into at most |iov_len| elements of iov[].
// Internally consumes copied body bytes as well as all interleaving and
// immediately trailing non-body bytes. |iov.iov_base| and |iov.iov_len| are
// preassigned and will not be changed. Returns the total number of bytes the
// caller shall mark consumed. Sets |*total_bytes_read| to the total number
// of body bytes read.
ABSL_MUST_USE_RESULT size_t ReadBody(const struct iovec* iov, size_t iov_len,
size_t* total_bytes_read);
bool HasBytesToRead() const { return !fragments_.empty(); }
uint64_t total_body_bytes_received() const {
return total_body_bytes_received_;
}
private:
// A Fragment instance represents a body fragment with a count of bytes
// received afterwards but before the next body fragment that can be marked
// consumed as soon as all of the body fragment is read.
struct QUIC_EXPORT_PRIVATE Fragment {
// |body| must not be empty.
absl::string_view body;
// Might be zero.
QuicByteCount trailing_non_body_byte_count;
};
// Queue of body fragments and trailing non-body byte counts.
quiche::QuicheCircularDeque<Fragment> fragments_;
// Total body bytes received.
QuicByteCount total_body_bytes_received_;
};
} // namespace quic
#endif // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_MANAGER_H_