| 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; | 
|  | 
|  |