Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Unified Diff: net/quic/core/quic_spdy_session.cc

Issue 2607873002: QUIC - refactor in preparation for two streams per HTTP transaction. (Closed)
Patch Set: Fixed namespaces and formatting. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/core/quic_spdy_session.h ('k') | net/quic/core/quic_spdy_stream.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/core/quic_spdy_session.cc
diff --git a/net/quic/core/quic_spdy_session.cc b/net/quic/core/quic_spdy_session.cc
index e3fd1ea8e68bd366494269ec3080124ee6d988b5..cff601ed7c06c9c810980ae4aca5c2b5263e2f34 100644
--- a/net/quic/core/quic_spdy_session.cc
+++ b/net/quic/core/quic_spdy_session.cc
@@ -8,18 +8,322 @@
#include "net/quic/core/quic_bug_tracker.h"
#include "net/quic/core/quic_headers_stream.h"
+#include "net/quic/platform/api/quic_str_cat.h"
using base::StringPiece;
using std::string;
namespace net {
+namespace {
+
+class HeaderTableDebugVisitor
+ : public HpackHeaderTable::DebugVisitorInterface {
+ public:
+ HeaderTableDebugVisitor(const QuicClock* clock,
+ std::unique_ptr<QuicHpackDebugVisitor> visitor)
+ : clock_(clock), headers_stream_hpack_visitor_(std::move(visitor)) {}
+
+ int64_t OnNewEntry(const HpackEntry& entry) override {
+ DVLOG(1) << entry.GetDebugString();
+ return (clock_->ApproximateNow() - QuicTime::Zero()).ToMicroseconds();
+ }
+
+ void OnUseEntry(const HpackEntry& entry) override {
+ const QuicTime::Delta elapsed(
+ clock_->ApproximateNow() -
+ QuicTime::Delta::FromMicroseconds(entry.time_added()) -
+ QuicTime::Zero());
+ DVLOG(1) << entry.GetDebugString() << " " << elapsed.ToMilliseconds()
+ << " ms";
+ headers_stream_hpack_visitor_->OnUseEntry(elapsed);
+ }
+
+ private:
+ const QuicClock* clock_;
+ std::unique_ptr<QuicHpackDebugVisitor> headers_stream_hpack_visitor_;
+
+ DISALLOW_COPY_AND_ASSIGN(HeaderTableDebugVisitor);
+};
+
+// When forced HOL blocking is enabled, extra bytes in the form of
+// HTTP/2 DATA frame headers are inserted on the way down to the
+// session layer. |ForceAckListener| filters the |OnPacketAcked()|
+// notifications generated by the session layer to not count the extra
+// bytes. Otherwise, code that is using ack listener on streams might
+// consider it an error if more bytes are acked than were written to
+// the stream, it is the case with some internal stats gathering code.
+class ForceHolAckListener : public QuicAckListenerInterface {
+ public:
+ // |extra_bytes| should be initialized to the size of the HTTP/2
+ // DATA frame header inserted when forced HOL blocking is enabled.
+ ForceHolAckListener(
+ QuicReferenceCountedPointer<QuicAckListenerInterface> stream_ack_listener,
+ int extra_bytes)
+ : stream_ack_listener_(std::move(stream_ack_listener)),
+ extra_bytes_(extra_bytes) {
+ DCHECK_GE(extra_bytes, 0);
+ }
+
+ void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override {
+ if (extra_bytes_ > 0) {
+ // Don't count the added HTTP/2 DATA frame header bytes
+ int delta = std::min(extra_bytes_, acked_bytes);
+ extra_bytes_ -= delta;
+ acked_bytes -= delta;
+ }
+ stream_ack_listener_->OnPacketAcked(acked_bytes, ack_delay_time);
+ }
+
+ void OnPacketRetransmitted(int retransmitted_bytes) override {
+ stream_ack_listener_->OnPacketRetransmitted(retransmitted_bytes);
+ }
+
+ protected:
+ ~ForceHolAckListener() override {}
+
+ private:
+ QuicReferenceCountedPointer<QuicAckListenerInterface> stream_ack_listener_;
+ int extra_bytes_;
+
+ DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener);
+};
+
+} // namespace
+
+// A SpdyFramerVisitor that passes HEADERS frames to the QuicSpdyStream, and
+// closes the connection if any unexpected frames are received.
+class QuicSpdySession::SpdyFramerVisitor
+ : public SpdyFramerVisitorInterface,
+ public SpdyFramerDebugVisitorInterface {
+ public:
+ explicit SpdyFramerVisitor(QuicSpdySession* session) : session_(session) {}
+
+ SpdyHeadersHandlerInterface* OnHeaderFrameStart(
+ SpdyStreamId /* stream_id */) override {
+ return &header_list_;
+ }
+
+ void OnHeaderFrameEnd(SpdyStreamId /* stream_id */,
+ bool end_headers) override {
+ if (end_headers) {
+ if (session_->IsConnected()) {
+ session_->OnHeaderList(header_list_);
+ }
+ header_list_.Clear();
+ }
+ }
+
+ void OnStreamFrameData(SpdyStreamId stream_id,
+ const char* data,
+ size_t len) override {
+ if (session_->OnStreamFrameData(stream_id, data, len)) {
+ return;
+ }
+ CloseConnection("SPDY DATA frame received.");
+ }
+
+ void OnStreamEnd(SpdyStreamId stream_id) override {
+ // The framer invokes OnStreamEnd after processing a frame that had the fin
+ // bit set.
+ }
+
+ void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
+ CloseConnection("SPDY frame padding received.");
+ }
+
+ void OnError(SpdyFramer* framer) override {
+ CloseConnection(
+ QuicStrCat("SPDY framing error: ",
+ SpdyFramer::ErrorCodeToString(framer->error_code())));
+ }
+
+ void OnDataFrameHeader(SpdyStreamId stream_id,
+ size_t length,
+ bool fin) override {
+ if (session_->OnDataFrameHeader(stream_id, length, fin)) {
+ return;
+ }
+ CloseConnection("SPDY DATA frame received.");
+ }
+
+ void OnRstStream(SpdyStreamId stream_id,
+ SpdyRstStreamStatus status) override {
+ CloseConnection("SPDY RST_STREAM frame received.");
+ }
+
+ void OnSetting(SpdySettingsIds id, uint32_t value) override {
+ if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
+ CloseConnection("SPDY SETTINGS frame received.");
+ return;
+ }
+ switch (id) {
+ case SETTINGS_HEADER_TABLE_SIZE:
+ session_->UpdateHeaderEncoderTableSize(value);
+ break;
+ case SETTINGS_ENABLE_PUSH:
+ if (FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default &&
+ session_->perspective() == Perspective::IS_SERVER) {
+ // See rfc7540, Section 6.5.2.
+ if (value > 1) {
+ CloseConnection(
+ QuicStrCat("Invalid value for SETTINGS_ENABLE_PUSH: ", value));
+ return;
+ }
+ session_->UpdateEnableServerPush(value > 0);
+ break;
+ } else {
+ CloseConnection(
+ QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
+ }
+ break;
+ // TODO(fayang): Need to support SETTINGS_MAX_HEADER_LIST_SIZE when
+ // clients are actually sending it.
+ case SETTINGS_MAX_HEADER_LIST_SIZE:
+ if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size) {
+ break;
+ }
+ default:
+ CloseConnection(
+ QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
+ }
+ }
+
+ void OnSettingsAck() override {
+ if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
+ CloseConnection("SPDY SETTINGS frame received.");
+ }
+ }
+
+ void OnSettingsEnd() override {
+ if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
+ CloseConnection("SPDY SETTINGS frame received.");
+ }
+ }
+
+ void OnPing(SpdyPingId unique_id, bool is_ack) override {
+ CloseConnection("SPDY PING frame received.");
+ }
+
+ void OnGoAway(SpdyStreamId last_accepted_stream_id,
+ SpdyGoAwayStatus status) override {
+ CloseConnection("SPDY GOAWAY frame received.");
+ }
+
+ void OnHeaders(SpdyStreamId stream_id,
+ bool has_priority,
+ int weight,
+ SpdyStreamId /*parent_stream_id*/,
+ bool /*exclusive*/,
+ bool fin,
+ bool end) override {
+ if (!session_->IsConnected()) {
+ return;
+ }
+
+ // TODO(mpw): avoid down-conversion and plumb SpdyStreamPrecedence through
+ // QuicHeadersStream.
+ SpdyPriority priority =
+ has_priority ? Http2WeightToSpdy3Priority(weight) : 0;
+ session_->OnHeaders(stream_id, has_priority, priority, fin);
+ }
+
+ void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
+ CloseConnection("SPDY WINDOW_UPDATE frame received.");
+ }
+
+ void OnPushPromise(SpdyStreamId stream_id,
+ SpdyStreamId promised_stream_id,
+ bool end) override {
+ if (!session_->supports_push_promise()) {
+ CloseConnection("PUSH_PROMISE not supported.");
+ return;
+ }
+ if (!session_->IsConnected()) {
+ return;
+ }
+ session_->OnPushPromise(stream_id, promised_stream_id, end);
+ }
+
+ void OnContinuation(SpdyStreamId stream_id, bool end) override {}
+
+ void OnPriority(SpdyStreamId stream_id,
+ SpdyStreamId parent_id,
+ int weight,
+ bool exclusive) override {
+ CloseConnection("SPDY PRIORITY frame received.");
+ }
+
+ bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
+ CloseConnection("Unknown frame type received.");
+ return false;
+ }
+
+ // SpdyFramerDebugVisitorInterface implementation
+ void OnSendCompressedFrame(SpdyStreamId stream_id,
+ SpdyFrameType type,
+ size_t payload_len,
+ size_t frame_len) override {
+ if (payload_len == 0) {
+ QUIC_BUG << "Zero payload length.";
+ return;
+ }
+ int compression_pct = 100 - (100 * frame_len) / payload_len;
+ DVLOG(1) << "Net.QuicHpackCompressionPercentage: " << compression_pct;
+ }
+
+ void OnReceiveCompressedFrame(SpdyStreamId stream_id,
+ SpdyFrameType type,
+ size_t frame_len) override {
+ if (session_->IsConnected()) {
+ session_->OnCompressedFrameSize(frame_len);
+ }
+ }
+
+ void set_max_uncompressed_header_bytes(
+ size_t set_max_uncompressed_header_bytes) {
+ header_list_.set_max_uncompressed_header_bytes(
+ set_max_uncompressed_header_bytes);
+ }
+
+ private:
+ void CloseConnection(const string& details) {
+ if (session_->IsConnected()) {
+ session_->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
+ details);
+ }
+ }
+
+ private:
+ QuicSpdySession* session_;
+ QuicHeaderList header_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
+};
+
+QuicHpackDebugVisitor::QuicHpackDebugVisitor() {}
+
+QuicHpackDebugVisitor::~QuicHpackDebugVisitor() {}
+
QuicSpdySession::QuicSpdySession(QuicConnection* connection,
QuicSession::Visitor* visitor,
const QuicConfig& config)
: QuicSession(connection, visitor, config),
force_hol_blocking_(false),
- server_push_enabled_(false) {}
+ server_push_enabled_(false),
+ stream_id_(kInvalidStreamId),
+ promised_stream_id_(kInvalidStreamId),
+ fin_(false),
+ frame_len_(0),
+ uncompressed_frame_len_(0),
+ supports_push_promise_(perspective() == Perspective::IS_CLIENT),
+ cur_max_timestamp_(QuicTime::Zero()),
+ prev_max_timestamp_(QuicTime::Zero()),
+ spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
+ spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
+ spdy_framer_.set_visitor(spdy_framer_visitor_.get());
+ spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
+}
QuicSpdySession::~QuicSpdySession() {
// Set the streams' session pointers in closed and dynamic stream lists
@@ -69,6 +373,14 @@ void QuicSpdySession::OnStreamHeaderList(QuicStreamId stream_id,
stream->OnStreamHeaderList(fin, frame_len, header_list);
}
+size_t QuicSpdySession::ProcessHeaderData(const struct iovec& iov,
+ QuicTime timestamp) {
+ DCHECK(timestamp.IsInitialized());
+ UpdateCurMaxTimeStamp(timestamp);
+ return spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base),
+ iov.iov_len);
+}
+
size_t QuicSpdySession::WriteHeaders(
QuicStreamId id,
SpdyHeaderBlock headers,
@@ -76,8 +388,132 @@ size_t QuicSpdySession::WriteHeaders(
SpdyPriority priority,
QuicReferenceCountedPointer<QuicAckListenerInterface>
ack_notifier_delegate) {
- return headers_stream_->WriteHeaders(id, std::move(headers), fin, priority,
- std::move(ack_notifier_delegate));
+ return WriteHeadersImpl(id, std::move(headers), fin, priority,
+ std::move(ack_notifier_delegate));
+}
+
+size_t QuicSpdySession::WriteHeadersImpl(
+ QuicStreamId id,
+ SpdyHeaderBlock headers,
+ bool fin,
+ SpdyPriority priority,
+ QuicReferenceCountedPointer<QuicAckListenerInterface>
+ ack_notifier_delegate) {
+ SpdyHeadersIR headers_frame(id, std::move(headers));
+ headers_frame.set_fin(fin);
+ if (perspective() == Perspective::IS_CLIENT) {
+ headers_frame.set_has_priority(true);
+ headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority));
+ }
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
+ headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
+ false, std::move(ack_notifier_delegate));
+ return frame.size();
+}
+
+size_t QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
+ QuicStreamId promised_stream_id,
+ SpdyHeaderBlock headers) {
+ if (perspective() == Perspective::IS_CLIENT) {
+ QUIC_BUG << "Client shouldn't send PUSH_PROMISE";
+ return 0;
+ }
+
+ SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
+ std::move(headers));
+ // PUSH_PROMISE must not be the last frame sent out, at least followed by
+ // response headers.
+ push_promise.set_fin(false);
+
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
+ headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
+ false, nullptr);
+ return frame.size();
+}
+
+void QuicSpdySession::WriteDataFrame(
+ QuicStreamId id,
+ StringPiece data,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ SpdyDataIR spdy_data(id, data);
+ spdy_data.set_fin(fin);
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
+ QuicReferenceCountedPointer<ForceHolAckListener> force_hol_ack_listener;
+ if (ack_listener != nullptr) {
+ force_hol_ack_listener = new ForceHolAckListener(
+ std::move(ack_listener), frame.size() - data.length());
+ }
+ // Use buffered writes so that coherence of framing is preserved
+ // between streams.
+ headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
+ false, std::move(force_hol_ack_listener));
+}
+
+QuicConsumedData QuicSpdySession::WritevStreamData(
+ QuicStreamId id,
+ QuicIOVector iov,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ const size_t max_len =
+ kSpdyInitialFrameSizeLimit - kDataFrameMinimumSize;
+
+ QuicConsumedData result(0, false);
+ size_t total_length = iov.total_length;
+
+ if (total_length == 0 && fin) {
+ WriteDataFrame(id, StringPiece(), true, std::move(ack_listener));
+ result.fin_consumed = true;
+ return result;
+ }
+
+ // Encapsulate the data into HTTP/2 DATA frames. The outer loop
+ // handles each element of the source iov, the inner loop handles
+ // the possibility of fragmenting each of those into multiple DATA
+ // frames, as the DATA frames have a max size of 16KB.
+ for (int i = 0; i < iov.iov_count; i++) {
+ size_t src_iov_offset = 0;
+ const struct iovec* src_iov = &iov.iov[i];
+ do {
+ if (headers_stream_->queued_data_bytes() > 0) {
+ // Limit the amount of buffering to the minimum needed to
+ // preserve framing.
+ return result;
+ }
+ size_t len = std::min(
+ std::min(src_iov->iov_len - src_iov_offset, max_len), total_length);
+ char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset;
+ src_iov_offset += len;
+ offset += len;
+ // fin handling, only set it for the final HTTP/2 DATA frame.
+ bool last_iov = i == iov.iov_count - 1;
+ bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len;
+ bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
+ WriteDataFrame(id, StringPiece(data, len), frame_fin, ack_listener);
+ result.bytes_consumed += len;
+ if (frame_fin) {
+ result.fin_consumed = true;
+ }
+ DCHECK_GE(total_length, len);
+ total_length -= len;
+ if (total_length <= 0) {
+ return result;
+ }
+ } while (src_iov_offset < src_iov->iov_len);
+ }
+
+ return result;
+}
+
+size_t QuicSpdySession::SendMaxHeaderListSize(size_t value) {
+ SpdySettingsIR settings_frame;
+ settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, value);
+
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame));
+ headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
+ false, nullptr);
+ return frame.size();
}
void QuicSpdySession::OnHeadersHeadOfLineBlocking(QuicTime::Delta delta) {
@@ -107,7 +543,7 @@ void QuicSpdySession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
QuicSession::OnCryptoHandshakeEvent(event);
if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size &&
event == HANDSHAKE_CONFIRMED && config()->SupportMaxHeaderListSize()) {
- headers_stream()->SendMaxHeaderListSize(kDefaultMaxUncompressedHeaderSize);
+ SendMaxHeaderListSize(kDefaultMaxUncompressedHeaderSize);
}
}
@@ -124,7 +560,7 @@ void QuicSpdySession::OnPromiseHeaderList(QuicStreamId stream_id,
void QuicSpdySession::OnConfigNegotiated() {
QuicSession::OnConfigNegotiated();
if (config()->HasClientSentConnectionOption(kDHDT, perspective())) {
- headers_stream_->DisableHpackDynamicTable();
+ DisableHpackDynamicTable();
}
const QuicVersion version = connection()->version();
if (FLAGS_quic_reloadable_flag_quic_enable_force_hol_blocking &&
@@ -167,4 +603,143 @@ bool QuicSpdySession::ShouldReleaseHeadersStreamSequencerBuffer() {
return false;
}
+void QuicSpdySession::OnHeaders(SpdyStreamId stream_id,
+ bool has_priority,
+ SpdyPriority priority,
+ bool fin) {
+ if (has_priority) {
+ if (perspective() == Perspective::IS_CLIENT) {
+ CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "Server must not send priorities.");
+ return;
+ }
+ OnStreamHeadersPriority(stream_id, priority);
+ } else {
+ if (perspective() == Perspective::IS_SERVER) {
+ CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "Client must send priorities.");
+ return;
+ }
+ }
+ DCHECK_EQ(kInvalidStreamId, stream_id_);
+ DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
+ stream_id_ = stream_id;
+ fin_ = fin;
+}
+
+void QuicSpdySession::OnPushPromise(SpdyStreamId stream_id,
+ SpdyStreamId promised_stream_id,
+ bool end) {
+ DCHECK_EQ(kInvalidStreamId, stream_id_);
+ DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
+ stream_id_ = stream_id;
+ promised_stream_id_ = promised_stream_id;
+}
+
+void QuicSpdySession::OnHeaderList(const QuicHeaderList& header_list) {
+ DVLOG(1) << "Received header list for stream " << stream_id_ << ": "
+ << header_list.DebugString();
+ if (prev_max_timestamp_ > cur_max_timestamp_) {
+ // prev_max_timestamp_ > cur_max_timestamp_ implies that
+ // headers from lower numbered streams actually came off the
+ // wire after headers for the current stream, hence there was
+ // HOL blocking.
+ QuicTime::Delta delta = prev_max_timestamp_ - cur_max_timestamp_;
+ DVLOG(1) << "stream " << stream_id_
+ << ": Net.QuicSession.HeadersHOLBlockedTime "
+ << delta.ToMilliseconds();
+ OnHeadersHeadOfLineBlocking(delta);
+ }
+ prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_);
+ cur_max_timestamp_ = QuicTime::Zero();
+ if (promised_stream_id_ == kInvalidStreamId) {
+ OnStreamHeaderList(stream_id_, fin_, frame_len_, header_list);
+ } else {
+ OnPromiseHeaderList(stream_id_, promised_stream_id_, frame_len_,
+ header_list);
+ }
+ // Reset state for the next frame.
+ promised_stream_id_ = kInvalidStreamId;
+ stream_id_ = kInvalidStreamId;
+ fin_ = false;
+ frame_len_ = 0;
+ uncompressed_frame_len_ = 0;
+}
+
+void QuicSpdySession::OnCompressedFrameSize(size_t frame_len) {
+ frame_len_ += frame_len;
+}
+
+void QuicSpdySession::DisableHpackDynamicTable() {
+ spdy_framer_.UpdateHeaderEncoderTableSize(0);
+}
+
+void QuicSpdySession::SetHpackEncoderDebugVisitor(
+ std::unique_ptr<QuicHpackDebugVisitor> visitor) {
+ spdy_framer_.SetEncoderHeaderTableDebugVisitor(
+ std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
+ connection()->helper()->GetClock(), std::move(visitor))));
+}
+
+void QuicSpdySession::SetHpackDecoderDebugVisitor(
+ std::unique_ptr<QuicHpackDebugVisitor> visitor) {
+ spdy_framer_.SetDecoderHeaderTableDebugVisitor(
+ std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
+ connection()->helper()->GetClock(), std::move(visitor))));
+}
+
+void QuicSpdySession::UpdateHeaderEncoderTableSize(uint32_t value) {
+ spdy_framer_.UpdateHeaderEncoderTableSize(value);
+}
+
+void QuicSpdySession::UpdateEnableServerPush(bool value) {
+ set_server_push_enabled(value);
+}
+
+bool QuicSpdySession::OnDataFrameHeader(QuicStreamId stream_id,
+ size_t length,
+ bool fin) {
+ if (!force_hol_blocking()) {
+ return false;
+ }
+ if (!IsConnected()) {
+ return true;
+ }
+ DVLOG(1) << "DATA frame header for stream " << stream_id << " length "
+ << length << " fin " << fin;
+ fin_ = fin;
+ frame_len_ = length;
+ if (fin && length == 0) {
+ OnStreamFrameData(stream_id, "", 0);
+ }
+ return true;
+}
+
+bool QuicSpdySession::OnStreamFrameData(QuicStreamId stream_id,
+ const char* data,
+ size_t len) {
+ if (!force_hol_blocking()) {
+ return false;
+ }
+ if (!IsConnected()) {
+ return true;
+ }
+ frame_len_ -= len;
+ // Ignore fin_ while there is more data coming, if frame_len_ > 0.
+ OnStreamFrameData(stream_id, data, len, frame_len_ > 0 ? false : fin_);
+ return true;
+}
+
+void QuicSpdySession::set_max_uncompressed_header_bytes(
+ size_t set_max_uncompressed_header_bytes) {
+ spdy_framer_visitor_->set_max_uncompressed_header_bytes(
+ set_max_uncompressed_header_bytes);
+}
+
+void QuicSpdySession::CloseConnectionWithDetails(QuicErrorCode error,
+ const string& details) {
+ connection()->CloseConnection(
+ error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+}
+
} // namespace net
« no previous file with comments | « net/quic/core/quic_spdy_session.h ('k') | net/quic/core/quic_spdy_stream.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698