Index: net/spdy/spdy_session.cc |
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc |
index fc549d5af311a4adc4bdfbc04152b4c81558a782..01cb874ac22d502258aa5886c3709c83690dd5c0 100644 |
--- a/net/spdy/spdy_session.cc |
+++ b/net/spdy/spdy_session.cc |
@@ -13,6 +13,7 @@ |
#include "base/compiler_specific.h" |
#include "base/location.h" |
#include "base/logging.h" |
+#include "base/memory/ptr_util.h" |
#include "base/metrics/histogram_macros.h" |
#include "base/metrics/sparse_histogram.h" |
#include "base/profiler/scoped_tracker.h" |
@@ -265,6 +266,20 @@ std::unique_ptr<base::Value> NetLogSpdyAdoptedPushStreamCallback( |
return std::move(dict); |
} |
+std::unique_ptr<base::Value> NetLogSpdyPriorityCallback( |
+ SpdyStreamId stream_id, |
+ SpdyStreamId parent_stream_id, |
+ int weight, |
+ bool exclusive, |
+ NetLogCaptureMode capture_mode) { |
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
Bence
2017/01/05 17:14:46
Please use MakeUnique in new code, see https://cs.
Tom Bergan
2017/01/06 00:08:41
Done. Also did a search/replace on the other NetLo
|
+ dict->SetInteger("stream_id", stream_id); |
+ dict->SetInteger("parent_stream_id", parent_stream_id); |
+ dict->SetInteger("weight", weight); |
+ dict->SetBoolean("exclusive", exclusive); |
+ return std::move(dict); |
+} |
+ |
// Helper function to return the total size of an array of objects |
// with .size() member functions. |
template <typename T, size_t N> size_t GetTotalSize(const T (&arr)[N]) { |
@@ -772,6 +787,7 @@ bool SpdySession::VerifyDomainAuthentication(const std::string& domain) { |
} |
int SpdySession::GetPushStream(const GURL& url, |
+ RequestPriority priority, |
base::WeakPtr<SpdyStream>* stream, |
const NetLogWithSource& stream_net_log) { |
CHECK(!in_io_loop_); |
@@ -785,7 +801,26 @@ int SpdySession::GetPushStream(const GURL& url, |
if (*stream) { |
DCHECK_LT(streams_pushed_and_claimed_count_, streams_pushed_count_); |
streams_pushed_and_claimed_count_++; |
+ |
+ // If the stream is still open, update its priority to match |
+ // the priority of the matching request. |
+ if (!(*stream)->IsClosed() && (*stream)->priority() != priority) { |
+ (*stream)->set_priority(priority); |
+ |
+ // Send PRIORITY updates. |
+ auto updates = priority_dependency_state_.OnStreamUpdate( |
+ (*stream)->stream_id(), |
+ ConvertRequestPriorityToSpdyPriority(priority)); |
+ for (auto u : updates) { |
+ ActiveStreamMap::iterator it = active_streams_.find(u.id); |
+ DCHECK(it != active_streams_.end()); |
+ int weight = Spdy3PriorityToHttp2Weight( |
+ ConvertRequestPriorityToSpdyPriority(it->second->priority())); |
+ EnqueuePriorityFrame(u.id, u.dependent_stream_id, weight, u.exclusive); |
+ } |
+ } |
} |
+ |
return OK; |
} |
@@ -1011,8 +1046,8 @@ std::unique_ptr<SpdySerializedFrame> SpdySession::CreateHeaders( |
SpdyStreamId dependent_stream_id = 0; |
bool exclusive = false; |
- priority_dependency_state_.OnStreamSynSent(stream_id, spdy_priority, |
- &dependent_stream_id, &exclusive); |
+ priority_dependency_state_.OnStreamCreation(stream_id, spdy_priority, |
+ &dependent_stream_id, &exclusive); |
if (net_log().IsCapturing()) { |
net_log().AddEvent( |
@@ -1270,6 +1305,28 @@ void SpdySession::EnqueueResetStreamFrame(SpdyStreamId stream_id, |
RecordProtocolErrorHistogram(MapRstStreamStatusToProtocolError(status)); |
} |
+void SpdySession::EnqueuePriorityFrame(SpdyStreamId stream_id, |
+ SpdyStreamId dependency_id, |
+ int weight, |
+ bool exclusive) { |
+ net_log().AddEvent(NetLogEventType::HTTP2_STREAM_UPDATE_PRIORITY, |
+ base::Bind(&NetLogSpdyPriorityCallback, stream_id, |
+ dependency_id, weight, exclusive)); |
+ |
+ DCHECK(buffered_spdy_framer_.get()); |
+ std::unique_ptr<SpdySerializedFrame> frame( |
+ buffered_spdy_framer_->CreatePriority(stream_id, dependency_id, weight, |
+ exclusive)); |
+ |
+ // PRIORITY frames describe sequenced updates to the tree, so they must |
+ // be serialized. We do this by queueing all PRIORITY frames at HIGHEST |
+ // priority. |
+ EnqueueWrite(HIGHEST, PRIORITY, |
+ base::MakeUnique<SimpleBufferProducer>( |
+ base::MakeUnique<SpdyBuffer>(std::move(frame))), |
+ base::WeakPtr<SpdyStream>()); |
+} |
+ |
void SpdySession::PumpReadLoop(ReadState expected_read_state, int result) { |
CHECK(!in_io_loop_); |
if (availability_state_ == STATE_DRAINING) { |
@@ -2408,7 +2465,6 @@ void SpdySession::OnWindowUpdate(SpdyStreamId stream_id, |
void SpdySession::TryCreatePushStream(SpdyStreamId stream_id, |
SpdyStreamId associated_stream_id, |
- SpdyPriority priority, |
SpdyHeaderBlock headers) { |
// Server-initiated streams should have even sequence numbers. |
if ((stream_id & 0x1) != 0) { |
@@ -2443,8 +2499,8 @@ void SpdySession::TryCreatePushStream(SpdyStreamId stream_id, |
last_accepted_push_stream_id_ = stream_id; |
- RequestPriority request_priority = |
- ConvertSpdyPriorityToRequestPriority(priority); |
+ // Pushed streams are speculative, so they start at an IDLE priority. |
+ const RequestPriority request_priority = IDLE; |
if (availability_state_ == STATE_GOING_AWAY) { |
// TODO(akalin): This behavior isn't in the SPDY spec, although it |
@@ -2561,6 +2617,16 @@ void SpdySession::TryCreatePushStream(SpdyStreamId stream_id, |
stream_max_recv_window_size_, net_log_)); |
stream->set_stream_id(stream_id); |
+ // Convert RequestPriority to a SpdyPriority to send in a PRIORITY frame. |
+ SpdyPriority spdy_priority = |
+ ConvertRequestPriorityToSpdyPriority(request_priority); |
+ SpdyStreamId dependency_id = 0; |
+ bool exclusive = false; |
+ priority_dependency_state_.OnStreamCreation(stream_id, spdy_priority, |
+ &dependency_id, &exclusive); |
+ EnqueuePriorityFrame(stream_id, dependency_id, |
+ Spdy3PriorityToHttp2Weight(spdy_priority), exclusive); |
+ |
// PUSH_PROMISE arrives on associated stream. |
associated_it->second->AddRawReceivedBytes(last_compressed_frame_len_); |
last_compressed_frame_len_ = 0; |
@@ -2602,8 +2668,7 @@ void SpdySession::OnPushPromise(SpdyStreamId stream_id, |
&headers, stream_id, promised_stream_id)); |
} |
- // Any priority will do. TODO(baranovich): Pass parent stream id priority? |
- TryCreatePushStream(promised_stream_id, stream_id, 0, std::move(headers)); |
+ TryCreatePushStream(promised_stream_id, stream_id, std::move(headers)); |
} |
void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id, |