blob: db1b123fb54ab2a684fe5ed6fb2a5e07bbdb13da [file] [log] [blame]
// Copyright 2013 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 NET_QUIC_QUIC_HEADERS_STREAM_H_
#define NET_QUIC_QUIC_HEADERS_STREAM_H_
#include <stddef.h>
#include <memory>
#include "base/macros.h"
#include "net/base/net_export.h"
#include "net/quic/core/quic_header_list.h"
#include "net/quic/core/quic_protocol.h"
#include "net/quic/core/reliable_quic_stream.h"
#include "net/spdy/spdy_framer.h"
namespace net {
class QuicSpdySession;
namespace test {
class QuicHeadersStreamPeer;
} // namespace test
// Headers in QUIC are sent as HTTP/2 HEADERS or PUSH_PROMISE frames
// over a reserved reliable stream with the id 3. Each endpoint
// (client and server) will allocate an instance of QuicHeadersStream
// to send and receive headers.
class NET_EXPORT_PRIVATE QuicHeadersStream : public ReliableQuicStream {
public:
class NET_EXPORT_PRIVATE HpackDebugVisitor {
public:
HpackDebugVisitor();
virtual ~HpackDebugVisitor();
// For each HPACK indexed representation processed, |elapsed| is
// the time since the corresponding entry was added to the dynamic
// table.
virtual void OnUseEntry(QuicTime::Delta elapsed) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(HpackDebugVisitor);
};
explicit QuicHeadersStream(QuicSpdySession* session);
~QuicHeadersStream() override;
// Writes |headers| for |stream_id| in an HTTP/2 HEADERS frame to the peer.
// If |fin| is true, the fin flag will be set on the HEADERS frame. Returns
// the size, in bytes, of the resulting HEADERS frame.
virtual size_t WriteHeaders(QuicStreamId stream_id,
SpdyHeaderBlock headers,
bool fin,
SpdyPriority priority,
QuicAckListenerInterface* ack_listener);
// Write |headers| for |promised_stream_id| on |original_stream_id| in a
// PUSH_PROMISE frame to peer.
// Return the size, in bytes, of the resulting PUSH_PROMISE frame.
virtual size_t WritePushPromise(QuicStreamId original_stream_id,
QuicStreamId promised_stream_id,
SpdyHeaderBlock headers);
// For forcing HOL blocking. This encapsulates data from other
// streams into HTTP/2 data frames on the headers stream.
QuicConsumedData WritevStreamData(
QuicStreamId id,
QuicIOVector iov,
QuicStreamOffset offset,
bool fin,
QuicAckListenerInterface* ack_notifier_delegate);
// ReliableQuicStream implementation
void OnDataAvailable() override;
bool supports_push_promise() { return supports_push_promise_; }
// Experimental: force HPACK to use static table and huffman coding
// only. Part of exploring improvements related to headers stream
// induced HOL blocking in QUIC.
void DisableHpackDynamicTable();
// Optional, enables instrumentation related to go/quic-hpack.
void SetHpackEncoderDebugVisitor(std::unique_ptr<HpackDebugVisitor> visitor);
void SetHpackDecoderDebugVisitor(std::unique_ptr<HpackDebugVisitor> visitor);
// Sets the maximum size of the header compression table spdy_framer_ is
// willing to use to decode header blocks.
void UpdateHeaderEncoderTableSize(uint32_t value);
// Sets how much encoded data the hpack decoder of spdy_framer_ is willing to
// buffer.
void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) {
spdy_framer_.set_max_decode_buffer_size_bytes(max_decode_buffer_size_bytes);
}
private:
friend class test::QuicHeadersStreamPeer;
class SpdyFramerVisitor;
// The following methods are called by the SimpleVisitor.
// Called when a HEADERS frame has been received.
void OnHeaders(SpdyStreamId stream_id,
bool has_priority,
SpdyPriority priority,
bool fin);
// Called when a PUSH_PROMISE frame has been received.
void OnPushPromise(SpdyStreamId stream_id,
SpdyStreamId promised_stream_id,
bool end);
// Called when a chunk of header data is available. This is called
// after OnHeaders.
// |stream_id| The stream receiving the header data.
// |header_data| A buffer containing the header data chunk received.
// |len| The length of the header data buffer. A length of zero indicates
// that the header data block has been completely sent.
void OnControlFrameHeaderData(SpdyStreamId stream_id,
const char* header_data,
size_t len);
// Called when the complete list of headers is available.
void OnHeaderList(const QuicHeaderList& header_list);
// Called when the size of the compressed frame payload is available.
void OnCompressedFrameSize(size_t frame_len);
// For force HOL blocking, where stream frames from all streams are
// plumbed through headers stream as HTTP/2 data frames. Return false
// if force_hol_blocking_ is false;
bool OnDataFrameHeader(QuicStreamId stream_id, size_t length, bool fin);
bool OnStreamFrameData(QuicStreamId stream_id, const char* data, size_t len);
// Returns true if the session is still connected.
bool IsConnected();
QuicSpdySession* spdy_session_;
// Data about the stream whose headers are being processed.
QuicStreamId stream_id_;
QuicStreamId promised_stream_id_;
bool fin_;
size_t frame_len_;
size_t uncompressed_frame_len_;
bool supports_push_promise_;
// Timestamps used to measure HOL blocking, these are recorded by
// the sequencer approximate to the time of arrival off the wire.
// |cur_max_timestamp_| tracks the most recent arrival time of
// frames for current (at the headers stream level) processed
// stream's headers, and |prev_max_timestamp_| tracks the most
// recent arrival time of lower numbered streams.
QuicTime cur_max_timestamp_;
QuicTime prev_max_timestamp_;
SpdyFramer spdy_framer_;
std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
// Either empty, or contains the complete list of headers.
QuicHeaderList header_list_;
DISALLOW_COPY_AND_ASSIGN(QuicHeadersStream);
};
} // namespace net
#endif // NET_QUIC_QUIC_HEADERS_STREAM_H_