Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: net/spdy/spdy_session.cc

Issue 14348012: [SPDY] Close SPDY sessions on session flow control errors (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove TODOs Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/spdy/spdy_session.h" 5 #include "net/spdy/spdy_session.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/message_loop.h" 14 #include "base/message_loop.h"
15 #include "base/metrics/field_trial.h" 15 #include "base/metrics/field_trial.h"
16 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
17 #include "base/metrics/sparse_histogram.h" 17 #include "base/metrics/sparse_histogram.h"
18 #include "base/metrics/stats_counters.h" 18 #include "base/metrics/stats_counters.h"
19 #include "base/stl_util.h" 19 #include "base/stl_util.h"
20 #include "base/string_number_conversions.h"
21 #include "base/string_util.h" 20 #include "base/string_util.h"
22 #include "base/stringprintf.h" 21 #include "base/stringprintf.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/time.h" 23 #include "base/time.h"
24 #include "base/utf_string_conversions.h" 24 #include "base/utf_string_conversions.h"
25 #include "base/values.h" 25 #include "base/values.h"
26 #include "crypto/ec_private_key.h" 26 #include "crypto/ec_private_key.h"
27 #include "crypto/ec_signature_creator.h" 27 #include "crypto/ec_signature_creator.h"
28 #include "net/base/connection_type_histograms.h" 28 #include "net/base/connection_type_histograms.h"
29 #include "net/base/net_log.h" 29 #include "net/base/net_log.h"
30 #include "net/base/net_util.h" 30 #include "net/base/net_util.h"
31 #include "net/cert/asn1_util.h" 31 #include "net/cert/asn1_util.h"
32 #include "net/http/http_network_session.h" 32 #include "net/http/http_network_session.h"
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 next_unclaimed_push_stream_sweep_time_ = time_func_() + 367 next_unclaimed_push_stream_sweep_time_ = time_func_() +
368 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); 368 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds);
369 // TODO(mbelshe): consider randomization of the stream_hi_water_mark. 369 // TODO(mbelshe): consider randomization of the stream_hi_water_mark.
370 } 370 }
371 371
372 SpdySession::~SpdySession() { 372 SpdySession::~SpdySession() {
373 if (state_ != STATE_CLOSED) { 373 if (state_ != STATE_CLOSED) {
374 state_ = STATE_CLOSED; 374 state_ = STATE_CLOSED;
375 375
376 // Cleanup all the streams. 376 // Cleanup all the streams.
377 CloseAllStreams(net::ERR_ABORTED); 377 CloseAllStreams(ERR_ABORTED);
378 } 378 }
379 379
380 if (connection_->is_initialized()) { 380 if (connection_->is_initialized()) {
381 // With SPDY we can't recycle sockets. 381 // With SPDY we can't recycle sockets.
382 connection_->socket()->Disconnect(); 382 connection_->socket()->Disconnect();
383 } 383 }
384 384
385 // Streams should all be gone now. 385 // Streams should all be gone now.
386 DCHECK_EQ(0u, num_active_streams()); 386 DCHECK_EQ(0u, num_active_streams());
387 DCHECK_EQ(0u, num_unclaimed_pushed_streams()); 387 DCHECK_EQ(0u, num_unclaimed_pushed_streams());
388 388
389 for (int i = 0; i < NUM_PRIORITIES; ++i) { 389 for (int i = 0; i < NUM_PRIORITIES; ++i) {
390 DCHECK(pending_create_stream_queues_[i].empty()); 390 DCHECK(pending_create_stream_queues_[i].empty());
391 } 391 }
392 DCHECK(pending_stream_request_completions_.empty()); 392 DCHECK(pending_stream_request_completions_.empty());
393 393
394 RecordHistograms(); 394 RecordHistograms();
395 395
396 net_log_.EndEvent(NetLog::TYPE_SPDY_SESSION); 396 net_log_.EndEvent(NetLog::TYPE_SPDY_SESSION);
397 } 397 }
398 398
399 net::Error SpdySession::InitializeWithSocket( 399 Error SpdySession::InitializeWithSocket(
400 ClientSocketHandle* connection, 400 ClientSocketHandle* connection,
401 bool is_secure, 401 bool is_secure,
402 int certificate_error_code) { 402 int certificate_error_code) {
403 base::StatsCounter spdy_sessions("spdy.sessions"); 403 base::StatsCounter spdy_sessions("spdy.sessions");
404 spdy_sessions.Increment(); 404 spdy_sessions.Increment();
405 405
406 state_ = STATE_DO_READ; 406 state_ = STATE_DO_READ;
407 connection_.reset(connection); 407 connection_.reset(connection);
408 is_secure_ = is_secure; 408 is_secure_ = is_secure;
409 certificate_error_code_ = certificate_error_code; 409 certificate_error_code_ = certificate_error_code;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 DCHECK_GT(session_recv_window_size_, 0); 450 DCHECK_GT(session_recv_window_size_, 0);
451 IncreaseRecvWindowSize( 451 IncreaseRecvWindowSize(
452 kDefaultInitialRecvWindowSize - session_recv_window_size_); 452 kDefaultInitialRecvWindowSize - session_recv_window_size_);
453 } 453 }
454 454
455 // Write out any data that we might have to send, such as the settings frame. 455 // Write out any data that we might have to send, such as the settings frame.
456 WriteSocketLater(); 456 WriteSocketLater();
457 int error = DoLoop(OK); 457 int error = DoLoop(OK);
458 if (error == ERR_IO_PENDING) 458 if (error == ERR_IO_PENDING)
459 return OK; 459 return OK;
460 return static_cast<net::Error>(error); 460 return static_cast<Error>(error);
461 } 461 }
462 462
463 bool SpdySession::VerifyDomainAuthentication(const std::string& domain) { 463 bool SpdySession::VerifyDomainAuthentication(const std::string& domain) {
464 if (!verify_domain_authentication_) 464 if (!verify_domain_authentication_)
465 return true; 465 return true;
466 466
467 if (!IsConnected()) 467 if (!IsConnected())
468 return false; 468 return false;
469 469
470 SSLInfo ssl_info; 470 SSLInfo ssl_info;
(...skipping 18 matching lines...) Expand all
489 489
490 *stream = NULL; 490 *stream = NULL;
491 491
492 // Don't allow access to secure push streams over an unauthenticated, but 492 // Don't allow access to secure push streams over an unauthenticated, but
493 // encrypted SSL socket. 493 // encrypted SSL socket.
494 if (is_secure_ && certificate_error_code_ != OK && 494 if (is_secure_ && certificate_error_code_ != OK &&
495 (url.SchemeIs("https") || url.SchemeIs("wss"))) { 495 (url.SchemeIs("https") || url.SchemeIs("wss"))) {
496 RecordProtocolErrorHistogram( 496 RecordProtocolErrorHistogram(
497 PROTOCOL_ERROR_REQUEST_FOR_SECURE_CONTENT_OVER_INSECURE_SESSION); 497 PROTOCOL_ERROR_REQUEST_FOR_SECURE_CONTENT_OVER_INSECURE_SESSION);
498 CloseSessionOnError( 498 CloseSessionOnError(
499 static_cast<net::Error>(certificate_error_code_), 499 static_cast<Error>(certificate_error_code_),
500 true, 500 true,
501 "Tried to get SPDY stream for secure content over an unauthenticated " 501 "Tried to get SPDY stream for secure content over an unauthenticated "
502 "session."); 502 "session.");
503 return ERR_SPDY_PROTOCOL_ERROR; 503 return ERR_SPDY_PROTOCOL_ERROR;
504 } 504 }
505 505
506 *stream = GetActivePushStream(url.spec()); 506 *stream = GetActivePushStream(url.spec());
507 if (stream->get()) { 507 if (stream->get()) {
508 DCHECK(streams_pushed_and_claimed_count_ < streams_pushed_count_); 508 DCHECK(streams_pushed_and_claimed_count_ < streams_pushed_count_);
509 streams_pushed_and_claimed_count_++; 509 streams_pushed_and_claimed_count_++;
(...skipping 20 matching lines...) Expand all
530 DCHECK_GE(request.priority(), MINIMUM_PRIORITY); 530 DCHECK_GE(request.priority(), MINIMUM_PRIORITY);
531 DCHECK_LT(request.priority(), NUM_PRIORITIES); 531 DCHECK_LT(request.priority(), NUM_PRIORITIES);
532 532
533 // Make sure that we don't try to send https/wss over an unauthenticated, but 533 // Make sure that we don't try to send https/wss over an unauthenticated, but
534 // encrypted SSL socket. 534 // encrypted SSL socket.
535 if (is_secure_ && certificate_error_code_ != OK && 535 if (is_secure_ && certificate_error_code_ != OK &&
536 (request.url().SchemeIs("https") || request.url().SchemeIs("wss"))) { 536 (request.url().SchemeIs("https") || request.url().SchemeIs("wss"))) {
537 RecordProtocolErrorHistogram( 537 RecordProtocolErrorHistogram(
538 PROTOCOL_ERROR_REQUEST_FOR_SECURE_CONTENT_OVER_INSECURE_SESSION); 538 PROTOCOL_ERROR_REQUEST_FOR_SECURE_CONTENT_OVER_INSECURE_SESSION);
539 CloseSessionOnError( 539 CloseSessionOnError(
540 static_cast<net::Error>(certificate_error_code_), 540 static_cast<Error>(certificate_error_code_),
541 true, 541 true,
542 "Tried to create SPDY stream for secure content over an " 542 "Tried to create SPDY stream for secure content over an "
543 "unauthenticated session."); 543 "unauthenticated session.");
544 return ERR_SPDY_PROTOCOL_ERROR; 544 return ERR_SPDY_PROTOCOL_ERROR;
545 } 545 }
546 546
547 const std::string& path = request.url().PathForRequest(); 547 const std::string& path = request.url().PathForRequest();
548 *stream = new SpdyStream(this, path, request.priority(), 548 *stream = new SpdyStream(this, path, request.priority(),
549 stream_initial_send_window_size_, 549 stream_initial_send_window_size_,
550 stream_initial_recv_window_size_, 550 stream_initial_recv_window_size_,
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 net_log().AddEvent( 733 net_log().AddEvent(
734 NetLog::TYPE_SPDY_SESSION_SEND_HEADERS, 734 NetLog::TYPE_SPDY_SESSION_SEND_HEADERS,
735 base::Bind(&NetLogSpdySynCallback, 735 base::Bind(&NetLogSpdySynCallback,
736 &headers, fin, /*unidirectional=*/false, 736 &headers, fin, /*unidirectional=*/false,
737 stream_id, 0)); 737 stream_id, 0));
738 } 738 }
739 return frame.Pass(); 739 return frame.Pass();
740 } 740 }
741 741
742 scoped_ptr<SpdyBuffer> SpdySession::CreateDataBuffer(SpdyStreamId stream_id, 742 scoped_ptr<SpdyBuffer> SpdySession::CreateDataBuffer(SpdyStreamId stream_id,
743 net::IOBuffer* data, 743 IOBuffer* data,
744 int len, 744 int len,
745 SpdyDataFlags flags) { 745 SpdyDataFlags flags) {
746 // Find our stream. 746 // Find our stream.
747 CHECK(IsStreamActive(stream_id)); 747 CHECK(IsStreamActive(stream_id));
748 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 748 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
749 CHECK_EQ(stream->stream_id(), stream_id); 749 CHECK_EQ(stream->stream_id(), stream_id);
750 750
751 if (len < 0) { 751 if (len < 0) {
752 NOTREACHED(); 752 NOTREACHED();
753 return scoped_ptr<SpdyBuffer>(); 753 return scoped_ptr<SpdyBuffer>();
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 const std::string& description) { 878 const std::string& description) {
879 net_log().AddEvent( 879 net_log().AddEvent(
880 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM, 880 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM,
881 base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description)); 881 base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description));
882 882
883 DCHECK(buffered_spdy_framer_.get()); 883 DCHECK(buffered_spdy_framer_.get());
884 scoped_ptr<SpdyFrame> rst_frame( 884 scoped_ptr<SpdyFrame> rst_frame(
885 buffered_spdy_framer_->CreateRstStream(stream_id, status)); 885 buffered_spdy_framer_->CreateRstStream(stream_id, status));
886 886
887 // Default to lowest priority unless we know otherwise. 887 // Default to lowest priority unless we know otherwise.
888 RequestPriority priority = net::IDLE; 888 RequestPriority priority = IDLE;
889 if (IsStreamActive(stream_id)) { 889 if (IsStreamActive(stream_id)) {
890 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 890 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
891 priority = stream->priority(); 891 priority = stream->priority();
892 } 892 }
893 EnqueueSessionWrite(priority, RST_STREAM, rst_frame.Pass()); 893 EnqueueSessionWrite(priority, RST_STREAM, rst_frame.Pass());
894 RecordProtocolErrorHistogram( 894 RecordProtocolErrorHistogram(
895 static_cast<SpdyProtocolErrorDetails>(status + STATUS_CODE_INVALID)); 895 static_cast<SpdyProtocolErrorDetails>(status + STATUS_CODE_INVALID));
896 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); 896 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR);
897 } 897 }
898 898
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
975 base::Bind(&SpdySession::OnReadComplete, weak_factory_.GetWeakPtr())); 975 base::Bind(&SpdySession::OnReadComplete, weak_factory_.GetWeakPtr()));
976 } 976 }
977 977
978 int SpdySession::DoReadComplete(int result) { 978 int SpdySession::DoReadComplete(int result) {
979 // Parse a frame. For now this code requires that the frame fit into our 979 // Parse a frame. For now this code requires that the frame fit into our
980 // buffer (32KB). 980 // buffer (32KB).
981 // TODO(mbelshe): support arbitrarily large frames! 981 // TODO(mbelshe): support arbitrarily large frames!
982 982
983 if (result <= 0) { 983 if (result <= 0) {
984 // Session is tearing down. 984 // Session is tearing down.
985 net::Error error = static_cast<net::Error>(result); 985 Error error = static_cast<Error>(result);
986 if (result == 0) { 986 if (result == 0) {
987 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySession.BytesRead.EOF", 987 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySession.BytesRead.EOF",
988 total_bytes_received_, 1, 100000000, 50); 988 total_bytes_received_, 1, 100000000, 50);
989 error = ERR_CONNECTION_CLOSED; 989 error = ERR_CONNECTION_CLOSED;
990 } 990 }
991 CloseSessionOnError(error, true, "result is <= 0."); 991 CloseSessionOnError(error, true, "result is <= 0.");
992 return ERR_CONNECTION_CLOSED; 992 return ERR_CONNECTION_CLOSED;
993 } 993 }
994 994
995 total_bytes_received_ += result; 995 total_bytes_received_ += result;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1039 // It should not be possible to have written more bytes than our 1039 // It should not be possible to have written more bytes than our
1040 // in_flight_write_. 1040 // in_flight_write_.
1041 DCHECK_LE(static_cast<size_t>(result), 1041 DCHECK_LE(static_cast<size_t>(result),
1042 in_flight_write_->GetRemainingSize()); 1042 in_flight_write_->GetRemainingSize());
1043 1043
1044 if (result > 0) { 1044 if (result > 0) {
1045 in_flight_write_->Consume(static_cast<size_t>(result)); 1045 in_flight_write_->Consume(static_cast<size_t>(result));
1046 1046
1047 // We only notify the stream when we've fully written the pending frame. 1047 // We only notify the stream when we've fully written the pending frame.
1048 if (in_flight_write_->GetRemainingSize() == 0) { 1048 if (in_flight_write_->GetRemainingSize() == 0) {
1049 // It is possible that the stream was cancelled while we were 1049 // It is possible that the stream was cancelled while we were
1050 // writing to the socket. 1050 // writing to the socket.
1051 if (in_flight_write_stream_ && !in_flight_write_stream_->cancelled()) { 1051 if (in_flight_write_stream_ && !in_flight_write_stream_->cancelled()) {
1052 DCHECK_GT(in_flight_write_frame_size_, 0u); 1052 DCHECK_GT(in_flight_write_frame_size_, 0u);
1053 in_flight_write_stream_->OnFrameWriteComplete( 1053 in_flight_write_stream_->OnFrameWriteComplete(
1054 in_flight_write_frame_type_, 1054 in_flight_write_frame_type_,
1055 in_flight_write_frame_size_); 1055 in_flight_write_frame_size_);
1056 } 1056 }
1057 1057
1058 // Cleanup the write which just completed. 1058 // Cleanup the write which just completed.
1059 in_flight_write_.reset(); 1059 in_flight_write_.reset();
1060 in_flight_write_frame_type_ = DATA; 1060 in_flight_write_frame_type_ = DATA;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1136 } 1136 }
1137 in_flight_write_frame_type_ = frame_type; 1137 in_flight_write_frame_type_ = frame_type;
1138 in_flight_write_frame_size_ = in_flight_write_->GetRemainingSize(); 1138 in_flight_write_frame_size_ = in_flight_write_->GetRemainingSize();
1139 DCHECK_GE(in_flight_write_frame_size_, 1139 DCHECK_GE(in_flight_write_frame_size_,
1140 buffered_spdy_framer_->GetFrameMinimumSize()); 1140 buffered_spdy_framer_->GetFrameMinimumSize());
1141 in_flight_write_stream_ = stream; 1141 in_flight_write_stream_ = stream;
1142 } 1142 }
1143 1143
1144 write_pending_ = true; 1144 write_pending_ = true;
1145 // Explicitly store in a scoped_refptr<IOBuffer> to avoid problems 1145 // Explicitly store in a scoped_refptr<IOBuffer> to avoid problems
1146 // with net::Socket implementations that don't store their 1146 // with Socket implementations that don't store their IOBuffer
1147 // IOBuffer argument in a scoped_refptr<IOBuffer> (see 1147 // argument in a scoped_refptr<IOBuffer> (see crbug.com/232345).
1148 // crbug.com/232345).
1149 scoped_refptr<IOBuffer> write_io_buffer = 1148 scoped_refptr<IOBuffer> write_io_buffer =
1150 in_flight_write_->GetIOBufferForRemainingData(); 1149 in_flight_write_->GetIOBufferForRemainingData();
1151 // We keep |in_flight_write_| alive until OnWriteComplete(), so 1150 // We keep |in_flight_write_| alive until OnWriteComplete(), so
1152 // it's okay to use GetIOBufferForRemainingData() since the socket 1151 // it's okay to use GetIOBufferForRemainingData() since the socket
1153 // doesn't use the IOBuffer past OnWriteComplete(). 1152 // doesn't use the IOBuffer past OnWriteComplete().
1154 int rv = connection_->socket()->Write( 1153 int rv = connection_->socket()->Write(
1155 write_io_buffer, 1154 write_io_buffer,
1156 in_flight_write_->GetRemainingSize(), 1155 in_flight_write_->GetRemainingSize(),
1157 base::Bind(&SpdySession::OnWriteComplete, weak_factory_.GetWeakPtr())); 1156 base::Bind(&SpdySession::OnWriteComplete, weak_factory_.GetWeakPtr()));
1158 // Avoid persisting |write_io_buffer| past |in_flight_write_|'s 1157 // Avoid persisting |write_io_buffer| past |in_flight_write_|'s
1159 // lifetime (which will end if OnWriteComplete() is called below). 1158 // lifetime (which will end if OnWriteComplete() is called below).
1160 write_io_buffer = NULL; 1159 write_io_buffer = NULL;
1161 if (rv == net::ERR_IO_PENDING) 1160 if (rv == ERR_IO_PENDING)
1162 break; 1161 break;
1163 1162
1164 // We sent the frame successfully. 1163 // We sent the frame successfully.
1165 OnWriteComplete(rv); 1164 OnWriteComplete(rv);
1166 1165
1167 // TODO(mbelshe): Test this error case. Maybe we should mark the socket 1166 // TODO(mbelshe): Test this error case. Maybe we should mark the socket
1168 // as in an error state. 1167 // as in an error state.
1169 if (rv < 0) 1168 if (rv < 0)
1170 break; 1169 break;
1171 } 1170 }
1172 } 1171 }
1173 1172
1174 void SpdySession::CloseAllStreamsAfter(SpdyStreamId last_good_stream_id, 1173 void SpdySession::CloseAllStreamsAfter(SpdyStreamId last_good_stream_id,
1175 net::Error status) { 1174 Error status) {
1176 for (int i = 0; i < NUM_PRIORITIES; ++i) { 1175 for (int i = 0; i < NUM_PRIORITIES; ++i) {
1177 PendingStreamRequestQueue queue; 1176 PendingStreamRequestQueue queue;
1178 queue.swap(pending_create_stream_queues_[i]); 1177 queue.swap(pending_create_stream_queues_[i]);
1179 for (PendingStreamRequestQueue::const_iterator it = queue.begin(); 1178 for (PendingStreamRequestQueue::const_iterator it = queue.begin();
1180 it != queue.end(); ++it) { 1179 it != queue.end(); ++it) {
1181 (*it)->OnRequestComplete(NULL, ERR_ABORTED); 1180 (*it)->OnRequestComplete(NULL, ERR_ABORTED);
1182 } 1181 }
1183 } 1182 }
1184 1183
1185 ActiveStreamMap::iterator it = 1184 ActiveStreamMap::iterator it =
(...skipping 10 matching lines...) Expand all
1196 CreatedStreamSet::iterator it = created_streams_.begin(); 1195 CreatedStreamSet::iterator it = created_streams_.begin();
1197 const scoped_refptr<SpdyStream> stream = *it; 1196 const scoped_refptr<SpdyStream> stream = *it;
1198 created_streams_.erase(it); 1197 created_streams_.erase(it);
1199 LogAbandonedStream(stream, status); 1198 LogAbandonedStream(stream, status);
1200 stream->OnClose(status); 1199 stream->OnClose(status);
1201 } 1200 }
1202 1201
1203 write_queue_.RemovePendingWritesForStreamsAfter(last_good_stream_id); 1202 write_queue_.RemovePendingWritesForStreamsAfter(last_good_stream_id);
1204 } 1203 }
1205 1204
1206 void SpdySession::CloseAllStreams(net::Error status) { 1205 void SpdySession::CloseAllStreams(Error status) {
1207 base::StatsCounter abandoned_streams("spdy.abandoned_streams"); 1206 base::StatsCounter abandoned_streams("spdy.abandoned_streams");
1208 base::StatsCounter abandoned_push_streams( 1207 base::StatsCounter abandoned_push_streams(
1209 "spdy.abandoned_push_streams"); 1208 "spdy.abandoned_push_streams");
1210 1209
1211 if (!unclaimed_pushed_streams_.empty()) { 1210 if (!unclaimed_pushed_streams_.empty()) {
1212 streams_abandoned_count_ += unclaimed_pushed_streams_.size(); 1211 streams_abandoned_count_ += unclaimed_pushed_streams_.size();
1213 abandoned_push_streams.Add(unclaimed_pushed_streams_.size()); 1212 abandoned_push_streams.Add(unclaimed_pushed_streams_.size());
1214 unclaimed_pushed_streams_.clear(); 1213 unclaimed_pushed_streams_.clear();
1215 } 1214 }
1216 1215
1217 CloseAllStreamsAfter(0, status); 1216 CloseAllStreamsAfter(0, status);
1218 write_queue_.Clear(); 1217 write_queue_.Clear();
1219 } 1218 }
1220 1219
1221 void SpdySession::LogAbandonedStream(const scoped_refptr<SpdyStream>& stream, 1220 void SpdySession::LogAbandonedStream(const scoped_refptr<SpdyStream>& stream,
1222 net::Error status) { 1221 Error status) {
1223 DCHECK(stream); 1222 DCHECK(stream);
1224 std::string description = base::StringPrintf( 1223 std::string description = base::StringPrintf(
1225 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path(); 1224 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path();
1226 stream->LogStreamError(status, description); 1225 stream->LogStreamError(status, description);
1227 } 1226 }
1228 1227
1229 int SpdySession::GetNewStreamId() { 1228 int SpdySession::GetNewStreamId() {
1230 int id = stream_hi_water_mark_; 1229 int id = stream_hi_water_mark_;
1231 stream_hi_water_mark_ += 2; 1230 stream_hi_water_mark_ += 2;
1232 if (stream_hi_water_mark_ > 0x7fff) 1231 if (stream_hi_water_mark_ > 0x7fff)
1233 stream_hi_water_mark_ = 1; 1232 stream_hi_water_mark_ = 1;
1234 return id; 1233 return id;
1235 } 1234 }
1236 1235
1237 void SpdySession::CloseSessionOnError(net::Error err, 1236 void SpdySession::CloseSessionOnError(Error err,
1238 bool remove_from_pool, 1237 bool remove_from_pool,
1239 const std::string& description) { 1238 const std::string& description) {
1240 // Closing all streams can have a side-effect of dropping the last reference 1239 // Closing all streams can have a side-effect of dropping the last reference
1241 // to |this|. Hold a reference through this function. 1240 // to |this|. Hold a reference through this function.
1242 scoped_refptr<SpdySession> self(this); 1241 scoped_refptr<SpdySession> self(this);
1243 1242
1244 DCHECK_LT(err, OK); 1243 DCHECK_LT(err, OK);
1245 net_log_.AddEvent( 1244 net_log_.AddEvent(
1246 NetLog::TYPE_SPDY_SESSION_CLOSE, 1245 NetLog::TYPE_SPDY_SESSION_CLOSE,
1247 base::Bind(&NetLogSpdySessionCloseCallback, err, &description)); 1246 base::Bind(&NetLogSpdySessionCloseCallback, err, &description));
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1452 if (!is_secure_) 1451 if (!is_secure_)
1453 return NULL; 1452 return NULL;
1454 return GetSSLClientSocket()->GetServerBoundCertService(); 1453 return GetSSLClientSocket()->GetServerBoundCertService();
1455 } 1454 }
1456 1455
1457 void SpdySession::OnError(SpdyFramer::SpdyError error_code) { 1456 void SpdySession::OnError(SpdyFramer::SpdyError error_code) {
1458 RecordProtocolErrorHistogram( 1457 RecordProtocolErrorHistogram(
1459 static_cast<SpdyProtocolErrorDetails>(error_code)); 1458 static_cast<SpdyProtocolErrorDetails>(error_code));
1460 std::string description = base::StringPrintf( 1459 std::string description = base::StringPrintf(
1461 "SPDY_ERROR error_code: %d.", error_code); 1460 "SPDY_ERROR error_code: %d.", error_code);
1462 CloseSessionOnError(net::ERR_SPDY_PROTOCOL_ERROR, true, description); 1461 CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, true, description);
1463 } 1462 }
1464 1463
1465 void SpdySession::OnStreamError(SpdyStreamId stream_id, 1464 void SpdySession::OnStreamError(SpdyStreamId stream_id,
1466 const std::string& description) { 1465 const std::string& description) {
1467 if (IsStreamActive(stream_id)) 1466 if (IsStreamActive(stream_id))
1468 ResetStream(stream_id, RST_STREAM_PROTOCOL_ERROR, description); 1467 ResetStream(stream_id, RST_STREAM_PROTOCOL_ERROR, description);
1469 } 1468 }
1470 1469
1471 void SpdySession::OnStreamFrameData(SpdyStreamId stream_id, 1470 void SpdySession::OnStreamFrameData(SpdyStreamId stream_id,
1472 const char* data, 1471 const char* data,
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
1785 1784
1786 void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id, 1785 void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id,
1787 SpdyGoAwayStatus status) { 1786 SpdyGoAwayStatus status) {
1788 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_GOAWAY, 1787 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_GOAWAY,
1789 base::Bind(&NetLogSpdyGoAwayCallback, 1788 base::Bind(&NetLogSpdyGoAwayCallback,
1790 last_accepted_stream_id, 1789 last_accepted_stream_id,
1791 active_streams_.size(), 1790 active_streams_.size(),
1792 unclaimed_pushed_streams_.size(), 1791 unclaimed_pushed_streams_.size(),
1793 status)); 1792 status));
1794 RemoveFromPool(); 1793 RemoveFromPool();
1795 CloseAllStreamsAfter(last_accepted_stream_id, net::ERR_ABORTED); 1794 CloseAllStreamsAfter(last_accepted_stream_id, ERR_ABORTED);
1796 } 1795 }
1797 1796
1798 void SpdySession::OnPing(uint32 unique_id) { 1797 void SpdySession::OnPing(uint32 unique_id) {
1799 net_log_.AddEvent( 1798 net_log_.AddEvent(
1800 NetLog::TYPE_SPDY_SESSION_PING, 1799 NetLog::TYPE_SPDY_SESSION_PING,
1801 base::Bind(&NetLogSpdyPingCallback, unique_id, "received")); 1800 base::Bind(&NetLogSpdyPingCallback, unique_id, "received"));
1802 1801
1803 // Send response to a PING from server. 1802 // Send response to a PING from server.
1804 if (unique_id % 2 == 0) { 1803 if (unique_id % 2 == 0) {
1805 WritePingFrame(unique_id); 1804 WritePingFrame(unique_id);
1806 return; 1805 return;
1807 } 1806 }
1808 1807
1809 --pings_in_flight_; 1808 --pings_in_flight_;
1810 if (pings_in_flight_ < 0) { 1809 if (pings_in_flight_ < 0) {
1811 RecordProtocolErrorHistogram(PROTOCOL_ERROR_UNEXPECTED_PING); 1810 RecordProtocolErrorHistogram(PROTOCOL_ERROR_UNEXPECTED_PING);
1812 CloseSessionOnError( 1811 CloseSessionOnError(
1813 net::ERR_SPDY_PROTOCOL_ERROR, true, "pings_in_flight_ is < 0."); 1812 ERR_SPDY_PROTOCOL_ERROR, true, "pings_in_flight_ is < 0.");
1814 pings_in_flight_ = 0; 1813 pings_in_flight_ = 0;
1815 return; 1814 return;
1816 } 1815 }
1817 1816
1818 if (pings_in_flight_ > 0) 1817 if (pings_in_flight_ > 0)
1819 return; 1818 return;
1820 1819
1821 // We will record RTT in histogram when there are no more client sent 1820 // We will record RTT in histogram when there are no more client sent
1822 // pings_in_flight_. 1821 // pings_in_flight_.
1823 RecordPingRTTHistogram(base::TimeTicks::Now() - last_ping_sent_time_); 1822 RecordPingRTTHistogram(base::TimeTicks::Now() - last_ping_sent_time_);
(...skipping 21 matching lines...) Expand all
1845 } 1844 }
1846 1845
1847 if ((stream_id != kSessionFlowControlStreamId) && 1846 if ((stream_id != kSessionFlowControlStreamId) &&
1848 !IsStreamActive(stream_id)) { 1847 !IsStreamActive(stream_id)) {
1849 LOG(WARNING) << "Received WINDOW_UPDATE for invalid stream " << stream_id; 1848 LOG(WARNING) << "Received WINDOW_UPDATE for invalid stream " << stream_id;
1850 return; 1849 return;
1851 } 1850 }
1852 1851
1853 if (delta_window_size < 1u) { 1852 if (delta_window_size < 1u) {
1854 if (stream_id == kSessionFlowControlStreamId) { 1853 if (stream_id == kSessionFlowControlStreamId) {
1855 LOG(WARNING) << "Received session WINDOW_UPDATE with an " 1854 RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE);
1856 << "invalid delta_window_size " << delta_window_size; 1855 CloseSessionOnError(
1857 // TODO(akalin): Figure out whether we should instead send a 1856 ERR_SPDY_PROTOCOL_ERROR,
1858 // GOAWAY and close the connection here. 1857 true,
1858 "Received WINDOW_UPDATE with an invalid delta_window_size " +
1859 base::UintToString(delta_window_size));
1859 } else { 1860 } else {
1860 ResetStream(stream_id, RST_STREAM_FLOW_CONTROL_ERROR, 1861 ResetStream(stream_id, RST_STREAM_FLOW_CONTROL_ERROR,
1861 base::StringPrintf( 1862 base::StringPrintf(
1862 "Received WINDOW_UPDATE with an invalid " 1863 "Received WINDOW_UPDATE with an invalid "
1863 "delta_window_size %ud", delta_window_size)); 1864 "delta_window_size %ud", delta_window_size));
1864 } 1865 }
1865 return; 1866 return;
1866 } 1867 }
1867 1868
1868 if (stream_id == kSessionFlowControlStreamId) { 1869 if (stream_id == kSessionFlowControlStreamId) {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1972 1973
1973 void SpdySession::HandleSetting(uint32 id, uint32 value) { 1974 void SpdySession::HandleSetting(uint32 id, uint32 value) {
1974 switch (id) { 1975 switch (id) {
1975 case SETTINGS_MAX_CONCURRENT_STREAMS: 1976 case SETTINGS_MAX_CONCURRENT_STREAMS:
1976 max_concurrent_streams_ = std::min(static_cast<size_t>(value), 1977 max_concurrent_streams_ = std::min(static_cast<size_t>(value),
1977 kMaxConcurrentStreamLimit); 1978 kMaxConcurrentStreamLimit);
1978 ProcessPendingStreamRequests(); 1979 ProcessPendingStreamRequests();
1979 break; 1980 break;
1980 case SETTINGS_INITIAL_WINDOW_SIZE: { 1981 case SETTINGS_INITIAL_WINDOW_SIZE: {
1981 if (flow_control_state_ < FLOW_CONTROL_STREAM) { 1982 if (flow_control_state_ < FLOW_CONTROL_STREAM) {
1982 LOG(WARNING) << "SETTINGS_INITIAL_WINDOW_SIZE setting received " 1983 net_log().AddEvent(
1983 << "when flow control is turned off"; 1984 NetLog::TYPE_SPDY_SESSION_INITIAL_WINDOW_SIZE_NO_FLOW_CONTROL);
1984 // TODO(akalin): Figure out whether we should instead send a
1985 // GOAWAY and close the connection here.
1986 return; 1985 return;
1987 } 1986 }
1988 1987
1989 if (static_cast<int32>(value) < 0) { 1988 if (value > static_cast<uint32>(kint32max)) {
1990 net_log().AddEvent( 1989 net_log().AddEvent(
1991 NetLog::TYPE_SPDY_SESSION_NEGATIVE_INITIAL_WINDOW_SIZE, 1990 NetLog::TYPE_SPDY_SESSION_INITIAL_WINDOW_SIZE_OUT_OF_RANGE,
1992 NetLog::IntegerCallback("initial_window_size", value)); 1991 NetLog::IntegerCallback("initial_window_size", value));
1993 return; 1992 return;
1994 } 1993 }
1995 1994
1996 // SETTINGS_INITIAL_WINDOW_SIZE updates initial_send_window_size_ only. 1995 // SETTINGS_INITIAL_WINDOW_SIZE updates initial_send_window_size_ only.
1997 int32 delta_window_size = value - stream_initial_send_window_size_; 1996 int32 delta_window_size =
1998 stream_initial_send_window_size_ = value; 1997 static_cast<int32>(value) - stream_initial_send_window_size_;
1998 stream_initial_send_window_size_ = static_cast<int32>(value);
1999 UpdateStreamsSendWindowSize(delta_window_size); 1999 UpdateStreamsSendWindowSize(delta_window_size);
2000 net_log().AddEvent( 2000 net_log().AddEvent(
2001 NetLog::TYPE_SPDY_SESSION_UPDATE_STREAMS_SEND_WINDOW_SIZE, 2001 NetLog::TYPE_SPDY_SESSION_UPDATE_STREAMS_SEND_WINDOW_SIZE,
2002 NetLog::IntegerCallback("delta_window_size", delta_window_size)); 2002 NetLog::IntegerCallback("delta_window_size", delta_window_size));
2003 break; 2003 break;
2004 } 2004 }
2005 } 2005 }
2006 } 2006 }
2007 2007
2008 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) { 2008 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
2094 check_ping_status_pending_ = false; 2094 check_ping_status_pending_ = false;
2095 return; 2095 return;
2096 } 2096 }
2097 2097
2098 DCHECK(check_ping_status_pending_); 2098 DCHECK(check_ping_status_pending_);
2099 2099
2100 base::TimeTicks now = base::TimeTicks::Now(); 2100 base::TimeTicks now = base::TimeTicks::Now();
2101 base::TimeDelta delay = hung_interval_ - (now - last_activity_time_); 2101 base::TimeDelta delay = hung_interval_ - (now - last_activity_time_);
2102 2102
2103 if (delay.InMilliseconds() < 0 || last_activity_time_ < last_check_time) { 2103 if (delay.InMilliseconds() < 0 || last_activity_time_ < last_check_time) {
2104 CloseSessionOnError(net::ERR_SPDY_PING_FAILED, true, "Failed ping."); 2104 CloseSessionOnError(ERR_SPDY_PING_FAILED, true, "Failed ping.");
2105 // Track all failed PING messages in a separate bucket. 2105 // Track all failed PING messages in a separate bucket.
2106 const base::TimeDelta kFailedPing = 2106 const base::TimeDelta kFailedPing =
2107 base::TimeDelta::FromInternalValue(INT_MAX); 2107 base::TimeDelta::FromInternalValue(INT_MAX);
2108 RecordPingRTTHistogram(kFailedPing); 2108 RecordPingRTTHistogram(kFailedPing);
2109 return; 2109 return;
2110 } 2110 }
2111 2111
2112 // Check the status of connection after a delay. 2112 // Check the status of connection after a delay.
2113 MessageLoop::current()->PostDelayedTask( 2113 MessageLoop::current()->PostDelayedTask(
2114 FROM_HERE, 2114 FROM_HERE,
2115 base::Bind(&SpdySession::CheckPingStatus, weak_factory_.GetWeakPtr(), 2115 base::Bind(&SpdySession::CheckPingStatus, weak_factory_.GetWeakPtr(),
2116 now), 2116 now),
2117 delay); 2117 delay);
2118 } 2118 }
2119 2119
2120 void SpdySession::RecordPingRTTHistogram(base::TimeDelta duration) { 2120 void SpdySession::RecordPingRTTHistogram(base::TimeDelta duration) {
2121 UMA_HISTOGRAM_TIMES("Net.SpdyPing.RTT", duration); 2121 UMA_HISTOGRAM_TIMES("Net.SpdyPing.RTT", duration);
2122 } 2122 }
2123 2123
2124 void SpdySession::RecordProtocolErrorHistogram( 2124 void SpdySession::RecordProtocolErrorHistogram(
2125 SpdyProtocolErrorDetails details) { 2125 SpdyProtocolErrorDetails details) {
2126 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionErrorDetails", details, 2126 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionErrorDetails2", details,
2127 NUM_SPDY_PROTOCOL_ERROR_DETAILS); 2127 NUM_SPDY_PROTOCOL_ERROR_DETAILS);
2128 if (EndsWith(host_port_pair().host(), "google.com", false)) { 2128 if (EndsWith(host_port_pair().host(), "google.com", false)) {
2129 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionErrorDetails_Google", details, 2129 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionErrorDetails_Google2", details,
2130 NUM_SPDY_PROTOCOL_ERROR_DETAILS); 2130 NUM_SPDY_PROTOCOL_ERROR_DETAILS);
2131 } 2131 }
2132 } 2132 }
2133 2133
2134 void SpdySession::RecordHistograms() { 2134 void SpdySession::RecordHistograms() {
2135 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession", 2135 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession",
2136 streams_initiated_count_, 2136 streams_initiated_count_,
2137 0, 300, 50); 2137 0, 300, 50);
2138 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedPerSession", 2138 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedPerSession",
2139 streams_pushed_count_, 2139 streams_pushed_count_,
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
2243 // a WINDOW_UPDATE frame. 2243 // a WINDOW_UPDATE frame.
2244 } 2244 }
2245 2245
2246 void SpdySession::IncreaseSendWindowSize(int32 delta_window_size) { 2246 void SpdySession::IncreaseSendWindowSize(int32 delta_window_size) {
2247 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 2247 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION);
2248 DCHECK_GE(delta_window_size, 1); 2248 DCHECK_GE(delta_window_size, 1);
2249 2249
2250 // Check for overflow. 2250 // Check for overflow.
2251 int32 max_delta_window_size = kint32max - session_send_window_size_; 2251 int32 max_delta_window_size = kint32max - session_send_window_size_;
2252 if (delta_window_size > max_delta_window_size) { 2252 if (delta_window_size > max_delta_window_size) {
2253 LOG(WARNING) << "Received WINDOW_UPDATE [delta: " 2253 RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE);
2254 << delta_window_size 2254 CloseSessionOnError(
2255 << "] for session overflows session_send_window_size_ " 2255 ERR_SPDY_PROTOCOL_ERROR,
2256 << "[current: " << session_send_window_size_ << "]"; 2256 true,
2257 // TODO(akalin): Figure out whether we should instead send a 2257 "Received WINDOW_UPDATE [delta: " +
2258 // GOAWAY and close the connection here. 2258 base::IntToString(delta_window_size) +
jar (doing other things) 2013/04/19 23:12:38 nit: Probably indent this 4 more than the argument
2259 "] for session overflows session_send_window_size_ [current: " +
2260 base::IntToString(session_send_window_size_) + "]");
2259 return; 2261 return;
2260 } 2262 }
2261 2263
2262 session_send_window_size_ += delta_window_size; 2264 session_send_window_size_ += delta_window_size;
2263 2265
2264 net_log_.AddEvent( 2266 net_log_.AddEvent(
2265 NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW, 2267 NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW,
2266 base::Bind(&NetLogSpdySessionWindowUpdateCallback, 2268 base::Bind(&NetLogSpdySessionWindowUpdateCallback,
2267 delta_window_size, session_send_window_size_)); 2269 delta_window_size, session_send_window_size_));
2268 2270
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2319 session_unacked_recv_window_bytes_, 2321 session_unacked_recv_window_bytes_,
2320 HIGHEST); 2322 HIGHEST);
2321 session_unacked_recv_window_bytes_ = 0; 2323 session_unacked_recv_window_bytes_ = 0;
2322 } 2324 }
2323 } 2325 }
2324 2326
2325 void SpdySession::DecreaseRecvWindowSize(int32 delta_window_size) { 2327 void SpdySession::DecreaseRecvWindowSize(int32 delta_window_size) {
2326 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 2328 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION);
2327 DCHECK_GE(delta_window_size, 1); 2329 DCHECK_GE(delta_window_size, 1);
2328 2330
2329 // |delta_window_size| should never cause 2331 // Since we never decrease the initial receive window size,
2330 // |session_recv_window_size_| to go negative. If we do, it's a 2332 // |delta_window_size| should never cause |recv_window_size_| to go
2331 // client-side bug. 2333 // negative. If we do, the receive window isn't being respected.
2332 if (delta_window_size > session_recv_window_size_) { 2334 if (delta_window_size > session_recv_window_size_) {
2333 NOTREACHED() << "Received session WINDOW_UPDATE with an " 2335 RecordProtocolErrorHistogram(PROTOCOL_ERROR_RECEIVE_WINDOW_VIOLATION);
2334 << "invalid delta_window_size " << delta_window_size; 2336 CloseSessionOnError(
2335 // TODO(akalin): Figure out whether we should instead send a 2337 ERR_SPDY_PROTOCOL_ERROR,
2336 // GOAWAY and close the connection here. 2338 true,
2339 "delta_window_size is " + base::IntToString(delta_window_size) +
2340 " in DecreaseRecvWindowSize, which is larger than the receive " +
jar (doing other things) 2013/04/19 23:12:38 nit: indent 4 more? same on line 1859
2341 "window size of " + base::IntToString(session_recv_window_size_));
2337 return; 2342 return;
2338 } 2343 }
2339 2344
2340 session_recv_window_size_ -= delta_window_size; 2345 session_recv_window_size_ -= delta_window_size;
2341 net_log_.AddEvent( 2346 net_log_.AddEvent(
2342 NetLog::TYPE_SPDY_SESSION_UPDATE_RECV_WINDOW, 2347 NetLog::TYPE_SPDY_SESSION_UPDATE_RECV_WINDOW,
2343 base::Bind(&NetLogSpdySessionWindowUpdateCallback, 2348 base::Bind(&NetLogSpdySessionWindowUpdateCallback,
2344 -delta_window_size, session_recv_window_size_)); 2349 -delta_window_size, session_recv_window_size_));
2345 } 2350 }
2346 2351
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2399 if (!queue->empty()) { 2404 if (!queue->empty()) {
2400 SpdyStreamId stream_id = queue->front(); 2405 SpdyStreamId stream_id = queue->front();
2401 queue->pop_front(); 2406 queue->pop_front();
2402 return stream_id; 2407 return stream_id;
2403 } 2408 }
2404 } 2409 }
2405 return 0; 2410 return 0;
2406 } 2411 }
2407 2412
2408 } // namespace net 2413 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698