Index: net/spdy/spdy_session.cc |
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc |
index 46e2273c0f3f6d68b3548ebb094d781ad89dbcc3..8b0d63fe57d01a770975d8e92f587edbfdfb21bf 100644 |
--- a/net/spdy/spdy_session.cc |
+++ b/net/spdy/spdy_session.cc |
@@ -278,24 +278,7 @@ int SpdySession::GetPushStream( |
streams_pushed_and_claimed_count_++; |
return OK; |
} |
- |
- // Check if we have a pending push stream for this url. |
- // Note that we shouldn't have a pushed stream for non-GET method. |
- PendingStreamMap::iterator it; |
- it = pending_streams_.find(path); |
- if (it != pending_streams_.end()) { |
- // Server has advertised a stream, but not yet sent it. |
- DCHECK(!it->second); |
- // Server will assign a stream id when the push stream arrives. Use 0 for |
- // now. |
- net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ADOPTED_PUSH_STREAM, NULL); |
- *stream = new SpdyStream(this, 0, true); |
- (*stream)->set_path(path); |
- (*stream)->set_net_log(stream_net_log); |
- it->second = *stream; |
- return OK; |
- } |
- return OK; |
+ return NULL; |
} |
int SpdySession::CreateStream( |
@@ -472,16 +455,19 @@ void SpdySession::CloseStream(spdy::SpdyStreamId stream_id, int status) { |
void SpdySession::ResetStream( |
spdy::SpdyStreamId stream_id, spdy::SpdyStatusCodes status) { |
- DCHECK(IsStreamActive(stream_id)); |
- scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
- CHECK_EQ(stream->stream_id(), stream_id); |
- |
LOG(INFO) << "Sending a RST_STREAM frame for stream " << stream_id |
<< " with status " << status; |
scoped_ptr<spdy::SpdyRstStreamControlFrame> rst_frame( |
spdy_framer_.CreateRstStream(stream_id, status)); |
- QueueFrame(rst_frame.get(), stream->priority(), stream); |
+ |
+ // Default to lowest priority unless we know otherwise. |
+ int priority = 3; |
+ if(IsStreamActive(stream_id)) { |
+ scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
+ priority = stream->priority(); |
+ } |
+ QueueFrame(rst_frame.get(), priority, NULL); |
DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); |
} |
@@ -785,9 +771,9 @@ void SpdySession::CloseAllStreams(net::Error status) { |
if (!active_streams_.empty()) |
abandoned_streams.Add(active_streams_.size()); |
- if (!pushed_streams_.empty()) { |
- streams_abandoned_count_ += pushed_streams_.size(); |
- abandoned_push_streams.Add(pushed_streams_.size()); |
+ if (!unclaimed_pushed_streams_.empty()) { |
+ streams_abandoned_count_ += unclaimed_pushed_streams_.size(); |
+ abandoned_push_streams.Add(unclaimed_pushed_streams_.size()); |
} |
for (int i = 0;i < NUM_PRIORITIES;++i) { |
@@ -807,16 +793,6 @@ void SpdySession::CloseAllStreams(net::Error status) { |
DeleteStream(stream->stream_id(), status); |
} |
- // TODO(erikchen): ideally stream->OnClose() is only ever called by |
- // DeleteStream, but pending streams fall into their own category for now. |
- PendingStreamMap::iterator it; |
- for (it = pending_streams_.begin(); it != pending_streams_.end(); ++it) { |
- const scoped_refptr<SpdyStream>& stream = it->second; |
- if (stream) |
- stream->OnClose(ERR_ABORTED); |
- } |
- pending_streams_.clear(); |
- |
// We also need to drain the queue. |
while (queue_.size()) |
queue_.pop(); |
@@ -869,12 +845,13 @@ void SpdySession::ActivateStream(SpdyStream* stream) { |
} |
void SpdySession::DeleteStream(spdy::SpdyStreamId id, int status) { |
- // Remove the stream from pushed_streams_ and active_streams_. |
- ActivePushedStreamList::iterator it; |
- for (it = pushed_streams_.begin(); it != pushed_streams_.end(); ++it) { |
- scoped_refptr<SpdyStream> curr = *it; |
+ // Remove the stream from unclaimed_pushed_streams_ and active_streams_. |
+ PushedStreamMap::iterator it; |
+ for (it = unclaimed_pushed_streams_.begin(); |
+ it != unclaimed_pushed_streams_.end(); ++it) { |
+ scoped_refptr<SpdyStream> curr = it->second; |
if (id == curr->stream_id()) { |
- pushed_streams_.erase(it); |
+ unclaimed_pushed_streams_.erase(it); |
break; |
} |
} |
@@ -905,22 +882,19 @@ scoped_refptr<SpdyStream> SpdySession::GetActivePushStream( |
LOG(INFO) << "Looking for push stream: " << path; |
- scoped_refptr<SpdyStream> stream; |
- |
- // We just walk a linear list here. |
- ActivePushedStreamList::iterator it; |
- for (it = pushed_streams_.begin(); it != pushed_streams_.end(); ++it) { |
- stream = *it; |
- if (path == stream->path()) { |
- CHECK(stream->pushed()); |
- pushed_streams_.erase(it); |
- used_push_streams.Increment(); |
- LOG(INFO) << "Push Stream Claim for: " << path; |
- return stream; |
- } |
+ PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(path); |
+ if (it != unclaimed_pushed_streams_.end()) { |
+ LOG(INFO) << "Push stream: " << path << " found."; |
+ net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ADOPTED_PUSH_STREAM, NULL); |
+ scoped_refptr<SpdyStream> stream = it->second; |
+ unclaimed_pushed_streams_.erase(it); |
+ used_push_streams.Increment(); |
+ return stream; |
+ } |
+ else { |
+ LOG(INFO) << "Push stream: " << path << " not found."; |
+ return NULL; |
} |
- |
- return NULL; |
} |
bool SpdySession::GetSSLInfo(SSLInfo* ssl_info, bool* was_npn_negotiated) { |
@@ -971,9 +945,9 @@ bool SpdySession::Respond(const spdy::SpdyHeaderBlock& headers, |
void SpdySession::OnSyn(const spdy::SpdySynStreamControlFrame& frame, |
const linked_ptr<spdy::SpdyHeaderBlock>& headers) { |
spdy::SpdyStreamId stream_id = frame.stream_id(); |
- |
- LOG(INFO) << "Spdy SynStream for stream " << stream_id; |
- |
+ spdy::SpdyStreamId associated_stream_id = frame.associated_stream_id(); |
+ LOG(INFO) << "Spdy SynStream for stream " << stream_id |
+ << " with associated stream " << associated_stream_id; |
// Server-initiated streams should have even sequence numbers. |
if ((stream_id & 0x1) != 0) { |
LOG(ERROR) << "Received invalid OnSyn stream id " << stream_id; |
@@ -985,6 +959,14 @@ void SpdySession::OnSyn(const spdy::SpdySynStreamControlFrame& frame, |
return; |
} |
+ if (associated_stream_id == 0) { |
+ LOG(ERROR) << "Received invalid OnSyn associated stream id " |
+ << associated_stream_id |
+ << " for stream " << stream_id; |
+ ResetStream(stream_id, spdy::INVALID_STREAM); |
+ return; |
+ } |
+ |
streams_pushed_count_++; |
LOG(INFO) << "SpdySession: Syn received for stream: " << stream_id; |
@@ -998,54 +980,47 @@ void SpdySession::OnSyn(const spdy::SpdySynStreamControlFrame& frame, |
headers->find("path")->second : ""; |
// Verify that the response had a URL for us. |
- DCHECK(!path.empty()); |
if (path.empty()) { |
+ ResetStream(stream_id, spdy::PROTOCOL_ERROR); |
LOG(WARNING) << "Pushed stream did not contain a path."; |
return; |
} |
- // Only HTTP push a stream. |
+ if (!IsStreamActive(associated_stream_id)) { |
+ LOG(ERROR) << "Received OnSyn with inactive associated stream " |
+ << associated_stream_id; |
+ ResetStream(stream_id, spdy::INVALID_ASSOCIATED_STREAM); |
+ return; |
+ } |
+ |
scoped_refptr<SpdyStream> stream; |
- // Check if we already have a delegate awaiting this stream. |
- PendingStreamMap::iterator it; |
- it = pending_streams_.find(path); |
- if (it != pending_streams_.end()) { |
- stream = it->second; |
- pending_streams_.erase(it); |
- } |
+ stream = new SpdyStream(this, stream_id, true); |
- if (stream) { |
- CHECK(stream->pushed()); |
- CHECK_EQ(0u, stream->stream_id()); |
- stream->set_stream_id(stream_id); |
- const BoundNetLog& log = stream->net_log(); |
- if (log.HasListener()) { |
- log.AddEvent( |
- NetLog::TYPE_SPDY_STREAM_PUSHED_SYN_STREAM, |
- new NetLogSpdySynParameter( |
- headers, static_cast<spdy::SpdyControlFlags>(frame.flags()), |
- stream_id)); |
- } |
- } else { |
- stream = new SpdyStream(this, stream_id, true); |
- |
- if (net_log_.HasListener()) { |
- net_log_.AddEvent( |
- NetLog::TYPE_SPDY_SESSION_PUSHED_SYN_STREAM, |
- new NetLogSpdySynParameter( |
- headers, static_cast<spdy::SpdyControlFlags>(frame.flags()), |
- stream_id)); |
- } |
+ if (net_log_.HasListener()) { |
+ net_log_.AddEvent( |
+ NetLog::TYPE_SPDY_SESSION_PUSHED_SYN_STREAM, |
+ new NetLogSpdySynParameter( |
+ headers, static_cast<spdy::SpdyControlFlags>(frame.flags()), |
+ stream_id)); |
} |
- pushed_streams_.push_back(stream); |
+ // TODO(erikchen): Actually do something with the associated id. |
+ |
+ stream->set_path(path); |
+ |
+ // There should not be an existing pushed stream with the same path. |
+ PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(path); |
+ if (it != unclaimed_pushed_streams_.end()) { |
+ LOG(ERROR) << "Received duplicate pushed stream with path: " << path; |
+ ResetStream(stream_id, spdy::PROTOCOL_ERROR); |
+ } |
+ unclaimed_pushed_streams_[path] = stream; |
// Activate a stream and parse the headers. |
ActivateStream(stream); |
- stream->set_path(path); |
- |
+ // Parse the headers. |
if (!Respond(*headers, stream)) |
return; |
@@ -1081,34 +1056,6 @@ void SpdySession::OnSynReply(const spdy::SpdySynReplyControlFrame& frame, |
} |
stream->set_syn_reply_received(); |
- // We record content declared as being pushed so that we don't |
- // request a duplicate stream which is already scheduled to be |
- // sent to us. |
- spdy::SpdyHeaderBlock::const_iterator it; |
- it = headers->find("x-associated-content"); |
- if (it != headers->end()) { |
- const std::string& content = it->second; |
- std::string::size_type start = 0; |
- std::string::size_type end = 0; |
- do { |
- end = content.find("||", start); |
- if (end == std::string::npos) |
- end = content.length(); |
- std::string url = content.substr(start, end - start); |
- std::string::size_type pos = url.find("??"); |
- if (pos == std::string::npos) |
- break; |
- url = url.substr(pos + 2); |
- GURL gurl(url); |
- std::string path = gurl.PathForRequest(); |
- if (path.length()) |
- pending_streams_[path] = NULL; |
- else |
- LOG(INFO) << "Invalid X-Associated-Content path: " << url; |
- start = end + 2; |
- } while (start < content.length()); |
- } |
- |
const BoundNetLog& log = stream->net_log(); |
if (log.HasListener()) { |
log.AddEvent( |
@@ -1151,7 +1098,7 @@ void SpdySession::OnControl(const spdy::SpdyControlFrame* frame) { |
*reinterpret_cast<const spdy::SpdySettingsControlFrame*>(frame)); |
break; |
case spdy::RST_STREAM: |
- OnFin(*reinterpret_cast<const spdy::SpdyRstStreamControlFrame*>(frame)); |
+ OnRst(*reinterpret_cast<const spdy::SpdyRstStreamControlFrame*>(frame)); |
break; |
case spdy::SYN_STREAM: |
OnSyn(*reinterpret_cast<const spdy::SpdySynStreamControlFrame*>(frame), |
@@ -1171,7 +1118,7 @@ void SpdySession::OnControl(const spdy::SpdyControlFrame* frame) { |
} |
} |
-void SpdySession::OnFin(const spdy::SpdyRstStreamControlFrame& frame) { |
+void SpdySession::OnRst(const spdy::SpdyRstStreamControlFrame& frame) { |
spdy::SpdyStreamId stream_id = frame.stream_id(); |
LOG(INFO) << "Spdy Fin for stream " << stream_id; |