summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_session.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/spdy/spdy_session.cc')
-rw-r--r--net/spdy/spdy_session.cc92
1 files changed, 86 insertions, 6 deletions
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 13a54d5..b938f53 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) {