| Index: net/spdy/spdy_session.cc
|
| diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
|
| index 13a54d5c1c1c53d2b1a606c18d61b1678d49e7fc..b938f53caeed9073bdf2862ea368d8dca8365684 100644
|
| --- a/net/spdy/spdy_session.cc
|
| +++ b/net/spdy/spdy_session.cc
|
| @@ -156,6 +156,7 @@ SpdySession::SpdySession(const HostPortPair& host_port_pair,
|
| certificate_error_code_(OK),
|
| error_(OK),
|
| state_(IDLE),
|
| + max_concurrent_streams_(kDefaultMaxConcurrentStreams),
|
| streams_initiated_count_(0),
|
| streams_pushed_count_(0),
|
| streams_pushed_and_claimed_count_(0),
|
| @@ -292,6 +293,65 @@ int SpdySession::CreateStream(
|
| const GURL& url,
|
| RequestPriority priority,
|
| scoped_refptr<SpdyStream>* spdy_stream,
|
| + const BoundNetLog& stream_net_log,
|
| + CompletionCallback* callback,
|
| + const SpdyHttpStream* spdy_http_stream) {
|
| + if (!max_concurrent_streams_ ||
|
| + active_streams_.size() < max_concurrent_streams_) {
|
| + return CreateStreamImpl(url, priority, spdy_stream, stream_net_log);
|
| + }
|
| +
|
| + create_stream_queues_[priority].push(
|
| + PendingCreateStream(url, priority, spdy_stream,
|
| + stream_net_log, callback, spdy_http_stream));
|
| + return ERR_IO_PENDING;
|
| +}
|
| +
|
| +void SpdySession::ProcessPendingCreateStreams() {
|
| + while (!max_concurrent_streams_ ||
|
| + active_streams_.size() < max_concurrent_streams_) {
|
| + bool no_pending_create_streams = true;
|
| + for (int i = 0;i < NUM_PRIORITIES;++i) {
|
| + if (!create_stream_queues_[i].empty()) {
|
| + PendingCreateStream& pending_create = create_stream_queues_[i].front();
|
| + no_pending_create_streams = false;
|
| + int error = CreateStreamImpl(*pending_create.url,
|
| + pending_create.priority,
|
| + pending_create.spdy_stream,
|
| + *pending_create.stream_net_log);
|
| + pending_create.callback->Run(error);
|
| + create_stream_queues_[i].pop();
|
| + break;
|
| + }
|
| + }
|
| + if (no_pending_create_streams)
|
| + return; // there were no streams in any queue
|
| + }
|
| +}
|
| +
|
| +void SpdySession::CancelPendingCreateStreams(
|
| + const SpdyHttpStream *const spdy_http_stream) {
|
| + for (int i = 0;i < NUM_PRIORITIES;++i) {
|
| + PendingCreateStreamQueue tmp;
|
| + // Make a copy removing this trans
|
| + while (!create_stream_queues_[i].empty()) {
|
| + PendingCreateStream& pending_create = create_stream_queues_[i].front();
|
| + if (pending_create.spdy_http_stream != spdy_http_stream)
|
| + tmp.push(pending_create);
|
| + create_stream_queues_[i].pop();
|
| + }
|
| + // Now copy it back
|
| + while (!tmp.empty()) {
|
| + create_stream_queues_[i].push(tmp.front());
|
| + tmp.pop();
|
| + }
|
| + }
|
| +}
|
| +
|
| +int SpdySession::CreateStreamImpl(
|
| + const GURL& url,
|
| + RequestPriority priority,
|
| + scoped_refptr<SpdyStream>* spdy_stream,
|
| const BoundNetLog& stream_net_log) {
|
| // Make sure that we don't try to send https/wss over an unauthenticated, but
|
| // encrypted SSL socket.
|
| @@ -707,6 +767,14 @@ void SpdySession::CloseAllStreams(net::Error status) {
|
| abandoned_push_streams.Add(pushed_streams_.size());
|
| }
|
|
|
| + for (int i = 0;i < NUM_PRIORITIES;++i) {
|
| + while (!create_stream_queues_[i].empty()) {
|
| + PendingCreateStream& pending_create = create_stream_queues_[i].front();
|
| + pending_create.callback->Run(ERR_ABORTED);
|
| + create_stream_queues_[i].pop();
|
| + }
|
| + }
|
| +
|
| while (!active_streams_.empty()) {
|
| ActiveStreamMap::iterator it = active_streams_.begin();
|
| const scoped_refptr<SpdyStream>& stream = it->second;
|
| @@ -719,8 +787,7 @@ void SpdySession::CloseAllStreams(net::Error 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)
|
| - {
|
| + for (it = pending_streams_.begin(); it != pending_streams_.end(); ++it) {
|
| const scoped_refptr<SpdyStream>& stream = it->second;
|
| if (stream)
|
| stream->OnClose(ERR_ABORTED);
|
| @@ -799,6 +866,7 @@ void SpdySession::DeleteStream(spdy::SpdyStreamId id, int status) {
|
| active_streams_.erase(it2);
|
| if (stream)
|
| stream->OnClose(status);
|
| + ProcessPendingCreateStreams();
|
| }
|
|
|
| void SpdySession::RemoveFromPool() {
|
| @@ -1118,6 +1186,7 @@ void SpdySession::OnGoAway(const spdy::SpdyGoAwayControlFrame& frame) {
|
| void SpdySession::OnSettings(const spdy::SpdySettingsControlFrame& frame) {
|
| spdy::SpdySettings settings;
|
| if (spdy_framer_.ParseSettings(&frame, &settings)) {
|
| + HandleSettings(settings);
|
| SpdySettingsStorage* settings_storage = session_->mutable_spdy_settings();
|
| settings_storage->Set(host_port_pair_, settings);
|
| }
|
| @@ -1134,6 +1203,7 @@ void SpdySession::SendSettings() {
|
| const spdy::SpdySettings& settings = settings_storage.Get(host_port_pair_);
|
| if (settings.empty())
|
| return;
|
| + HandleSettings(settings);
|
|
|
| net_log_.AddEvent(
|
| NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS,
|
| @@ -1146,6 +1216,20 @@ void SpdySession::SendSettings() {
|
| QueueFrame(settings_frame.get(), 0, NULL);
|
| }
|
|
|
| +void SpdySession::HandleSettings(const spdy::SpdySettings& settings) {
|
| + for (spdy::SpdySettings::const_iterator i = settings.begin(),
|
| + end = settings.end(); i != end; ++i) {
|
| + const uint32 id = i->first.id();
|
| + const uint32 val = i->second;
|
| + switch (id) {
|
| + case spdy::SETTINGS_MAX_CONCURRENT_STREAMS:
|
| + max_concurrent_streams_ = val;
|
| + ProcessPendingCreateStreams();
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| void SpdySession::RecordHistograms() {
|
| UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession",
|
| streams_initiated_count_,
|
| @@ -1168,10 +1252,6 @@ void SpdySession::RecordHistograms() {
|
| // Enumerate the saved settings, and set histograms for it.
|
| const SpdySettingsStorage& settings_storage = session_->spdy_settings();
|
| const spdy::SpdySettings& settings = settings_storage.Get(host_port_pair_);
|
| - if (settings.empty()) {
|
| - NOTREACHED(); // If we lost our settings already, something is wrong!
|
| - return;
|
| - }
|
|
|
| spdy::SpdySettings::const_iterator it;
|
| for (it = settings.begin(); it != settings.end(); ++it) {
|
|
|