| OLD | NEW |
| 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" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 const SpdyStreamId kFirstStreamId = 1; | 53 const SpdyStreamId kFirstStreamId = 1; |
| 54 | 54 |
| 55 // Minimum seconds that unclaimed pushed streams will be kept in memory. | 55 // Minimum seconds that unclaimed pushed streams will be kept in memory. |
| 56 const int kMinPushedStreamLifetimeSeconds = 300; | 56 const int kMinPushedStreamLifetimeSeconds = 300; |
| 57 | 57 |
| 58 scoped_ptr<base::ListValue> SpdyHeaderBlockToListValue( | 58 scoped_ptr<base::ListValue> SpdyHeaderBlockToListValue( |
| 59 const SpdyHeaderBlock& headers, | 59 const SpdyHeaderBlock& headers, |
| 60 net::NetLog::LogLevel log_level) { | 60 net::NetLog::LogLevel log_level) { |
| 61 scoped_ptr<base::ListValue> headers_list(new base::ListValue()); | 61 scoped_ptr<base::ListValue> headers_list(new base::ListValue()); |
| 62 for (SpdyHeaderBlock::const_iterator it = headers.begin(); | 62 for (SpdyHeaderBlock::const_iterator it = headers.begin(); |
| 63 it != headers.end(); ++it) { | 63 it != headers.end(); |
| 64 ++it) { |
| 64 headers_list->AppendString( | 65 headers_list->AppendString( |
| 65 it->first + ": " + | 66 it->first + ": " + |
| 66 ElideHeaderValueForNetLog(log_level, it->first, it->second)); | 67 ElideHeaderValueForNetLog(log_level, it->first, it->second)); |
| 67 } | 68 } |
| 68 return headers_list.Pass(); | 69 return headers_list.Pass(); |
| 69 } | 70 } |
| 70 | 71 |
| 71 base::Value* NetLogSpdySynStreamSentCallback(const SpdyHeaderBlock* headers, | 72 base::Value* NetLogSpdySynStreamSentCallback(const SpdyHeaderBlock* headers, |
| 72 bool fin, | 73 bool fin, |
| 73 bool unidirectional, | 74 bool unidirectional, |
| 74 SpdyPriority spdy_priority, | 75 SpdyPriority spdy_priority, |
| 75 SpdyStreamId stream_id, | 76 SpdyStreamId stream_id, |
| 76 NetLog::LogLevel log_level) { | 77 NetLog::LogLevel log_level) { |
| 77 base::DictionaryValue* dict = new base::DictionaryValue(); | 78 base::DictionaryValue* dict = new base::DictionaryValue(); |
| 78 dict->Set("headers", | 79 dict->Set("headers", |
| 79 SpdyHeaderBlockToListValue(*headers, log_level).release()); | 80 SpdyHeaderBlockToListValue(*headers, log_level).release()); |
| 80 dict->SetBoolean("fin", fin); | 81 dict->SetBoolean("fin", fin); |
| 81 dict->SetBoolean("unidirectional", unidirectional); | 82 dict->SetBoolean("unidirectional", unidirectional); |
| 82 dict->SetInteger("spdy_priority", static_cast<int>(spdy_priority)); | 83 dict->SetInteger("spdy_priority", static_cast<int>(spdy_priority)); |
| 83 dict->SetInteger("stream_id", stream_id); | 84 dict->SetInteger("stream_id", stream_id); |
| 84 return dict; | 85 return dict; |
| 85 } | 86 } |
| 86 | 87 |
| 87 base::Value* NetLogSpdySynStreamReceivedCallback( | 88 base::Value* NetLogSpdySynStreamReceivedCallback(const SpdyHeaderBlock* headers, |
| 88 const SpdyHeaderBlock* headers, | 89 bool fin, |
| 89 bool fin, | 90 bool unidirectional, |
| 90 bool unidirectional, | 91 SpdyPriority spdy_priority, |
| 91 SpdyPriority spdy_priority, | 92 SpdyStreamId stream_id, |
| 92 SpdyStreamId stream_id, | 93 SpdyStreamId associated_stream, |
| 93 SpdyStreamId associated_stream, | 94 NetLog::LogLevel log_level) { |
| 94 NetLog::LogLevel log_level) { | |
| 95 base::DictionaryValue* dict = new base::DictionaryValue(); | 95 base::DictionaryValue* dict = new base::DictionaryValue(); |
| 96 dict->Set("headers", | 96 dict->Set("headers", |
| 97 SpdyHeaderBlockToListValue(*headers, log_level).release()); | 97 SpdyHeaderBlockToListValue(*headers, log_level).release()); |
| 98 dict->SetBoolean("fin", fin); | 98 dict->SetBoolean("fin", fin); |
| 99 dict->SetBoolean("unidirectional", unidirectional); | 99 dict->SetBoolean("unidirectional", unidirectional); |
| 100 dict->SetInteger("spdy_priority", static_cast<int>(spdy_priority)); | 100 dict->SetInteger("spdy_priority", static_cast<int>(spdy_priority)); |
| 101 dict->SetInteger("stream_id", stream_id); | 101 dict->SetInteger("stream_id", stream_id); |
| 102 dict->SetInteger("associated_stream", associated_stream); | 102 dict->SetInteger("associated_stream", associated_stream); |
| 103 return dict; | 103 return dict; |
| 104 } | 104 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 dict->SetInteger("flags", flags); | 151 dict->SetInteger("flags", flags); |
| 152 dict->SetInteger("value", value); | 152 dict->SetInteger("value", value); |
| 153 return dict; | 153 return dict; |
| 154 } | 154 } |
| 155 | 155 |
| 156 base::Value* NetLogSpdySendSettingsCallback(const SettingsMap* settings, | 156 base::Value* NetLogSpdySendSettingsCallback(const SettingsMap* settings, |
| 157 NetLog::LogLevel /* log_level */) { | 157 NetLog::LogLevel /* log_level */) { |
| 158 base::DictionaryValue* dict = new base::DictionaryValue(); | 158 base::DictionaryValue* dict = new base::DictionaryValue(); |
| 159 base::ListValue* settings_list = new base::ListValue(); | 159 base::ListValue* settings_list = new base::ListValue(); |
| 160 for (SettingsMap::const_iterator it = settings->begin(); | 160 for (SettingsMap::const_iterator it = settings->begin(); |
| 161 it != settings->end(); ++it) { | 161 it != settings->end(); |
| 162 ++it) { |
| 162 const SpdySettingsIds id = it->first; | 163 const SpdySettingsIds id = it->first; |
| 163 const SpdySettingsFlags flags = it->second.first; | 164 const SpdySettingsFlags flags = it->second.first; |
| 164 const uint32 value = it->second.second; | 165 const uint32 value = it->second.second; |
| 165 settings_list->Append(new base::StringValue( | 166 settings_list->Append(new base::StringValue( |
| 166 base::StringPrintf("[id:%u flags:%u value:%u]", id, flags, value))); | 167 base::StringPrintf("[id:%u flags:%u value:%u]", id, flags, value))); |
| 167 } | 168 } |
| 168 dict->Set("settings", settings_list); | 169 dict->Set("settings", settings_list); |
| 169 return dict; | 170 return dict; |
| 170 } | 171 } |
| 171 | 172 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 dict->SetBoolean("is_ack", is_ack); | 222 dict->SetBoolean("is_ack", is_ack); |
| 222 return dict; | 223 return dict; |
| 223 } | 224 } |
| 224 | 225 |
| 225 base::Value* NetLogSpdyGoAwayCallback(SpdyStreamId last_stream_id, | 226 base::Value* NetLogSpdyGoAwayCallback(SpdyStreamId last_stream_id, |
| 226 int active_streams, | 227 int active_streams, |
| 227 int unclaimed_streams, | 228 int unclaimed_streams, |
| 228 SpdyGoAwayStatus status, | 229 SpdyGoAwayStatus status, |
| 229 NetLog::LogLevel /* log_level */) { | 230 NetLog::LogLevel /* log_level */) { |
| 230 base::DictionaryValue* dict = new base::DictionaryValue(); | 231 base::DictionaryValue* dict = new base::DictionaryValue(); |
| 231 dict->SetInteger("last_accepted_stream_id", | 232 dict->SetInteger("last_accepted_stream_id", static_cast<int>(last_stream_id)); |
| 232 static_cast<int>(last_stream_id)); | |
| 233 dict->SetInteger("active_streams", active_streams); | 233 dict->SetInteger("active_streams", active_streams); |
| 234 dict->SetInteger("unclaimed_streams", unclaimed_streams); | 234 dict->SetInteger("unclaimed_streams", unclaimed_streams); |
| 235 dict->SetInteger("status", static_cast<int>(status)); | 235 dict->SetInteger("status", static_cast<int>(status)); |
| 236 return dict; | 236 return dict; |
| 237 } | 237 } |
| 238 | 238 |
| 239 // Helper function to return the total size of an array of objects | 239 // Helper function to return the total size of an array of objects |
| 240 // with .size() member functions. | 240 // with .size() member functions. |
| 241 template <typename T, size_t N> size_t GetTotalSize(const T (&arr)[N]) { | 241 template <typename T, size_t N> |
| 242 size_t GetTotalSize(const T (&arr)[N]) { |
| 242 size_t total_size = 0; | 243 size_t total_size = 0; |
| 243 for (size_t i = 0; i < N; ++i) { | 244 for (size_t i = 0; i < N; ++i) { |
| 244 total_size += arr[i].size(); | 245 total_size += arr[i].size(); |
| 245 } | 246 } |
| 246 return total_size; | 247 return total_size; |
| 247 } | 248 } |
| 248 | 249 |
| 249 // Helper class for std:find_if on STL container containing | 250 // Helper class for std:find_if on STL container containing |
| 250 // SpdyStreamRequest weak pointers. | 251 // SpdyStreamRequest weak pointers. |
| 251 class RequestEquals { | 252 class RequestEquals { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 262 }; | 263 }; |
| 263 | 264 |
| 264 // The maximum number of concurrent streams we will ever create. Even if | 265 // The maximum number of concurrent streams we will ever create. Even if |
| 265 // the server permits more, we will never exceed this limit. | 266 // the server permits more, we will never exceed this limit. |
| 266 const size_t kMaxConcurrentStreamLimit = 256; | 267 const size_t kMaxConcurrentStreamLimit = 256; |
| 267 | 268 |
| 268 } // namespace | 269 } // namespace |
| 269 | 270 |
| 270 SpdyProtocolErrorDetails MapFramerErrorToProtocolError( | 271 SpdyProtocolErrorDetails MapFramerErrorToProtocolError( |
| 271 SpdyFramer::SpdyError err) { | 272 SpdyFramer::SpdyError err) { |
| 272 switch(err) { | 273 switch (err) { |
| 273 case SpdyFramer::SPDY_NO_ERROR: | 274 case SpdyFramer::SPDY_NO_ERROR: |
| 274 return SPDY_ERROR_NO_ERROR; | 275 return SPDY_ERROR_NO_ERROR; |
| 275 case SpdyFramer::SPDY_INVALID_CONTROL_FRAME: | 276 case SpdyFramer::SPDY_INVALID_CONTROL_FRAME: |
| 276 return SPDY_ERROR_INVALID_CONTROL_FRAME; | 277 return SPDY_ERROR_INVALID_CONTROL_FRAME; |
| 277 case SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE: | 278 case SpdyFramer::SPDY_CONTROL_PAYLOAD_TOO_LARGE: |
| 278 return SPDY_ERROR_CONTROL_PAYLOAD_TOO_LARGE; | 279 return SPDY_ERROR_CONTROL_PAYLOAD_TOO_LARGE; |
| 279 case SpdyFramer::SPDY_ZLIB_INIT_FAILURE: | 280 case SpdyFramer::SPDY_ZLIB_INIT_FAILURE: |
| 280 return SPDY_ERROR_ZLIB_INIT_FAILURE; | 281 return SPDY_ERROR_ZLIB_INIT_FAILURE; |
| 281 case SpdyFramer::SPDY_UNSUPPORTED_VERSION: | 282 case SpdyFramer::SPDY_UNSUPPORTED_VERSION: |
| 282 return SPDY_ERROR_UNSUPPORTED_VERSION; | 283 return SPDY_ERROR_UNSUPPORTED_VERSION; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 295 case SpdyFramer::SPDY_UNEXPECTED_FRAME: | 296 case SpdyFramer::SPDY_UNEXPECTED_FRAME: |
| 296 return SPDY_ERROR_UNEXPECTED_FRAME; | 297 return SPDY_ERROR_UNEXPECTED_FRAME; |
| 297 default: | 298 default: |
| 298 NOTREACHED(); | 299 NOTREACHED(); |
| 299 return static_cast<SpdyProtocolErrorDetails>(-1); | 300 return static_cast<SpdyProtocolErrorDetails>(-1); |
| 300 } | 301 } |
| 301 } | 302 } |
| 302 | 303 |
| 303 SpdyProtocolErrorDetails MapRstStreamStatusToProtocolError( | 304 SpdyProtocolErrorDetails MapRstStreamStatusToProtocolError( |
| 304 SpdyRstStreamStatus status) { | 305 SpdyRstStreamStatus status) { |
| 305 switch(status) { | 306 switch (status) { |
| 306 case RST_STREAM_PROTOCOL_ERROR: | 307 case RST_STREAM_PROTOCOL_ERROR: |
| 307 return STATUS_CODE_PROTOCOL_ERROR; | 308 return STATUS_CODE_PROTOCOL_ERROR; |
| 308 case RST_STREAM_INVALID_STREAM: | 309 case RST_STREAM_INVALID_STREAM: |
| 309 return STATUS_CODE_INVALID_STREAM; | 310 return STATUS_CODE_INVALID_STREAM; |
| 310 case RST_STREAM_REFUSED_STREAM: | 311 case RST_STREAM_REFUSED_STREAM: |
| 311 return STATUS_CODE_REFUSED_STREAM; | 312 return STATUS_CODE_REFUSED_STREAM; |
| 312 case RST_STREAM_UNSUPPORTED_VERSION: | 313 case RST_STREAM_UNSUPPORTED_VERSION: |
| 313 return STATUS_CODE_UNSUPPORTED_VERSION; | 314 return STATUS_CODE_UNSUPPORTED_VERSION; |
| 314 case RST_STREAM_CANCEL: | 315 case RST_STREAM_CANCEL: |
| 315 return STATUS_CODE_CANCEL; | 316 return STATUS_CODE_CANCEL; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 338 } | 339 } |
| 339 | 340 |
| 340 SpdyStreamRequest::SpdyStreamRequest() : weak_ptr_factory_(this) { | 341 SpdyStreamRequest::SpdyStreamRequest() : weak_ptr_factory_(this) { |
| 341 Reset(); | 342 Reset(); |
| 342 } | 343 } |
| 343 | 344 |
| 344 SpdyStreamRequest::~SpdyStreamRequest() { | 345 SpdyStreamRequest::~SpdyStreamRequest() { |
| 345 CancelRequest(); | 346 CancelRequest(); |
| 346 } | 347 } |
| 347 | 348 |
| 348 int SpdyStreamRequest::StartRequest( | 349 int SpdyStreamRequest::StartRequest(SpdyStreamType type, |
| 349 SpdyStreamType type, | 350 const base::WeakPtr<SpdySession>& session, |
| 350 const base::WeakPtr<SpdySession>& session, | 351 const GURL& url, |
| 351 const GURL& url, | 352 RequestPriority priority, |
| 352 RequestPriority priority, | 353 const BoundNetLog& net_log, |
| 353 const BoundNetLog& net_log, | 354 const CompletionCallback& callback) { |
| 354 const CompletionCallback& callback) { | |
| 355 DCHECK(session); | 355 DCHECK(session); |
| 356 DCHECK(!session_); | 356 DCHECK(!session_); |
| 357 DCHECK(!stream_); | 357 DCHECK(!stream_); |
| 358 DCHECK(callback_.is_null()); | 358 DCHECK(callback_.is_null()); |
| 359 | 359 |
| 360 type_ = type; | 360 type_ = type; |
| 361 session_ = session; | 361 session_ = session; |
| 362 url_ = url; | 362 url_ = url; |
| 363 priority_ = priority; | 363 priority_ = priority; |
| 364 net_log_ = net_log; | 364 net_log_ = net_log; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 type_ = SPDY_BIDIRECTIONAL_STREAM; | 415 type_ = SPDY_BIDIRECTIONAL_STREAM; |
| 416 session_.reset(); | 416 session_.reset(); |
| 417 stream_.reset(); | 417 stream_.reset(); |
| 418 url_ = GURL(); | 418 url_ = GURL(); |
| 419 priority_ = MINIMUM_PRIORITY; | 419 priority_ = MINIMUM_PRIORITY; |
| 420 net_log_ = BoundNetLog(); | 420 net_log_ = BoundNetLog(); |
| 421 callback_.Reset(); | 421 callback_.Reset(); |
| 422 } | 422 } |
| 423 | 423 |
| 424 SpdySession::ActiveStreamInfo::ActiveStreamInfo() | 424 SpdySession::ActiveStreamInfo::ActiveStreamInfo() |
| 425 : stream(NULL), | 425 : stream(NULL), waiting_for_syn_reply(false) { |
| 426 waiting_for_syn_reply(false) {} | 426 } |
| 427 | 427 |
| 428 SpdySession::ActiveStreamInfo::ActiveStreamInfo(SpdyStream* stream) | 428 SpdySession::ActiveStreamInfo::ActiveStreamInfo(SpdyStream* stream) |
| 429 : stream(stream), | 429 : stream(stream), |
| 430 waiting_for_syn_reply(stream->type() != SPDY_PUSH_STREAM) {} | 430 waiting_for_syn_reply(stream->type() != SPDY_PUSH_STREAM) { |
| 431 } |
| 431 | 432 |
| 432 SpdySession::ActiveStreamInfo::~ActiveStreamInfo() {} | 433 SpdySession::ActiveStreamInfo::~ActiveStreamInfo() { |
| 434 } |
| 433 | 435 |
| 434 SpdySession::PushedStreamInfo::PushedStreamInfo() : stream_id(0) {} | 436 SpdySession::PushedStreamInfo::PushedStreamInfo() : stream_id(0) { |
| 437 } |
| 435 | 438 |
| 436 SpdySession::PushedStreamInfo::PushedStreamInfo( | 439 SpdySession::PushedStreamInfo::PushedStreamInfo(SpdyStreamId stream_id, |
| 437 SpdyStreamId stream_id, | 440 base::TimeTicks creation_time) |
| 438 base::TimeTicks creation_time) | 441 : stream_id(stream_id), creation_time(creation_time) { |
| 439 : stream_id(stream_id), | 442 } |
| 440 creation_time(creation_time) {} | |
| 441 | 443 |
| 442 SpdySession::PushedStreamInfo::~PushedStreamInfo() {} | 444 SpdySession::PushedStreamInfo::~PushedStreamInfo() { |
| 445 } |
| 443 | 446 |
| 444 SpdySession::SpdySession( | 447 SpdySession::SpdySession( |
| 445 const SpdySessionKey& spdy_session_key, | 448 const SpdySessionKey& spdy_session_key, |
| 446 const base::WeakPtr<HttpServerProperties>& http_server_properties, | 449 const base::WeakPtr<HttpServerProperties>& http_server_properties, |
| 447 bool verify_domain_authentication, | 450 bool verify_domain_authentication, |
| 448 bool enable_sending_initial_data, | 451 bool enable_sending_initial_data, |
| 449 bool enable_compression, | 452 bool enable_compression, |
| 450 bool enable_ping_based_connection_checking, | 453 bool enable_ping_based_connection_checking, |
| 451 NextProto default_protocol, | 454 NextProto default_protocol, |
| 452 size_t stream_initial_recv_window_size, | 455 size_t stream_initial_recv_window_size, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 463 read_buffer_(new IOBuffer(kReadBufferSize)), | 466 read_buffer_(new IOBuffer(kReadBufferSize)), |
| 464 stream_hi_water_mark_(kFirstStreamId), | 467 stream_hi_water_mark_(kFirstStreamId), |
| 465 in_flight_write_frame_type_(DATA), | 468 in_flight_write_frame_type_(DATA), |
| 466 in_flight_write_frame_size_(0), | 469 in_flight_write_frame_size_(0), |
| 467 is_secure_(false), | 470 is_secure_(false), |
| 468 certificate_error_code_(OK), | 471 certificate_error_code_(OK), |
| 469 availability_state_(STATE_AVAILABLE), | 472 availability_state_(STATE_AVAILABLE), |
| 470 read_state_(READ_STATE_DO_READ), | 473 read_state_(READ_STATE_DO_READ), |
| 471 write_state_(WRITE_STATE_IDLE), | 474 write_state_(WRITE_STATE_IDLE), |
| 472 error_on_close_(OK), | 475 error_on_close_(OK), |
| 473 max_concurrent_streams_(initial_max_concurrent_streams == 0 ? | 476 max_concurrent_streams_(initial_max_concurrent_streams == 0 |
| 474 kInitialMaxConcurrentStreams : | 477 ? kInitialMaxConcurrentStreams |
| 475 initial_max_concurrent_streams), | 478 : initial_max_concurrent_streams), |
| 476 max_concurrent_streams_limit_(max_concurrent_streams_limit == 0 ? | 479 max_concurrent_streams_limit_(max_concurrent_streams_limit == 0 |
| 477 kMaxConcurrentStreamLimit : | 480 ? kMaxConcurrentStreamLimit |
| 478 max_concurrent_streams_limit), | 481 : max_concurrent_streams_limit), |
| 479 streams_initiated_count_(0), | 482 streams_initiated_count_(0), |
| 480 streams_pushed_count_(0), | 483 streams_pushed_count_(0), |
| 481 streams_pushed_and_claimed_count_(0), | 484 streams_pushed_and_claimed_count_(0), |
| 482 streams_abandoned_count_(0), | 485 streams_abandoned_count_(0), |
| 483 total_bytes_received_(0), | 486 total_bytes_received_(0), |
| 484 sent_settings_(false), | 487 sent_settings_(false), |
| 485 received_settings_(false), | 488 received_settings_(false), |
| 486 stalled_streams_(0), | 489 stalled_streams_(0), |
| 487 pings_in_flight_(0), | 490 pings_in_flight_(0), |
| 488 next_ping_id_(1), | 491 next_ping_id_(1), |
| 489 last_activity_time_(time_func()), | 492 last_activity_time_(time_func()), |
| 490 last_compressed_frame_len_(0), | 493 last_compressed_frame_len_(0), |
| 491 check_ping_status_pending_(false), | 494 check_ping_status_pending_(false), |
| 492 send_connection_header_prefix_(false), | 495 send_connection_header_prefix_(false), |
| 493 flow_control_state_(FLOW_CONTROL_NONE), | 496 flow_control_state_(FLOW_CONTROL_NONE), |
| 494 stream_initial_send_window_size_(kSpdyStreamInitialWindowSize), | 497 stream_initial_send_window_size_(kSpdyStreamInitialWindowSize), |
| 495 stream_initial_recv_window_size_(stream_initial_recv_window_size == 0 ? | 498 stream_initial_recv_window_size_(stream_initial_recv_window_size == 0 |
| 496 kDefaultInitialRecvWindowSize : | 499 ? kDefaultInitialRecvWindowSize |
| 497 stream_initial_recv_window_size), | 500 : stream_initial_recv_window_size), |
| 498 session_send_window_size_(0), | 501 session_send_window_size_(0), |
| 499 session_recv_window_size_(0), | 502 session_recv_window_size_(0), |
| 500 session_unacked_recv_window_bytes_(0), | 503 session_unacked_recv_window_bytes_(0), |
| 501 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)), | 504 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)), |
| 502 verify_domain_authentication_(verify_domain_authentication), | 505 verify_domain_authentication_(verify_domain_authentication), |
| 503 enable_sending_initial_data_(enable_sending_initial_data), | 506 enable_sending_initial_data_(enable_sending_initial_data), |
| 504 enable_compression_(enable_compression), | 507 enable_compression_(enable_compression), |
| 505 enable_ping_based_connection_checking_( | 508 enable_ping_based_connection_checking_( |
| 506 enable_ping_based_connection_checking), | 509 enable_ping_based_connection_checking), |
| 507 protocol_(default_protocol), | 510 protocol_(default_protocol), |
| 508 connection_at_risk_of_loss_time_( | 511 connection_at_risk_of_loss_time_( |
| 509 base::TimeDelta::FromSeconds(kDefaultConnectionAtRiskOfLossSeconds)), | 512 base::TimeDelta::FromSeconds(kDefaultConnectionAtRiskOfLossSeconds)), |
| 510 hung_interval_( | 513 hung_interval_(base::TimeDelta::FromSeconds(kHungIntervalSeconds)), |
| 511 base::TimeDelta::FromSeconds(kHungIntervalSeconds)), | |
| 512 trusted_spdy_proxy_(trusted_spdy_proxy), | 514 trusted_spdy_proxy_(trusted_spdy_proxy), |
| 513 time_func_(time_func) { | 515 time_func_(time_func) { |
| 514 DCHECK_GE(protocol_, kProtoSPDYMinimumVersion); | 516 DCHECK_GE(protocol_, kProtoSPDYMinimumVersion); |
| 515 DCHECK_LE(protocol_, kProtoSPDYMaximumVersion); | 517 DCHECK_LE(protocol_, kProtoSPDYMaximumVersion); |
| 516 DCHECK(HttpStreamFactory::spdy_enabled()); | 518 DCHECK(HttpStreamFactory::spdy_enabled()); |
| 517 net_log_.BeginEvent( | 519 net_log_.BeginEvent( |
| 518 NetLog::TYPE_SPDY_SESSION, | 520 NetLog::TYPE_SPDY_SESSION, |
| 519 base::Bind(&NetLogSpdySessionCallback, &host_port_proxy_pair())); | 521 base::Bind(&NetLogSpdySessionCallback, &host_port_proxy_pair())); |
| 520 next_unclaimed_push_stream_sweep_time_ = time_func_() + | 522 next_unclaimed_push_stream_sweep_time_ = |
| 523 time_func_() + |
| 521 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); | 524 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); |
| 522 // TODO(mbelshe): consider randomization of the stream_hi_water_mark. | 525 // TODO(mbelshe): consider randomization of the stream_hi_water_mark. |
| 523 } | 526 } |
| 524 | 527 |
| 525 SpdySession::~SpdySession() { | 528 SpdySession::~SpdySession() { |
| 526 CHECK(!in_io_loop_); | 529 CHECK(!in_io_loop_); |
| 527 DCHECK(!pool_); | 530 DCHECK(!pool_); |
| 528 DcheckClosed(); | 531 DcheckClosed(); |
| 529 | 532 |
| 530 // TODO(akalin): Check connection->is_initialized() instead. This | 533 // TODO(akalin): Check connection->is_initialized() instead. This |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 if (protocol_ >= kProtoSPDY31) { | 579 if (protocol_ >= kProtoSPDY31) { |
| 577 flow_control_state_ = FLOW_CONTROL_STREAM_AND_SESSION; | 580 flow_control_state_ = FLOW_CONTROL_STREAM_AND_SESSION; |
| 578 session_send_window_size_ = kSpdySessionInitialWindowSize; | 581 session_send_window_size_ = kSpdySessionInitialWindowSize; |
| 579 session_recv_window_size_ = kSpdySessionInitialWindowSize; | 582 session_recv_window_size_ = kSpdySessionInitialWindowSize; |
| 580 } else if (protocol_ >= kProtoSPDY3) { | 583 } else if (protocol_ >= kProtoSPDY3) { |
| 581 flow_control_state_ = FLOW_CONTROL_STREAM; | 584 flow_control_state_ = FLOW_CONTROL_STREAM; |
| 582 } else { | 585 } else { |
| 583 flow_control_state_ = FLOW_CONTROL_NONE; | 586 flow_control_state_ = FLOW_CONTROL_NONE; |
| 584 } | 587 } |
| 585 | 588 |
| 586 buffered_spdy_framer_.reset( | 589 buffered_spdy_framer_.reset(new BufferedSpdyFramer( |
| 587 new BufferedSpdyFramer(NextProtoToSpdyMajorVersion(protocol_), | 590 NextProtoToSpdyMajorVersion(protocol_), enable_compression_)); |
| 588 enable_compression_)); | |
| 589 buffered_spdy_framer_->set_visitor(this); | 591 buffered_spdy_framer_->set_visitor(this); |
| 590 buffered_spdy_framer_->set_debug_visitor(this); | 592 buffered_spdy_framer_->set_debug_visitor(this); |
| 591 UMA_HISTOGRAM_ENUMERATION("Net.SpdyVersion", protocol_, kProtoMaximumVersion); | 593 UMA_HISTOGRAM_ENUMERATION("Net.SpdyVersion", protocol_, kProtoMaximumVersion); |
| 592 #if defined(SPDY_PROXY_AUTH_ORIGIN) | 594 #if defined(SPDY_PROXY_AUTH_ORIGIN) |
| 593 UMA_HISTOGRAM_BOOLEAN("Net.SpdySessions_DataReductionProxy", | 595 UMA_HISTOGRAM_BOOLEAN("Net.SpdySessions_DataReductionProxy", |
| 594 host_port_pair().Equals(HostPortPair::FromURL( | 596 host_port_pair().Equals(HostPortPair::FromURL( |
| 595 GURL(SPDY_PROXY_AUTH_ORIGIN)))); | 597 GURL(SPDY_PROXY_AUTH_ORIGIN)))); |
| 596 #endif | 598 #endif |
| 597 | 599 |
| 598 net_log_.AddEvent( | 600 net_log_.AddEvent( |
| 599 NetLog::TYPE_SPDY_SESSION_INITIALIZED, | 601 NetLog::TYPE_SPDY_SESSION_INITIALIZED, |
| 600 connection_->socket()->NetLog().source().ToEventParametersCallback()); | 602 connection_->socket()->NetLog().source().ToEventParametersCallback()); |
| 601 | 603 |
| 602 DCHECK_NE(availability_state_, STATE_CLOSED); | 604 DCHECK_NE(availability_state_, STATE_CLOSED); |
| 603 connection_->AddHigherLayeredPool(this); | 605 connection_->AddHigherLayeredPool(this); |
| 604 if (enable_sending_initial_data_) | 606 if (enable_sending_initial_data_) |
| 605 SendInitialData(); | 607 SendInitialData(); |
| 606 pool_ = pool; | 608 pool_ = pool; |
| 607 | 609 |
| 608 // Bootstrap the read loop. | 610 // Bootstrap the read loop. |
| 609 base::MessageLoop::current()->PostTask( | 611 base::MessageLoop::current()->PostTask(FROM_HERE, |
| 610 FROM_HERE, | 612 base::Bind(&SpdySession::PumpReadLoop, |
| 611 base::Bind(&SpdySession::PumpReadLoop, | 613 weak_factory_.GetWeakPtr(), |
| 612 weak_factory_.GetWeakPtr(), READ_STATE_DO_READ, OK)); | 614 READ_STATE_DO_READ, |
| 615 OK)); |
| 613 } | 616 } |
| 614 | 617 |
| 615 bool SpdySession::VerifyDomainAuthentication(const std::string& domain) { | 618 bool SpdySession::VerifyDomainAuthentication(const std::string& domain) { |
| 616 if (!verify_domain_authentication_) | 619 if (!verify_domain_authentication_) |
| 617 return true; | 620 return true; |
| 618 | 621 |
| 619 if (availability_state_ == STATE_CLOSED) | 622 if (availability_state_ == STATE_CLOSED) |
| 620 return false; | 623 return false; |
| 621 | 624 |
| 622 SSLInfo ssl_info; | 625 SSLInfo ssl_info; |
| 623 bool was_npn_negotiated; | 626 bool was_npn_negotiated; |
| 624 NextProto protocol_negotiated = kProtoUnknown; | 627 NextProto protocol_negotiated = kProtoUnknown; |
| 625 if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated)) | 628 if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated)) |
| 626 return true; // This is not a secure session, so all domains are okay. | 629 return true; // This is not a secure session, so all domains are okay. |
| 627 | 630 |
| 628 bool unused = false; | 631 bool unused = false; |
| 629 return | 632 return !ssl_info.client_cert_sent && |
| 630 !ssl_info.client_cert_sent && | 633 (!ssl_info.channel_id_sent || |
| 631 (!ssl_info.channel_id_sent || | 634 (ServerBoundCertService::GetDomainForHost(domain) == |
| 632 (ServerBoundCertService::GetDomainForHost(domain) == | 635 ServerBoundCertService::GetDomainForHost( |
| 633 ServerBoundCertService::GetDomainForHost(host_port_pair().host()))) && | 636 host_port_pair().host()))) && |
| 634 ssl_info.cert->VerifyNameMatch(domain, &unused); | 637 ssl_info.cert->VerifyNameMatch(domain, &unused); |
| 635 } | 638 } |
| 636 | 639 |
| 637 int SpdySession::GetPushStream( | 640 int SpdySession::GetPushStream(const GURL& url, |
| 638 const GURL& url, | 641 base::WeakPtr<SpdyStream>* stream, |
| 639 base::WeakPtr<SpdyStream>* stream, | 642 const BoundNetLog& stream_net_log) { |
| 640 const BoundNetLog& stream_net_log) { | |
| 641 CHECK(!in_io_loop_); | 643 CHECK(!in_io_loop_); |
| 642 | 644 |
| 643 stream->reset(); | 645 stream->reset(); |
| 644 | 646 |
| 645 // TODO(akalin): Add unit test exercising this code path. | 647 // TODO(akalin): Add unit test exercising this code path. |
| 646 if (availability_state_ == STATE_CLOSED) | 648 if (availability_state_ == STATE_CLOSED) |
| 647 return ERR_CONNECTION_CLOSED; | 649 return ERR_CONNECTION_CLOSED; |
| 648 | 650 |
| 649 Error err = TryAccessStream(url); | 651 Error err = TryAccessStream(url); |
| 650 if (err != OK) | 652 if (err != OK) |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 if (!connection_->socket()->IsConnected()) { | 739 if (!connection_->socket()->IsConnected()) { |
| 738 CloseSessionResult result = DoCloseSession( | 740 CloseSessionResult result = DoCloseSession( |
| 739 ERR_CONNECTION_CLOSED, | 741 ERR_CONNECTION_CLOSED, |
| 740 "Tried to create SPDY stream for a closed socket connection."); | 742 "Tried to create SPDY stream for a closed socket connection."); |
| 741 DCHECK_EQ(result, SESSION_CLOSED_AND_REMOVED); | 743 DCHECK_EQ(result, SESSION_CLOSED_AND_REMOVED); |
| 742 return ERR_CONNECTION_CLOSED; | 744 return ERR_CONNECTION_CLOSED; |
| 743 } | 745 } |
| 744 } | 746 } |
| 745 | 747 |
| 746 scoped_ptr<SpdyStream> new_stream( | 748 scoped_ptr<SpdyStream> new_stream( |
| 747 new SpdyStream(request.type(), GetWeakPtr(), request.url(), | 749 new SpdyStream(request.type(), |
| 750 GetWeakPtr(), |
| 751 request.url(), |
| 748 request.priority(), | 752 request.priority(), |
| 749 stream_initial_send_window_size_, | 753 stream_initial_send_window_size_, |
| 750 stream_initial_recv_window_size_, | 754 stream_initial_recv_window_size_, |
| 751 request.net_log())); | 755 request.net_log())); |
| 752 *stream = new_stream->GetWeakPtr(); | 756 *stream = new_stream->GetWeakPtr(); |
| 753 InsertCreatedStream(new_stream.Pass()); | 757 InsertCreatedStream(new_stream.Pass()); |
| 754 | 758 |
| 755 UMA_HISTOGRAM_CUSTOM_COUNTS( | 759 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 756 "Net.SpdyPriorityCount", | 760 "Net.SpdyPriorityCount", static_cast<int>(request.priority()), 0, 10, 11); |
| 757 static_cast<int>(request.priority()), 0, 10, 11); | |
| 758 | 761 |
| 759 return OK; | 762 return OK; |
| 760 } | 763 } |
| 761 | 764 |
| 762 void SpdySession::CancelStreamRequest( | 765 void SpdySession::CancelStreamRequest( |
| 763 const base::WeakPtr<SpdyStreamRequest>& request) { | 766 const base::WeakPtr<SpdyStreamRequest>& request) { |
| 764 DCHECK(request); | 767 DCHECK(request); |
| 765 RequestPriority priority = request->priority(); | 768 RequestPriority priority = request->priority(); |
| 766 CHECK_GE(priority, MINIMUM_PRIORITY); | 769 CHECK_GE(priority, MINIMUM_PRIORITY); |
| 767 CHECK_LE(priority, MAXIMUM_PRIORITY); | 770 CHECK_LE(priority, MAXIMUM_PRIORITY); |
| 768 | 771 |
| 769 #if DCHECK_IS_ON | 772 #if DCHECK_IS_ON |
| 770 // |request| should not be in a queue not matching its priority. | 773 // |request| should not be in a queue not matching its priority. |
| 771 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { | 774 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { |
| 772 if (priority == i) | 775 if (priority == i) |
| 773 continue; | 776 continue; |
| 774 PendingStreamRequestQueue* queue = &pending_create_stream_queues_[i]; | 777 PendingStreamRequestQueue* queue = &pending_create_stream_queues_[i]; |
| 775 DCHECK(std::find_if(queue->begin(), | 778 DCHECK(std::find_if(queue->begin(), queue->end(), RequestEquals(request)) == |
| 776 queue->end(), | 779 queue->end()); |
| 777 RequestEquals(request)) == queue->end()); | |
| 778 } | 780 } |
| 779 #endif | 781 #endif |
| 780 | 782 |
| 781 PendingStreamRequestQueue* queue = | 783 PendingStreamRequestQueue* queue = &pending_create_stream_queues_[priority]; |
| 782 &pending_create_stream_queues_[priority]; | |
| 783 // Remove |request| from |queue| while preserving the order of the | 784 // Remove |request| from |queue| while preserving the order of the |
| 784 // other elements. | 785 // other elements. |
| 785 PendingStreamRequestQueue::iterator it = | 786 PendingStreamRequestQueue::iterator it = |
| 786 std::find_if(queue->begin(), queue->end(), RequestEquals(request)); | 787 std::find_if(queue->begin(), queue->end(), RequestEquals(request)); |
| 787 // The request may already be removed if there's a | 788 // The request may already be removed if there's a |
| 788 // CompleteStreamRequest() in flight. | 789 // CompleteStreamRequest() in flight. |
| 789 if (it != queue->end()) { | 790 if (it != queue->end()) { |
| 790 it = queue->erase(it); | 791 it = queue->erase(it); |
| 791 // |request| should be in the queue at most once, and if it is | 792 // |request| should be in the queue at most once, and if it is |
| 792 // present, should not be pending completion. | 793 // present, should not be pending completion. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 812 void SpdySession::ProcessPendingStreamRequests() { | 813 void SpdySession::ProcessPendingStreamRequests() { |
| 813 // Like |max_concurrent_streams_|, 0 means infinite for | 814 // Like |max_concurrent_streams_|, 0 means infinite for |
| 814 // |max_requests_to_process|. | 815 // |max_requests_to_process|. |
| 815 size_t max_requests_to_process = 0; | 816 size_t max_requests_to_process = 0; |
| 816 if (max_concurrent_streams_ != 0) { | 817 if (max_concurrent_streams_ != 0) { |
| 817 max_requests_to_process = | 818 max_requests_to_process = |
| 818 max_concurrent_streams_ - | 819 max_concurrent_streams_ - |
| 819 (active_streams_.size() + created_streams_.size()); | 820 (active_streams_.size() + created_streams_.size()); |
| 820 } | 821 } |
| 821 for (size_t i = 0; | 822 for (size_t i = 0; |
| 822 max_requests_to_process == 0 || i < max_requests_to_process; ++i) { | 823 max_requests_to_process == 0 || i < max_requests_to_process; |
| 824 ++i) { |
| 823 base::WeakPtr<SpdyStreamRequest> pending_request = | 825 base::WeakPtr<SpdyStreamRequest> pending_request = |
| 824 GetNextPendingStreamRequest(); | 826 GetNextPendingStreamRequest(); |
| 825 if (!pending_request) | 827 if (!pending_request) |
| 826 break; | 828 break; |
| 827 | 829 |
| 828 base::MessageLoop::current()->PostTask( | 830 base::MessageLoop::current()->PostTask( |
| 829 FROM_HERE, | 831 FROM_HERE, |
| 830 base::Bind(&SpdySession::CompleteStreamRequest, | 832 base::Bind(&SpdySession::CompleteStreamRequest, |
| 831 weak_factory_.GetWeakPtr(), | 833 weak_factory_.GetWeakPtr(), |
| 832 pending_request)); | 834 pending_request)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 854 return false; | 856 return false; |
| 855 CloseSessionResult result = | 857 CloseSessionResult result = |
| 856 DoCloseSession(ERR_CONNECTION_CLOSED, "Closing one idle connection."); | 858 DoCloseSession(ERR_CONNECTION_CLOSED, "Closing one idle connection."); |
| 857 if (result != SESSION_CLOSED_AND_REMOVED) { | 859 if (result != SESSION_CLOSED_AND_REMOVED) { |
| 858 NOTREACHED(); | 860 NOTREACHED(); |
| 859 return false; | 861 return false; |
| 860 } | 862 } |
| 861 return true; | 863 return true; |
| 862 } | 864 } |
| 863 | 865 |
| 864 void SpdySession::EnqueueStreamWrite( | 866 void SpdySession::EnqueueStreamWrite(const base::WeakPtr<SpdyStream>& stream, |
| 865 const base::WeakPtr<SpdyStream>& stream, | 867 SpdyFrameType frame_type, |
| 866 SpdyFrameType frame_type, | 868 scoped_ptr<SpdyBufferProducer> producer) { |
| 867 scoped_ptr<SpdyBufferProducer> producer) { | 869 DCHECK(frame_type == HEADERS || frame_type == DATA || |
| 868 DCHECK(frame_type == HEADERS || | 870 frame_type == CREDENTIAL || frame_type == SYN_STREAM); |
| 869 frame_type == DATA || | |
| 870 frame_type == CREDENTIAL || | |
| 871 frame_type == SYN_STREAM); | |
| 872 EnqueueWrite(stream->priority(), frame_type, producer.Pass(), stream); | 871 EnqueueWrite(stream->priority(), frame_type, producer.Pass(), stream); |
| 873 } | 872 } |
| 874 | 873 |
| 875 scoped_ptr<SpdyFrame> SpdySession::CreateSynStream( | 874 scoped_ptr<SpdyFrame> SpdySession::CreateSynStream( |
| 876 SpdyStreamId stream_id, | 875 SpdyStreamId stream_id, |
| 877 RequestPriority priority, | 876 RequestPriority priority, |
| 878 SpdyControlFlags flags, | 877 SpdyControlFlags flags, |
| 879 const SpdyHeaderBlock& headers) { | 878 const SpdyHeaderBlock& headers) { |
| 880 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 879 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
| 881 CHECK(it != active_streams_.end()); | 880 CHECK(it != active_streams_.end()); |
| 882 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 881 CHECK_EQ(it->second.stream->stream_id(), stream_id); |
| 883 | 882 |
| 884 SendPrefacePingIfNoneInFlight(); | 883 SendPrefacePingIfNoneInFlight(); |
| 885 | 884 |
| 886 DCHECK(buffered_spdy_framer_.get()); | 885 DCHECK(buffered_spdy_framer_.get()); |
| 887 SpdyPriority spdy_priority = | 886 SpdyPriority spdy_priority = |
| 888 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()); | 887 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()); |
| 889 scoped_ptr<SpdyFrame> syn_frame( | 888 scoped_ptr<SpdyFrame> syn_frame(buffered_spdy_framer_->CreateSynStream( |
| 890 buffered_spdy_framer_->CreateSynStream(stream_id, 0, spdy_priority, flags, | 889 stream_id, 0, spdy_priority, flags, &headers)); |
| 891 &headers)); | |
| 892 | 890 |
| 893 base::StatsCounter spdy_requests("spdy.requests"); | 891 base::StatsCounter spdy_requests("spdy.requests"); |
| 894 spdy_requests.Increment(); | 892 spdy_requests.Increment(); |
| 895 streams_initiated_count_++; | 893 streams_initiated_count_++; |
| 896 | 894 |
| 897 if (net_log().IsLogging()) { | 895 if (net_log().IsLogging()) { |
| 898 net_log().AddEvent( | 896 net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_SYN_STREAM, |
| 899 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, | 897 base::Bind(&NetLogSpdySynStreamSentCallback, |
| 900 base::Bind(&NetLogSpdySynStreamSentCallback, &headers, | 898 &headers, |
| 901 (flags & CONTROL_FLAG_FIN) != 0, | 899 (flags & CONTROL_FLAG_FIN) != 0, |
| 902 (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0, | 900 (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0, |
| 903 spdy_priority, | 901 spdy_priority, |
| 904 stream_id)); | 902 stream_id)); |
| 905 } | 903 } |
| 906 | 904 |
| 907 return syn_frame.Pass(); | 905 return syn_frame.Pass(); |
| 908 } | 906 } |
| 909 | 907 |
| 910 scoped_ptr<SpdyBuffer> SpdySession::CreateDataBuffer(SpdyStreamId stream_id, | 908 scoped_ptr<SpdyBuffer> SpdySession::CreateDataBuffer(SpdyStreamId stream_id, |
| 911 IOBuffer* data, | 909 IOBuffer* data, |
| 912 int len, | 910 int len, |
| 913 SpdyDataFlags flags) { | 911 SpdyDataFlags flags) { |
| 914 if (availability_state_ == STATE_CLOSED) { | 912 if (availability_state_ == STATE_CLOSED) { |
| 915 NOTREACHED(); | 913 NOTREACHED(); |
| 916 return scoped_ptr<SpdyBuffer>(); | 914 return scoped_ptr<SpdyBuffer>(); |
| 917 } | 915 } |
| 918 | 916 |
| 919 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 917 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
| 920 CHECK(it != active_streams_.end()); | 918 CHECK(it != active_streams_.end()); |
| 921 SpdyStream* stream = it->second.stream; | 919 SpdyStream* stream = it->second.stream; |
| 922 CHECK_EQ(stream->stream_id(), stream_id); | 920 CHECK_EQ(stream->stream_id(), stream_id); |
| 923 | 921 |
| 924 if (len < 0) { | 922 if (len < 0) { |
| 925 NOTREACHED(); | 923 NOTREACHED(); |
| 926 return scoped_ptr<SpdyBuffer>(); | 924 return scoped_ptr<SpdyBuffer>(); |
| 927 } | 925 } |
| 928 | 926 |
| 929 int effective_len = std::min(len, kMaxSpdyFrameChunkSize); | 927 int effective_len = std::min(len, kMaxSpdyFrameChunkSize); |
| 930 | 928 |
| 931 bool send_stalled_by_stream = | 929 bool send_stalled_by_stream = (flow_control_state_ >= FLOW_CONTROL_STREAM) && |
| 932 (flow_control_state_ >= FLOW_CONTROL_STREAM) && | 930 (stream->send_window_size() <= 0); |
| 933 (stream->send_window_size() <= 0); | |
| 934 bool send_stalled_by_session = IsSendStalled(); | 931 bool send_stalled_by_session = IsSendStalled(); |
| 935 | 932 |
| 936 // NOTE: There's an enum of the same name in histograms.xml. | 933 // NOTE: There's an enum of the same name in histograms.xml. |
| 937 enum SpdyFrameFlowControlState { | 934 enum SpdyFrameFlowControlState { |
| 938 SEND_NOT_STALLED, | 935 SEND_NOT_STALLED, |
| 939 SEND_STALLED_BY_STREAM, | 936 SEND_STALLED_BY_STREAM, |
| 940 SEND_STALLED_BY_SESSION, | 937 SEND_STALLED_BY_SESSION, |
| 941 SEND_STALLED_BY_STREAM_AND_SESSION, | 938 SEND_STALLED_BY_STREAM_AND_SESSION, |
| 942 }; | 939 }; |
| 943 | 940 |
| 944 SpdyFrameFlowControlState frame_flow_control_state = SEND_NOT_STALLED; | 941 SpdyFrameFlowControlState frame_flow_control_state = SEND_NOT_STALLED; |
| 945 if (send_stalled_by_stream) { | 942 if (send_stalled_by_stream) { |
| 946 if (send_stalled_by_session) { | 943 if (send_stalled_by_session) { |
| 947 frame_flow_control_state = SEND_STALLED_BY_STREAM_AND_SESSION; | 944 frame_flow_control_state = SEND_STALLED_BY_STREAM_AND_SESSION; |
| 948 } else { | 945 } else { |
| 949 frame_flow_control_state = SEND_STALLED_BY_STREAM; | 946 frame_flow_control_state = SEND_STALLED_BY_STREAM; |
| 950 } | 947 } |
| 951 } else if (send_stalled_by_session) { | 948 } else if (send_stalled_by_session) { |
| 952 frame_flow_control_state = SEND_STALLED_BY_SESSION; | 949 frame_flow_control_state = SEND_STALLED_BY_SESSION; |
| 953 } | 950 } |
| 954 | 951 |
| 955 if (flow_control_state_ == FLOW_CONTROL_STREAM) { | 952 if (flow_control_state_ == FLOW_CONTROL_STREAM) { |
| 956 UMA_HISTOGRAM_ENUMERATION( | 953 UMA_HISTOGRAM_ENUMERATION("Net.SpdyFrameStreamFlowControlState", |
| 957 "Net.SpdyFrameStreamFlowControlState", | 954 frame_flow_control_state, |
| 958 frame_flow_control_state, | 955 SEND_STALLED_BY_STREAM + 1); |
| 959 SEND_STALLED_BY_STREAM + 1); | |
| 960 } else if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { | 956 } else if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { |
| 961 UMA_HISTOGRAM_ENUMERATION( | 957 UMA_HISTOGRAM_ENUMERATION("Net.SpdyFrameStreamAndSessionFlowControlState", |
| 962 "Net.SpdyFrameStreamAndSessionFlowControlState", | 958 frame_flow_control_state, |
| 963 frame_flow_control_state, | 959 SEND_STALLED_BY_STREAM_AND_SESSION + 1); |
| 964 SEND_STALLED_BY_STREAM_AND_SESSION + 1); | |
| 965 } | 960 } |
| 966 | 961 |
| 967 // Obey send window size of the stream if stream flow control is | 962 // Obey send window size of the stream if stream flow control is |
| 968 // enabled. | 963 // enabled. |
| 969 if (flow_control_state_ >= FLOW_CONTROL_STREAM) { | 964 if (flow_control_state_ >= FLOW_CONTROL_STREAM) { |
| 970 if (send_stalled_by_stream) { | 965 if (send_stalled_by_stream) { |
| 971 stream->set_send_stalled_by_flow_control(true); | 966 stream->set_send_stalled_by_flow_control(true); |
| 972 // Even though we're currently stalled only by the stream, we | 967 // Even though we're currently stalled only by the stream, we |
| 973 // might end up being stalled by the session also. | 968 // might end up being stalled by the session also. |
| 974 QueueSendStalledStream(*stream); | 969 QueueSendStalledStream(*stream); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 997 } | 992 } |
| 998 | 993 |
| 999 DCHECK_GE(effective_len, 0); | 994 DCHECK_GE(effective_len, 0); |
| 1000 | 995 |
| 1001 // Clear FIN flag if only some of the data will be in the data | 996 // Clear FIN flag if only some of the data will be in the data |
| 1002 // frame. | 997 // frame. |
| 1003 if (effective_len < len) | 998 if (effective_len < len) |
| 1004 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); | 999 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); |
| 1005 | 1000 |
| 1006 if (net_log().IsLogging()) { | 1001 if (net_log().IsLogging()) { |
| 1007 net_log().AddEvent( | 1002 net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_SEND_DATA, |
| 1008 NetLog::TYPE_SPDY_SESSION_SEND_DATA, | 1003 base::Bind(&NetLogSpdyDataCallback, |
| 1009 base::Bind(&NetLogSpdyDataCallback, stream_id, effective_len, | 1004 stream_id, |
| 1010 (flags & DATA_FLAG_FIN) != 0)); | 1005 effective_len, |
| 1006 (flags & DATA_FLAG_FIN) != 0)); |
| 1011 } | 1007 } |
| 1012 | 1008 |
| 1013 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. | 1009 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. |
| 1014 if (effective_len > 0) | 1010 if (effective_len > 0) |
| 1015 SendPrefacePingIfNoneInFlight(); | 1011 SendPrefacePingIfNoneInFlight(); |
| 1016 | 1012 |
| 1017 // TODO(mbelshe): reduce memory copies here. | 1013 // TODO(mbelshe): reduce memory copies here. |
| 1018 DCHECK(buffered_spdy_framer_.get()); | 1014 DCHECK(buffered_spdy_framer_.get()); |
| 1019 scoped_ptr<SpdyFrame> frame( | 1015 scoped_ptr<SpdyFrame> frame(buffered_spdy_framer_->CreateDataFrame( |
| 1020 buffered_spdy_framer_->CreateDataFrame( | 1016 stream_id, data->data(), static_cast<uint32>(effective_len), flags)); |
| 1021 stream_id, data->data(), | |
| 1022 static_cast<uint32>(effective_len), flags)); | |
| 1023 | 1017 |
| 1024 scoped_ptr<SpdyBuffer> data_buffer(new SpdyBuffer(frame.Pass())); | 1018 scoped_ptr<SpdyBuffer> data_buffer(new SpdyBuffer(frame.Pass())); |
| 1025 | 1019 |
| 1026 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { | 1020 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { |
| 1027 DecreaseSendWindowSize(static_cast<int32>(effective_len)); | 1021 DecreaseSendWindowSize(static_cast<int32>(effective_len)); |
| 1028 data_buffer->AddConsumeCallback( | 1022 data_buffer->AddConsumeCallback( |
| 1029 base::Bind(&SpdySession::OnWriteBufferConsumed, | 1023 base::Bind(&SpdySession::OnWriteBufferConsumed, |
| 1030 weak_factory_.GetWeakPtr(), | 1024 weak_factory_.GetWeakPtr(), |
| 1031 static_cast<size_t>(effective_len))); | 1025 static_cast<size_t>(effective_len))); |
| 1032 } | 1026 } |
| 1033 | 1027 |
| 1034 return data_buffer.Pass(); | 1028 return data_buffer.Pass(); |
| 1035 } | 1029 } |
| 1036 | 1030 |
| 1037 void SpdySession::CloseActiveStream(SpdyStreamId stream_id, int status) { | 1031 void SpdySession::CloseActiveStream(SpdyStreamId stream_id, int status) { |
| 1038 DCHECK_NE(stream_id, 0u); | 1032 DCHECK_NE(stream_id, 0u); |
| 1039 | 1033 |
| 1040 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 1034 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 1041 if (it == active_streams_.end()) { | 1035 if (it == active_streams_.end()) { |
| 1042 NOTREACHED(); | 1036 NOTREACHED(); |
| 1043 return; | 1037 return; |
| 1044 } | 1038 } |
| 1045 | 1039 |
| 1046 CloseActiveStreamIterator(it, status); | 1040 CloseActiveStreamIterator(it, status); |
| 1047 } | 1041 } |
| 1048 | 1042 |
| 1049 void SpdySession::CloseCreatedStream( | 1043 void SpdySession::CloseCreatedStream(const base::WeakPtr<SpdyStream>& stream, |
| 1050 const base::WeakPtr<SpdyStream>& stream, int status) { | 1044 int status) { |
| 1051 DCHECK_EQ(stream->stream_id(), 0u); | 1045 DCHECK_EQ(stream->stream_id(), 0u); |
| 1052 | 1046 |
| 1053 CreatedStreamSet::iterator it = created_streams_.find(stream.get()); | 1047 CreatedStreamSet::iterator it = created_streams_.find(stream.get()); |
| 1054 if (it == created_streams_.end()) { | 1048 if (it == created_streams_.end()) { |
| 1055 NOTREACHED(); | 1049 NOTREACHED(); |
| 1056 return; | 1050 return; |
| 1057 } | 1051 } |
| 1058 | 1052 |
| 1059 CloseCreatedStreamIterator(it, status); | 1053 CloseCreatedStreamIterator(it, status); |
| 1060 } | 1054 } |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1210 } | 1204 } |
| 1211 | 1205 |
| 1212 if (result == ERR_IO_PENDING) | 1206 if (result == ERR_IO_PENDING) |
| 1213 break; | 1207 break; |
| 1214 | 1208 |
| 1215 if (bytes_read_without_yielding > kMaxReadBytesWithoutYielding) { | 1209 if (bytes_read_without_yielding > kMaxReadBytesWithoutYielding) { |
| 1216 read_state_ = READ_STATE_DO_READ; | 1210 read_state_ = READ_STATE_DO_READ; |
| 1217 base::MessageLoop::current()->PostTask( | 1211 base::MessageLoop::current()->PostTask( |
| 1218 FROM_HERE, | 1212 FROM_HERE, |
| 1219 base::Bind(&SpdySession::PumpReadLoop, | 1213 base::Bind(&SpdySession::PumpReadLoop, |
| 1220 weak_factory_.GetWeakPtr(), READ_STATE_DO_READ, OK)); | 1214 weak_factory_.GetWeakPtr(), |
| 1215 READ_STATE_DO_READ, |
| 1216 OK)); |
| 1221 result = ERR_IO_PENDING; | 1217 result = ERR_IO_PENDING; |
| 1222 break; | 1218 break; |
| 1223 } | 1219 } |
| 1224 } | 1220 } |
| 1225 | 1221 |
| 1226 CHECK(in_io_loop_); | 1222 CHECK(in_io_loop_); |
| 1227 in_io_loop_ = false; | 1223 in_io_loop_ = false; |
| 1228 | 1224 |
| 1229 return result; | 1225 return result; |
| 1230 } | 1226 } |
| 1231 | 1227 |
| 1232 int SpdySession::DoRead() { | 1228 int SpdySession::DoRead() { |
| 1233 CHECK(in_io_loop_); | 1229 CHECK(in_io_loop_); |
| 1234 CHECK_NE(availability_state_, STATE_CLOSED); | 1230 CHECK_NE(availability_state_, STATE_CLOSED); |
| 1235 | 1231 |
| 1236 CHECK(connection_); | 1232 CHECK(connection_); |
| 1237 CHECK(connection_->socket()); | 1233 CHECK(connection_->socket()); |
| 1238 read_state_ = READ_STATE_DO_READ_COMPLETE; | 1234 read_state_ = READ_STATE_DO_READ_COMPLETE; |
| 1239 return connection_->socket()->Read( | 1235 return connection_->socket()->Read(read_buffer_.get(), |
| 1240 read_buffer_.get(), | 1236 kReadBufferSize, |
| 1241 kReadBufferSize, | 1237 base::Bind(&SpdySession::PumpReadLoop, |
| 1242 base::Bind(&SpdySession::PumpReadLoop, | 1238 weak_factory_.GetWeakPtr(), |
| 1243 weak_factory_.GetWeakPtr(), READ_STATE_DO_READ_COMPLETE)); | 1239 READ_STATE_DO_READ_COMPLETE)); |
| 1244 } | 1240 } |
| 1245 | 1241 |
| 1246 int SpdySession::DoReadComplete(int result) { | 1242 int SpdySession::DoReadComplete(int result) { |
| 1247 CHECK(in_io_loop_); | 1243 CHECK(in_io_loop_); |
| 1248 DCHECK_NE(availability_state_, STATE_CLOSED); | 1244 DCHECK_NE(availability_state_, STATE_CLOSED); |
| 1249 | 1245 |
| 1250 // Parse a frame. For now this code requires that the frame fit into our | 1246 // Parse a frame. For now this code requires that the frame fit into our |
| 1251 // buffer (kReadBufferSize). | 1247 // buffer (kReadBufferSize). |
| 1252 // TODO(mbelshe): support arbitrarily large frames! | 1248 // TODO(mbelshe): support arbitrarily large frames! |
| 1253 | 1249 |
| 1254 if (result == 0) { | 1250 if (result == 0) { |
| 1255 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySession.BytesRead.EOF", | 1251 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySession.BytesRead.EOF", |
| 1256 total_bytes_received_, 1, 100000000, 50); | 1252 total_bytes_received_, |
| 1253 1, |
| 1254 100000000, |
| 1255 50); |
| 1257 CloseSessionResult close_session_result = | 1256 CloseSessionResult close_session_result = |
| 1258 DoCloseSession(ERR_CONNECTION_CLOSED, "Connection closed"); | 1257 DoCloseSession(ERR_CONNECTION_CLOSED, "Connection closed"); |
| 1259 DCHECK_EQ(close_session_result, SESSION_CLOSED_BUT_NOT_REMOVED); | 1258 DCHECK_EQ(close_session_result, SESSION_CLOSED_BUT_NOT_REMOVED); |
| 1260 DCHECK_EQ(availability_state_, STATE_CLOSED); | 1259 DCHECK_EQ(availability_state_, STATE_CLOSED); |
| 1261 DCHECK_EQ(error_on_close_, ERR_CONNECTION_CLOSED); | 1260 DCHECK_EQ(error_on_close_, ERR_CONNECTION_CLOSED); |
| 1262 return ERR_CONNECTION_CLOSED; | 1261 return ERR_CONNECTION_CLOSED; |
| 1263 } | 1262 } |
| 1264 | 1263 |
| 1265 if (result < 0) { | 1264 if (result < 0) { |
| 1266 CloseSessionResult close_session_result = | 1265 CloseSessionResult close_session_result = |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1374 } | 1373 } |
| 1375 | 1374 |
| 1376 if (stream.get()) | 1375 if (stream.get()) |
| 1377 CHECK(!stream->IsClosed()); | 1376 CHECK(!stream->IsClosed()); |
| 1378 | 1377 |
| 1379 // Activate the stream only when sending the SYN_STREAM frame to | 1378 // Activate the stream only when sending the SYN_STREAM frame to |
| 1380 // guarantee monotonically-increasing stream IDs. | 1379 // guarantee monotonically-increasing stream IDs. |
| 1381 if (frame_type == SYN_STREAM) { | 1380 if (frame_type == SYN_STREAM) { |
| 1382 CHECK(stream.get()); | 1381 CHECK(stream.get()); |
| 1383 CHECK_EQ(stream->stream_id(), 0u); | 1382 CHECK_EQ(stream->stream_id(), 0u); |
| 1384 scoped_ptr<SpdyStream> owned_stream = | 1383 scoped_ptr<SpdyStream> owned_stream = ActivateCreatedStream(stream.get()); |
| 1385 ActivateCreatedStream(stream.get()); | |
| 1386 InsertActivatedStream(owned_stream.Pass()); | 1384 InsertActivatedStream(owned_stream.Pass()); |
| 1387 } | 1385 } |
| 1388 | 1386 |
| 1389 in_flight_write_ = producer->ProduceBuffer(); | 1387 in_flight_write_ = producer->ProduceBuffer(); |
| 1390 if (!in_flight_write_) { | 1388 if (!in_flight_write_) { |
| 1391 NOTREACHED(); | 1389 NOTREACHED(); |
| 1392 return ERR_UNEXPECTED; | 1390 return ERR_UNEXPECTED; |
| 1393 } | 1391 } |
| 1394 in_flight_write_frame_type_ = frame_type; | 1392 in_flight_write_frame_type_ = frame_type; |
| 1395 in_flight_write_frame_size_ = in_flight_write_->GetRemainingSize(); | 1393 in_flight_write_frame_size_ = in_flight_write_->GetRemainingSize(); |
| 1396 DCHECK_GE(in_flight_write_frame_size_, | 1394 DCHECK_GE(in_flight_write_frame_size_, |
| 1397 buffered_spdy_framer_->GetFrameMinimumSize()); | 1395 buffered_spdy_framer_->GetFrameMinimumSize()); |
| 1398 in_flight_write_stream_ = stream; | 1396 in_flight_write_stream_ = stream; |
| 1399 } | 1397 } |
| 1400 | 1398 |
| 1401 write_state_ = WRITE_STATE_DO_WRITE_COMPLETE; | 1399 write_state_ = WRITE_STATE_DO_WRITE_COMPLETE; |
| 1402 | 1400 |
| 1403 // Explicitly store in a scoped_refptr<IOBuffer> to avoid problems | 1401 // Explicitly store in a scoped_refptr<IOBuffer> to avoid problems |
| 1404 // with Socket implementations that don't store their IOBuffer | 1402 // with Socket implementations that don't store their IOBuffer |
| 1405 // argument in a scoped_refptr<IOBuffer> (see crbug.com/232345). | 1403 // argument in a scoped_refptr<IOBuffer> (see crbug.com/232345). |
| 1406 scoped_refptr<IOBuffer> write_io_buffer = | 1404 scoped_refptr<IOBuffer> write_io_buffer = |
| 1407 in_flight_write_->GetIOBufferForRemainingData(); | 1405 in_flight_write_->GetIOBufferForRemainingData(); |
| 1408 return connection_->socket()->Write( | 1406 return connection_->socket()->Write( |
| 1409 write_io_buffer.get(), | 1407 write_io_buffer.get(), |
| 1410 in_flight_write_->GetRemainingSize(), | 1408 in_flight_write_->GetRemainingSize(), |
| 1411 base::Bind(&SpdySession::PumpWriteLoop, | 1409 base::Bind(&SpdySession::PumpWriteLoop, |
| 1412 weak_factory_.GetWeakPtr(), WRITE_STATE_DO_WRITE_COMPLETE)); | 1410 weak_factory_.GetWeakPtr(), |
| 1411 WRITE_STATE_DO_WRITE_COMPLETE)); |
| 1413 } | 1412 } |
| 1414 | 1413 |
| 1415 int SpdySession::DoWriteComplete(int result) { | 1414 int SpdySession::DoWriteComplete(int result) { |
| 1416 CHECK(in_io_loop_); | 1415 CHECK(in_io_loop_); |
| 1417 DCHECK_NE(availability_state_, STATE_CLOSED); | 1416 DCHECK_NE(availability_state_, STATE_CLOSED); |
| 1418 DCHECK_NE(result, ERR_IO_PENDING); | 1417 DCHECK_NE(result, ERR_IO_PENDING); |
| 1419 DCHECK_GT(in_flight_write_->GetRemainingSize(), 0u); | 1418 DCHECK_GT(in_flight_write_->GetRemainingSize(), 0u); |
| 1420 | 1419 |
| 1421 last_activity_time_ = time_func_(); | 1420 last_activity_time_ = time_func_(); |
| 1422 | 1421 |
| 1423 if (result < 0) { | 1422 if (result < 0) { |
| 1424 DCHECK_NE(result, ERR_IO_PENDING); | 1423 DCHECK_NE(result, ERR_IO_PENDING); |
| 1425 in_flight_write_.reset(); | 1424 in_flight_write_.reset(); |
| 1426 in_flight_write_frame_type_ = DATA; | 1425 in_flight_write_frame_type_ = DATA; |
| 1427 in_flight_write_frame_size_ = 0; | 1426 in_flight_write_frame_size_ = 0; |
| 1428 in_flight_write_stream_.reset(); | 1427 in_flight_write_stream_.reset(); |
| 1429 CloseSessionResult close_session_result = | 1428 CloseSessionResult close_session_result = |
| 1430 DoCloseSession(static_cast<Error>(result), "Write error"); | 1429 DoCloseSession(static_cast<Error>(result), "Write error"); |
| 1431 DCHECK_EQ(close_session_result, SESSION_CLOSED_BUT_NOT_REMOVED); | 1430 DCHECK_EQ(close_session_result, SESSION_CLOSED_BUT_NOT_REMOVED); |
| 1432 DCHECK_EQ(availability_state_, STATE_CLOSED); | 1431 DCHECK_EQ(availability_state_, STATE_CLOSED); |
| 1433 DCHECK_EQ(error_on_close_, result); | 1432 DCHECK_EQ(error_on_close_, result); |
| 1434 return result; | 1433 return result; |
| 1435 } | 1434 } |
| 1436 | 1435 |
| 1437 // It should not be possible to have written more bytes than our | 1436 // It should not be possible to have written more bytes than our |
| 1438 // in_flight_write_. | 1437 // in_flight_write_. |
| 1439 DCHECK_LE(static_cast<size_t>(result), | 1438 DCHECK_LE(static_cast<size_t>(result), in_flight_write_->GetRemainingSize()); |
| 1440 in_flight_write_->GetRemainingSize()); | |
| 1441 | 1439 |
| 1442 if (result > 0) { | 1440 if (result > 0) { |
| 1443 in_flight_write_->Consume(static_cast<size_t>(result)); | 1441 in_flight_write_->Consume(static_cast<size_t>(result)); |
| 1444 | 1442 |
| 1445 // We only notify the stream when we've fully written the pending frame. | 1443 // We only notify the stream when we've fully written the pending frame. |
| 1446 if (in_flight_write_->GetRemainingSize() == 0) { | 1444 if (in_flight_write_->GetRemainingSize() == 0) { |
| 1447 // It is possible that the stream was cancelled while we were | 1445 // It is possible that the stream was cancelled while we were |
| 1448 // writing to the socket. | 1446 // writing to the socket. |
| 1449 if (in_flight_write_stream_.get()) { | 1447 if (in_flight_write_stream_.get()) { |
| 1450 DCHECK_GT(in_flight_write_frame_size_, 0u); | 1448 DCHECK_GT(in_flight_write_frame_size_, 0u); |
| 1451 in_flight_write_stream_->OnFrameWriteComplete( | 1449 in_flight_write_stream_->OnFrameWriteComplete( |
| 1452 in_flight_write_frame_type_, | 1450 in_flight_write_frame_type_, in_flight_write_frame_size_); |
| 1453 in_flight_write_frame_size_); | |
| 1454 } | 1451 } |
| 1455 | 1452 |
| 1456 // Cleanup the write which just completed. | 1453 // Cleanup the write which just completed. |
| 1457 in_flight_write_.reset(); | 1454 in_flight_write_.reset(); |
| 1458 in_flight_write_frame_type_ = DATA; | 1455 in_flight_write_frame_type_ = DATA; |
| 1459 in_flight_write_frame_size_ = 0; | 1456 in_flight_write_frame_size_ = 0; |
| 1460 in_flight_write_stream_.reset(); | 1457 in_flight_write_stream_.reset(); |
| 1461 } | 1458 } |
| 1462 } | 1459 } |
| 1463 | 1460 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1546 | 1543 |
| 1547 if (availability_state_ == STATE_CLOSED) | 1544 if (availability_state_ == STATE_CLOSED) |
| 1548 return SESSION_ALREADY_CLOSED; | 1545 return SESSION_ALREADY_CLOSED; |
| 1549 | 1546 |
| 1550 net_log_.AddEvent( | 1547 net_log_.AddEvent( |
| 1551 NetLog::TYPE_SPDY_SESSION_CLOSE, | 1548 NetLog::TYPE_SPDY_SESSION_CLOSE, |
| 1552 base::Bind(&NetLogSpdySessionCloseCallback, err, &description)); | 1549 base::Bind(&NetLogSpdySessionCloseCallback, err, &description)); |
| 1553 | 1550 |
| 1554 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SpdySession.ClosedOnError", -err); | 1551 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SpdySession.ClosedOnError", -err); |
| 1555 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySession.BytesRead.OtherErrors", | 1552 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySession.BytesRead.OtherErrors", |
| 1556 total_bytes_received_, 1, 100000000, 50); | 1553 total_bytes_received_, |
| 1554 1, |
| 1555 100000000, |
| 1556 50); |
| 1557 | 1557 |
| 1558 CHECK(pool_); | 1558 CHECK(pool_); |
| 1559 if (availability_state_ != STATE_GOING_AWAY) | 1559 if (availability_state_ != STATE_GOING_AWAY) |
| 1560 pool_->MakeSessionUnavailable(GetWeakPtr()); | 1560 pool_->MakeSessionUnavailable(GetWeakPtr()); |
| 1561 | 1561 |
| 1562 availability_state_ = STATE_CLOSED; | 1562 availability_state_ = STATE_CLOSED; |
| 1563 error_on_close_ = err; | 1563 error_on_close_ = err; |
| 1564 | 1564 |
| 1565 StartGoingAway(0, err); | 1565 StartGoingAway(0, err); |
| 1566 write_queue_.Clear(); | 1566 write_queue_.Clear(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1578 DcheckClosed(); | 1578 DcheckClosed(); |
| 1579 CHECK(pool_); | 1579 CHECK(pool_); |
| 1580 | 1580 |
| 1581 SpdySessionPool* pool = pool_; | 1581 SpdySessionPool* pool = pool_; |
| 1582 pool_ = NULL; | 1582 pool_ = NULL; |
| 1583 pool->RemoveUnavailableSession(GetWeakPtr()); | 1583 pool->RemoveUnavailableSession(GetWeakPtr()); |
| 1584 } | 1584 } |
| 1585 | 1585 |
| 1586 void SpdySession::LogAbandonedStream(SpdyStream* stream, Error status) { | 1586 void SpdySession::LogAbandonedStream(SpdyStream* stream, Error status) { |
| 1587 DCHECK(stream); | 1587 DCHECK(stream); |
| 1588 std::string description = base::StringPrintf( | 1588 std::string description = |
| 1589 "ABANDONED (stream_id=%d): ", stream->stream_id()) + | 1589 base::StringPrintf("ABANDONED (stream_id=%d): ", stream->stream_id()) + |
| 1590 stream->url().spec(); | 1590 stream->url().spec(); |
| 1591 stream->LogStreamError(status, description); | 1591 stream->LogStreamError(status, description); |
| 1592 // We don't increment the streams abandoned counter here. If the | 1592 // We don't increment the streams abandoned counter here. If the |
| 1593 // stream isn't active (i.e., it hasn't written anything to the wire | 1593 // stream isn't active (i.e., it hasn't written anything to the wire |
| 1594 // yet) then it's as if it never existed. If it is active, then | 1594 // yet) then it's as if it never existed. If it is active, then |
| 1595 // LogAbandonedActiveStream() will increment the counters. | 1595 // LogAbandonedActiveStream() will increment the counters. |
| 1596 } | 1596 } |
| 1597 | 1597 |
| 1598 void SpdySession::LogAbandonedActiveStream(ActiveStreamMap::const_iterator it, | 1598 void SpdySession::LogAbandonedActiveStream(ActiveStreamMap::const_iterator it, |
| 1599 Error status) { | 1599 Error status) { |
| 1600 DCHECK_GT(it->first, 0u); | 1600 DCHECK_GT(it->first, 0u); |
| 1601 LogAbandonedStream(it->second.stream, status); | 1601 LogAbandonedStream(it->second.stream, status); |
| 1602 ++streams_abandoned_count_; | 1602 ++streams_abandoned_count_; |
| 1603 base::StatsCounter abandoned_streams("spdy.abandoned_streams"); | 1603 base::StatsCounter abandoned_streams("spdy.abandoned_streams"); |
| 1604 abandoned_streams.Increment(); | 1604 abandoned_streams.Increment(); |
| 1605 if (it->second.stream->type() == SPDY_PUSH_STREAM && | 1605 if (it->second.stream->type() == SPDY_PUSH_STREAM && |
| 1606 unclaimed_pushed_streams_.find(it->second.stream->url()) != | 1606 unclaimed_pushed_streams_.find(it->second.stream->url()) != |
| 1607 unclaimed_pushed_streams_.end()) { | 1607 unclaimed_pushed_streams_.end()) { |
| 1608 base::StatsCounter abandoned_push_streams("spdy.abandoned_push_streams"); | 1608 base::StatsCounter abandoned_push_streams("spdy.abandoned_push_streams"); |
| 1609 abandoned_push_streams.Increment(); | 1609 abandoned_push_streams.Increment(); |
| 1610 } | 1610 } |
| 1611 } | 1611 } |
| 1612 | 1612 |
| 1613 int SpdySession::GetNewStreamId() { | 1613 int SpdySession::GetNewStreamId() { |
| 1614 int id = stream_hi_water_mark_; | 1614 int id = stream_hi_water_mark_; |
| 1615 stream_hi_water_mark_ += 2; | 1615 stream_hi_water_mark_ += 2; |
| 1616 if (stream_hi_water_mark_ > 0x7fff) | 1616 if (stream_hi_water_mark_ > 0x7fff) |
| 1617 stream_hi_water_mark_ = 1; | 1617 stream_hi_water_mark_ = 1; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1634 } | 1634 } |
| 1635 | 1635 |
| 1636 base::Value* SpdySession::GetInfoAsValue() const { | 1636 base::Value* SpdySession::GetInfoAsValue() const { |
| 1637 base::DictionaryValue* dict = new base::DictionaryValue(); | 1637 base::DictionaryValue* dict = new base::DictionaryValue(); |
| 1638 | 1638 |
| 1639 dict->SetInteger("source_id", net_log_.source().id); | 1639 dict->SetInteger("source_id", net_log_.source().id); |
| 1640 | 1640 |
| 1641 dict->SetString("host_port_pair", host_port_pair().ToString()); | 1641 dict->SetString("host_port_pair", host_port_pair().ToString()); |
| 1642 if (!pooled_aliases_.empty()) { | 1642 if (!pooled_aliases_.empty()) { |
| 1643 base::ListValue* alias_list = new base::ListValue(); | 1643 base::ListValue* alias_list = new base::ListValue(); |
| 1644 for (std::set<SpdySessionKey>::const_iterator it = | 1644 for (std::set<SpdySessionKey>::const_iterator it = pooled_aliases_.begin(); |
| 1645 pooled_aliases_.begin(); | 1645 it != pooled_aliases_.end(); |
| 1646 it != pooled_aliases_.end(); it++) { | 1646 it++) { |
| 1647 alias_list->Append(new base::StringValue( | 1647 alias_list->Append( |
| 1648 it->host_port_pair().ToString())); | 1648 new base::StringValue(it->host_port_pair().ToString())); |
| 1649 } | 1649 } |
| 1650 dict->Set("aliases", alias_list); | 1650 dict->Set("aliases", alias_list); |
| 1651 } | 1651 } |
| 1652 dict->SetString("proxy", host_port_proxy_pair().second.ToURI()); | 1652 dict->SetString("proxy", host_port_proxy_pair().second.ToURI()); |
| 1653 | 1653 |
| 1654 dict->SetInteger("active_streams", active_streams_.size()); | 1654 dict->SetInteger("active_streams", active_streams_.size()); |
| 1655 | 1655 |
| 1656 dict->SetInteger("unclaimed_pushed_streams", | 1656 dict->SetInteger("unclaimed_pushed_streams", |
| 1657 unclaimed_pushed_streams_.size()); | 1657 unclaimed_pushed_streams_.size()); |
| 1658 | 1658 |
| 1659 dict->SetBoolean("is_secure", is_secure_); | 1659 dict->SetBoolean("is_secure", is_secure_); |
| 1660 | 1660 |
| 1661 dict->SetString("protocol_negotiated", | 1661 dict->SetString("protocol_negotiated", |
| 1662 SSLClientSocket::NextProtoToString( | 1662 SSLClientSocket::NextProtoToString( |
| 1663 connection_->socket()->GetNegotiatedProtocol())); | 1663 connection_->socket()->GetNegotiatedProtocol())); |
| 1664 | 1664 |
| 1665 dict->SetInteger("error", error_on_close_); | 1665 dict->SetInteger("error", error_on_close_); |
| 1666 dict->SetInteger("max_concurrent_streams", max_concurrent_streams_); | 1666 dict->SetInteger("max_concurrent_streams", max_concurrent_streams_); |
| 1667 | 1667 |
| 1668 dict->SetInteger("streams_initiated_count", streams_initiated_count_); | 1668 dict->SetInteger("streams_initiated_count", streams_initiated_count_); |
| 1669 dict->SetInteger("streams_pushed_count", streams_pushed_count_); | 1669 dict->SetInteger("streams_pushed_count", streams_pushed_count_); |
| 1670 dict->SetInteger("streams_pushed_and_claimed_count", | 1670 dict->SetInteger("streams_pushed_and_claimed_count", |
| 1671 streams_pushed_and_claimed_count_); | 1671 streams_pushed_and_claimed_count_); |
| 1672 dict->SetInteger("streams_abandoned_count", streams_abandoned_count_); | 1672 dict->SetInteger("streams_abandoned_count", streams_abandoned_count_); |
| 1673 DCHECK(buffered_spdy_framer_.get()); | 1673 DCHECK(buffered_spdy_framer_.get()); |
| 1674 dict->SetInteger("frames_received", buffered_spdy_framer_->frames_received()); | 1674 dict->SetInteger("frames_received", buffered_spdy_framer_->frames_received()); |
| 1675 | 1675 |
| 1676 dict->SetBoolean("sent_settings", sent_settings_); | 1676 dict->SetBoolean("sent_settings", sent_settings_); |
| 1677 dict->SetBoolean("received_settings", received_settings_); | 1677 dict->SetBoolean("received_settings", received_settings_); |
| 1678 | 1678 |
| 1679 dict->SetInteger("send_window_size", session_send_window_size_); | 1679 dict->SetInteger("send_window_size", session_send_window_size_); |
| 1680 dict->SetInteger("recv_window_size", session_recv_window_size_); | 1680 dict->SetInteger("recv_window_size", session_recv_window_size_); |
| 1681 dict->SetInteger("unacked_recv_window_bytes", | 1681 dict->SetInteger("unacked_recv_window_bytes", |
| 1682 session_unacked_recv_window_bytes_); | 1682 session_unacked_recv_window_bytes_); |
| 1683 return dict; | 1683 return dict; |
| 1684 } | 1684 } |
| 1685 | 1685 |
| 1686 bool SpdySession::IsReused() const { | 1686 bool SpdySession::IsReused() const { |
| 1687 return buffered_spdy_framer_->frames_received() > 0 || | 1687 return buffered_spdy_framer_->frames_received() > 0 || |
| 1688 connection_->reuse_type() == ClientSocketHandle::UNUSED_IDLE; | 1688 connection_->reuse_type() == ClientSocketHandle::UNUSED_IDLE; |
| 1689 } | 1689 } |
| 1690 | 1690 |
| 1691 bool SpdySession::GetLoadTimingInfo(SpdyStreamId stream_id, | 1691 bool SpdySession::GetLoadTimingInfo(SpdyStreamId stream_id, |
| 1692 LoadTimingInfo* load_timing_info) const { | 1692 LoadTimingInfo* load_timing_info) const { |
| 1693 return connection_->GetLoadTimingInfo(stream_id != kFirstStreamId, | 1693 return connection_->GetLoadTimingInfo(stream_id != kFirstStreamId, |
| 1694 load_timing_info); | 1694 load_timing_info); |
| 1695 } | 1695 } |
| 1696 | 1696 |
| 1697 int SpdySession::GetPeerAddress(IPEndPoint* address) const { | 1697 int SpdySession::GetPeerAddress(IPEndPoint* address) const { |
| 1698 int rv = ERR_SOCKET_NOT_CONNECTED; | 1698 int rv = ERR_SOCKET_NOT_CONNECTED; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1714 | 1714 |
| 1715 UMA_HISTOGRAM_BOOLEAN("Net.SpdySessionSocketNotConnectedGetLocalAddress", | 1715 UMA_HISTOGRAM_BOOLEAN("Net.SpdySessionSocketNotConnectedGetLocalAddress", |
| 1716 rv == ERR_SOCKET_NOT_CONNECTED); | 1716 rv == ERR_SOCKET_NOT_CONNECTED); |
| 1717 | 1717 |
| 1718 return rv; | 1718 return rv; |
| 1719 } | 1719 } |
| 1720 | 1720 |
| 1721 void SpdySession::EnqueueSessionWrite(RequestPriority priority, | 1721 void SpdySession::EnqueueSessionWrite(RequestPriority priority, |
| 1722 SpdyFrameType frame_type, | 1722 SpdyFrameType frame_type, |
| 1723 scoped_ptr<SpdyFrame> frame) { | 1723 scoped_ptr<SpdyFrame> frame) { |
| 1724 DCHECK(frame_type == RST_STREAM || | 1724 DCHECK(frame_type == RST_STREAM || frame_type == SETTINGS || |
| 1725 frame_type == SETTINGS || | 1725 frame_type == WINDOW_UPDATE || frame_type == PING); |
| 1726 frame_type == WINDOW_UPDATE || | 1726 EnqueueWrite(priority, |
| 1727 frame_type == PING); | 1727 frame_type, |
| 1728 EnqueueWrite( | 1728 scoped_ptr<SpdyBufferProducer>(new SimpleBufferProducer( |
| 1729 priority, frame_type, | 1729 scoped_ptr<SpdyBuffer>(new SpdyBuffer(frame.Pass())))), |
| 1730 scoped_ptr<SpdyBufferProducer>( | 1730 base::WeakPtr<SpdyStream>()); |
| 1731 new SimpleBufferProducer( | |
| 1732 scoped_ptr<SpdyBuffer>(new SpdyBuffer(frame.Pass())))), | |
| 1733 base::WeakPtr<SpdyStream>()); | |
| 1734 } | 1731 } |
| 1735 | 1732 |
| 1736 void SpdySession::EnqueueWrite(RequestPriority priority, | 1733 void SpdySession::EnqueueWrite(RequestPriority priority, |
| 1737 SpdyFrameType frame_type, | 1734 SpdyFrameType frame_type, |
| 1738 scoped_ptr<SpdyBufferProducer> producer, | 1735 scoped_ptr<SpdyBufferProducer> producer, |
| 1739 const base::WeakPtr<SpdyStream>& stream) { | 1736 const base::WeakPtr<SpdyStream>& stream) { |
| 1740 if (availability_state_ == STATE_CLOSED) | 1737 if (availability_state_ == STATE_CLOSED) |
| 1741 return; | 1738 return; |
| 1742 | 1739 |
| 1743 bool was_idle = write_queue_.IsEmpty(); | 1740 bool was_idle = write_queue_.IsEmpty(); |
| 1744 write_queue_.Enqueue(priority, frame_type, producer.Pass(), stream); | 1741 write_queue_.Enqueue(priority, frame_type, producer.Pass(), stream); |
| 1745 if (write_state_ == WRITE_STATE_IDLE) { | 1742 if (write_state_ == WRITE_STATE_IDLE) { |
| 1746 DCHECK(was_idle); | 1743 DCHECK(was_idle); |
| 1747 DCHECK(!in_flight_write_); | 1744 DCHECK(!in_flight_write_); |
| 1748 write_state_ = WRITE_STATE_DO_WRITE; | 1745 write_state_ = WRITE_STATE_DO_WRITE; |
| 1749 base::MessageLoop::current()->PostTask( | 1746 base::MessageLoop::current()->PostTask( |
| 1750 FROM_HERE, | 1747 FROM_HERE, |
| 1751 base::Bind(&SpdySession::PumpWriteLoop, | 1748 base::Bind(&SpdySession::PumpWriteLoop, |
| 1752 weak_factory_.GetWeakPtr(), WRITE_STATE_DO_WRITE, OK)); | 1749 weak_factory_.GetWeakPtr(), |
| 1750 WRITE_STATE_DO_WRITE, |
| 1751 OK)); |
| 1753 } | 1752 } |
| 1754 } | 1753 } |
| 1755 | 1754 |
| 1756 void SpdySession::InsertCreatedStream(scoped_ptr<SpdyStream> stream) { | 1755 void SpdySession::InsertCreatedStream(scoped_ptr<SpdyStream> stream) { |
| 1757 CHECK_EQ(stream->stream_id(), 0u); | 1756 CHECK_EQ(stream->stream_id(), 0u); |
| 1758 CHECK(created_streams_.find(stream.get()) == created_streams_.end()); | 1757 CHECK(created_streams_.find(stream.get()) == created_streams_.end()); |
| 1759 created_streams_.insert(stream.release()); | 1758 created_streams_.insert(stream.release()); |
| 1760 } | 1759 } |
| 1761 | 1760 |
| 1762 scoped_ptr<SpdyStream> SpdySession::ActivateCreatedStream(SpdyStream* stream) { | 1761 scoped_ptr<SpdyStream> SpdySession::ActivateCreatedStream(SpdyStream* stream) { |
| 1763 CHECK_EQ(stream->stream_id(), 0u); | 1762 CHECK_EQ(stream->stream_id(), 0u); |
| 1764 CHECK(created_streams_.find(stream) != created_streams_.end()); | 1763 CHECK(created_streams_.find(stream) != created_streams_.end()); |
| 1765 stream->set_stream_id(GetNewStreamId()); | 1764 stream->set_stream_id(GetNewStreamId()); |
| 1766 scoped_ptr<SpdyStream> owned_stream(stream); | 1765 scoped_ptr<SpdyStream> owned_stream(stream); |
| 1767 created_streams_.erase(stream); | 1766 created_streams_.erase(stream); |
| 1768 return owned_stream.Pass(); | 1767 return owned_stream.Pass(); |
| 1769 } | 1768 } |
| 1770 | 1769 |
| 1771 void SpdySession::InsertActivatedStream(scoped_ptr<SpdyStream> stream) { | 1770 void SpdySession::InsertActivatedStream(scoped_ptr<SpdyStream> stream) { |
| 1772 SpdyStreamId stream_id = stream->stream_id(); | 1771 SpdyStreamId stream_id = stream->stream_id(); |
| 1773 CHECK_NE(stream_id, 0u); | 1772 CHECK_NE(stream_id, 0u); |
| 1774 std::pair<ActiveStreamMap::iterator, bool> result = | 1773 std::pair<ActiveStreamMap::iterator, bool> result = active_streams_.insert( |
| 1775 active_streams_.insert( | 1774 std::make_pair(stream_id, ActiveStreamInfo(stream.get()))); |
| 1776 std::make_pair(stream_id, ActiveStreamInfo(stream.get()))); | |
| 1777 CHECK(result.second); | 1775 CHECK(result.second); |
| 1778 ignore_result(stream.release()); | 1776 ignore_result(stream.release()); |
| 1779 } | 1777 } |
| 1780 | 1778 |
| 1781 void SpdySession::DeleteStream(scoped_ptr<SpdyStream> stream, int status) { | 1779 void SpdySession::DeleteStream(scoped_ptr<SpdyStream> stream, int status) { |
| 1782 if (in_flight_write_stream_.get() == stream.get()) { | 1780 if (in_flight_write_stream_.get() == stream.get()) { |
| 1783 // If we're deleting the stream for the in-flight write, we still | 1781 // If we're deleting the stream for the in-flight write, we still |
| 1784 // need to let the write complete, so we clear | 1782 // need to let the write complete, so we clear |
| 1785 // |in_flight_write_stream_| and let the write finish on its own | 1783 // |in_flight_write_stream_| and let the write finish on its own |
| 1786 // without notifying |in_flight_write_stream_|. | 1784 // without notifying |in_flight_write_stream_|. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1833 } | 1831 } |
| 1834 | 1832 |
| 1835 bool SpdySession::GetSSLInfo(SSLInfo* ssl_info, | 1833 bool SpdySession::GetSSLInfo(SSLInfo* ssl_info, |
| 1836 bool* was_npn_negotiated, | 1834 bool* was_npn_negotiated, |
| 1837 NextProto* protocol_negotiated) { | 1835 NextProto* protocol_negotiated) { |
| 1838 *was_npn_negotiated = connection_->socket()->WasNpnNegotiated(); | 1836 *was_npn_negotiated = connection_->socket()->WasNpnNegotiated(); |
| 1839 *protocol_negotiated = connection_->socket()->GetNegotiatedProtocol(); | 1837 *protocol_negotiated = connection_->socket()->GetNegotiatedProtocol(); |
| 1840 return connection_->socket()->GetSSLInfo(ssl_info); | 1838 return connection_->socket()->GetSSLInfo(ssl_info); |
| 1841 } | 1839 } |
| 1842 | 1840 |
| 1843 bool SpdySession::GetSSLCertRequestInfo( | 1841 bool SpdySession::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { |
| 1844 SSLCertRequestInfo* cert_request_info) { | |
| 1845 if (!is_secure_) | 1842 if (!is_secure_) |
| 1846 return false; | 1843 return false; |
| 1847 GetSSLClientSocket()->GetSSLCertRequestInfo(cert_request_info); | 1844 GetSSLClientSocket()->GetSSLCertRequestInfo(cert_request_info); |
| 1848 return true; | 1845 return true; |
| 1849 } | 1846 } |
| 1850 | 1847 |
| 1851 void SpdySession::OnError(SpdyFramer::SpdyError error_code) { | 1848 void SpdySession::OnError(SpdyFramer::SpdyError error_code) { |
| 1852 CHECK(in_io_loop_); | 1849 CHECK(in_io_loop_); |
| 1853 | 1850 |
| 1854 if (availability_state_ == STATE_CLOSED) | 1851 if (availability_state_ == STATE_CLOSED) |
| 1855 return; | 1852 return; |
| 1856 | 1853 |
| 1857 RecordProtocolErrorHistogram(MapFramerErrorToProtocolError(error_code)); | 1854 RecordProtocolErrorHistogram(MapFramerErrorToProtocolError(error_code)); |
| 1858 std::string description = base::StringPrintf( | 1855 std::string description = |
| 1859 "SPDY_ERROR error_code: %d.", error_code); | 1856 base::StringPrintf("SPDY_ERROR error_code: %d.", error_code); |
| 1860 CloseSessionResult result = | 1857 CloseSessionResult result = |
| 1861 DoCloseSession(ERR_SPDY_PROTOCOL_ERROR, description); | 1858 DoCloseSession(ERR_SPDY_PROTOCOL_ERROR, description); |
| 1862 DCHECK_EQ(result, SESSION_CLOSED_BUT_NOT_REMOVED); | 1859 DCHECK_EQ(result, SESSION_CLOSED_BUT_NOT_REMOVED); |
| 1863 } | 1860 } |
| 1864 | 1861 |
| 1865 void SpdySession::OnStreamError(SpdyStreamId stream_id, | 1862 void SpdySession::OnStreamError(SpdyStreamId stream_id, |
| 1866 const std::string& description) { | 1863 const std::string& description) { |
| 1867 CHECK(in_io_loop_); | 1864 CHECK(in_io_loop_); |
| 1868 | 1865 |
| 1869 if (availability_state_ == STATE_CLOSED) | 1866 if (availability_state_ == STATE_CLOSED) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1932 // inactive (since the other side has still reduced its session send | 1929 // inactive (since the other side has still reduced its session send |
| 1933 // window). | 1930 // window). |
| 1934 scoped_ptr<SpdyBuffer> buffer; | 1931 scoped_ptr<SpdyBuffer> buffer; |
| 1935 if (data) { | 1932 if (data) { |
| 1936 DCHECK_GT(len, 0u); | 1933 DCHECK_GT(len, 0u); |
| 1937 CHECK_LE(len, static_cast<size_t>(kReadBufferSize)); | 1934 CHECK_LE(len, static_cast<size_t>(kReadBufferSize)); |
| 1938 buffer.reset(new SpdyBuffer(data, len)); | 1935 buffer.reset(new SpdyBuffer(data, len)); |
| 1939 | 1936 |
| 1940 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { | 1937 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { |
| 1941 DecreaseRecvWindowSize(static_cast<int32>(len)); | 1938 DecreaseRecvWindowSize(static_cast<int32>(len)); |
| 1942 buffer->AddConsumeCallback( | 1939 buffer->AddConsumeCallback(base::Bind(&SpdySession::OnReadBufferConsumed, |
| 1943 base::Bind(&SpdySession::OnReadBufferConsumed, | 1940 weak_factory_.GetWeakPtr())); |
| 1944 weak_factory_.GetWeakPtr())); | |
| 1945 } | 1941 } |
| 1946 } else { | 1942 } else { |
| 1947 DCHECK_EQ(len, 0u); | 1943 DCHECK_EQ(len, 0u); |
| 1948 } | 1944 } |
| 1949 | 1945 |
| 1950 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 1946 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 1951 | 1947 |
| 1952 // By the time data comes in, the stream may already be inactive. | 1948 // By the time data comes in, the stream may already be inactive. |
| 1953 if (it == active_streams_.end()) | 1949 if (it == active_streams_.end()) |
| 1954 return; | 1950 return; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1973 | 1969 |
| 1974 if (availability_state_ == STATE_CLOSED) | 1970 if (availability_state_ == STATE_CLOSED) |
| 1975 return; | 1971 return; |
| 1976 | 1972 |
| 1977 if (clear_persisted) | 1973 if (clear_persisted) |
| 1978 http_server_properties_->ClearSpdySettings(host_port_pair()); | 1974 http_server_properties_->ClearSpdySettings(host_port_pair()); |
| 1979 | 1975 |
| 1980 if (net_log_.IsLogging()) { | 1976 if (net_log_.IsLogging()) { |
| 1981 net_log_.AddEvent( | 1977 net_log_.AddEvent( |
| 1982 NetLog::TYPE_SPDY_SESSION_RECV_SETTINGS, | 1978 NetLog::TYPE_SPDY_SESSION_RECV_SETTINGS, |
| 1983 base::Bind(&NetLogSpdySettingsCallback, host_port_pair(), | 1979 base::Bind( |
| 1984 clear_persisted)); | 1980 &NetLogSpdySettingsCallback, host_port_pair(), clear_persisted)); |
| 1985 } | 1981 } |
| 1986 } | 1982 } |
| 1987 | 1983 |
| 1988 void SpdySession::OnSetting(SpdySettingsIds id, | 1984 void SpdySession::OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) { |
| 1989 uint8 flags, | |
| 1990 uint32 value) { | |
| 1991 CHECK(in_io_loop_); | 1985 CHECK(in_io_loop_); |
| 1992 | 1986 |
| 1993 if (availability_state_ == STATE_CLOSED) | 1987 if (availability_state_ == STATE_CLOSED) |
| 1994 return; | 1988 return; |
| 1995 | 1989 |
| 1996 HandleSetting(id, value); | 1990 HandleSetting(id, value); |
| 1997 http_server_properties_->SetSpdySetting( | 1991 http_server_properties_->SetSpdySetting( |
| 1998 host_port_pair(), | 1992 host_port_pair(), id, static_cast<SpdySettingsFlags>(flags), value); |
| 1999 id, | |
| 2000 static_cast<SpdySettingsFlags>(flags), | |
| 2001 value); | |
| 2002 received_settings_ = true; | 1993 received_settings_ = true; |
| 2003 | 1994 |
| 2004 // Log the setting. | 1995 // Log the setting. |
| 2005 net_log_.AddEvent( | 1996 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_RECV_SETTING, |
| 2006 NetLog::TYPE_SPDY_SESSION_RECV_SETTING, | 1997 base::Bind(&NetLogSpdySettingCallback, |
| 2007 base::Bind(&NetLogSpdySettingCallback, | 1998 id, |
| 2008 id, static_cast<SpdySettingsFlags>(flags), value)); | 1999 static_cast<SpdySettingsFlags>(flags), |
| 2000 value)); |
| 2009 } | 2001 } |
| 2010 | 2002 |
| 2011 void SpdySession::OnSendCompressedFrame( | 2003 void SpdySession::OnSendCompressedFrame(SpdyStreamId stream_id, |
| 2012 SpdyStreamId stream_id, | 2004 SpdyFrameType type, |
| 2013 SpdyFrameType type, | 2005 size_t payload_len, |
| 2014 size_t payload_len, | 2006 size_t frame_len) { |
| 2015 size_t frame_len) { | |
| 2016 if (type != SYN_STREAM) | 2007 if (type != SYN_STREAM) |
| 2017 return; | 2008 return; |
| 2018 | 2009 |
| 2019 DCHECK(buffered_spdy_framer_.get()); | 2010 DCHECK(buffered_spdy_framer_.get()); |
| 2020 size_t compressed_len = | 2011 size_t compressed_len = |
| 2021 frame_len - buffered_spdy_framer_->GetSynStreamMinimumSize(); | 2012 frame_len - buffered_spdy_framer_->GetSynStreamMinimumSize(); |
| 2022 | 2013 |
| 2023 if (payload_len) { | 2014 if (payload_len) { |
| 2024 // Make sure we avoid early decimal truncation. | 2015 // Make sure we avoid early decimal truncation. |
| 2025 int compression_pct = 100 - (100 * compressed_len) / payload_len; | 2016 int compression_pct = 100 - (100 * compressed_len) / payload_len; |
| 2026 UMA_HISTOGRAM_PERCENTAGE("Net.SpdySynStreamCompressionPercentage", | 2017 UMA_HISTOGRAM_PERCENTAGE("Net.SpdySynStreamCompressionPercentage", |
| 2027 compression_pct); | 2018 compression_pct); |
| 2028 } | 2019 } |
| 2029 } | 2020 } |
| 2030 | 2021 |
| 2031 void SpdySession::OnReceiveCompressedFrame( | 2022 void SpdySession::OnReceiveCompressedFrame(SpdyStreamId stream_id, |
| 2032 SpdyStreamId stream_id, | 2023 SpdyFrameType type, |
| 2033 SpdyFrameType type, | 2024 size_t frame_len) { |
| 2034 size_t frame_len) { | |
| 2035 last_compressed_frame_len_ = frame_len; | 2025 last_compressed_frame_len_ = frame_len; |
| 2036 } | 2026 } |
| 2037 | 2027 |
| 2038 int SpdySession::OnInitialResponseHeadersReceived( | 2028 int SpdySession::OnInitialResponseHeadersReceived( |
| 2039 const SpdyHeaderBlock& response_headers, | 2029 const SpdyHeaderBlock& response_headers, |
| 2040 base::Time response_time, | 2030 base::Time response_time, |
| 2041 base::TimeTicks recv_first_byte_time, | 2031 base::TimeTicks recv_first_byte_time, |
| 2042 SpdyStream* stream) { | 2032 SpdyStream* stream) { |
| 2043 CHECK(in_io_loop_); | 2033 CHECK(in_io_loop_); |
| 2044 SpdyStreamId stream_id = stream->stream_id(); | 2034 SpdyStreamId stream_id = stream->stream_id(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2060 const SpdyHeaderBlock& headers) { | 2050 const SpdyHeaderBlock& headers) { |
| 2061 CHECK(in_io_loop_); | 2051 CHECK(in_io_loop_); |
| 2062 | 2052 |
| 2063 if (availability_state_ == STATE_CLOSED) | 2053 if (availability_state_ == STATE_CLOSED) |
| 2064 return; | 2054 return; |
| 2065 | 2055 |
| 2066 base::Time response_time = base::Time::Now(); | 2056 base::Time response_time = base::Time::Now(); |
| 2067 base::TimeTicks recv_first_byte_time = time_func_(); | 2057 base::TimeTicks recv_first_byte_time = time_func_(); |
| 2068 | 2058 |
| 2069 if (net_log_.IsLogging()) { | 2059 if (net_log_.IsLogging()) { |
| 2070 net_log_.AddEvent( | 2060 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_PUSHED_SYN_STREAM, |
| 2071 NetLog::TYPE_SPDY_SESSION_PUSHED_SYN_STREAM, | 2061 base::Bind(&NetLogSpdySynStreamReceivedCallback, |
| 2072 base::Bind(&NetLogSpdySynStreamReceivedCallback, | 2062 &headers, |
| 2073 &headers, fin, unidirectional, priority, | 2063 fin, |
| 2074 stream_id, associated_stream_id)); | 2064 unidirectional, |
| 2065 priority, |
| 2066 stream_id, |
| 2067 associated_stream_id)); |
| 2075 } | 2068 } |
| 2076 | 2069 |
| 2077 // Server-initiated streams should have even sequence numbers. | 2070 // Server-initiated streams should have even sequence numbers. |
| 2078 if ((stream_id & 0x1) != 0) { | 2071 if ((stream_id & 0x1) != 0) { |
| 2079 LOG(WARNING) << "Received invalid OnSyn stream id " << stream_id; | 2072 LOG(WARNING) << "Received invalid OnSyn stream id " << stream_id; |
| 2080 return; | 2073 return; |
| 2081 } | 2074 } |
| 2082 | 2075 |
| 2083 if (IsStreamActive(stream_id)) { | 2076 if (IsStreamActive(stream_id)) { |
| 2084 LOG(WARNING) << "Received OnSyn for active stream " << stream_id; | 2077 LOG(WARNING) << "Received OnSyn for active stream " << stream_id; |
| 2085 return; | 2078 return; |
| 2086 } | 2079 } |
| 2087 | 2080 |
| 2088 RequestPriority request_priority = | 2081 RequestPriority request_priority = |
| 2089 ConvertSpdyPriorityToRequestPriority(priority, GetProtocolVersion()); | 2082 ConvertSpdyPriorityToRequestPriority(priority, GetProtocolVersion()); |
| 2090 | 2083 |
| 2091 if (availability_state_ == STATE_GOING_AWAY) { | 2084 if (availability_state_ == STATE_GOING_AWAY) { |
| 2092 // TODO(akalin): This behavior isn't in the SPDY spec, although it | 2085 // TODO(akalin): This behavior isn't in the SPDY spec, although it |
| 2093 // probably should be. | 2086 // probably should be. |
| 2094 EnqueueResetStreamFrame(stream_id, request_priority, | 2087 EnqueueResetStreamFrame(stream_id, |
| 2088 request_priority, |
| 2095 RST_STREAM_REFUSED_STREAM, | 2089 RST_STREAM_REFUSED_STREAM, |
| 2096 "OnSyn received when going away"); | 2090 "OnSyn received when going away"); |
| 2097 return; | 2091 return; |
| 2098 } | 2092 } |
| 2099 | 2093 |
| 2100 // TODO(jgraettinger): SpdyFramer simulates OnSynStream() from HEADERS | 2094 // TODO(jgraettinger): SpdyFramer simulates OnSynStream() from HEADERS |
| 2101 // frames, which don't convey associated stream ID. Disable this check | 2095 // frames, which don't convey associated stream ID. Disable this check |
| 2102 // for now, and re-enable when PUSH_PROMISE is implemented properly. | 2096 // for now, and re-enable when PUSH_PROMISE is implemented properly. |
| 2103 if (associated_stream_id == 0 && GetProtocolVersion() < SPDY4) { | 2097 if (associated_stream_id == 0 && GetProtocolVersion() < SPDY4) { |
| 2104 std::string description = base::StringPrintf( | 2098 std::string description = base::StringPrintf( |
| 2105 "Received invalid OnSyn associated stream id %d for stream %d", | 2099 "Received invalid OnSyn associated stream id %d for stream %d", |
| 2106 associated_stream_id, stream_id); | 2100 associated_stream_id, |
| 2107 EnqueueResetStreamFrame(stream_id, request_priority, | 2101 stream_id); |
| 2108 RST_STREAM_REFUSED_STREAM, description); | 2102 EnqueueResetStreamFrame( |
| 2103 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, description); |
| 2109 return; | 2104 return; |
| 2110 } | 2105 } |
| 2111 | 2106 |
| 2112 streams_pushed_count_++; | 2107 streams_pushed_count_++; |
| 2113 | 2108 |
| 2114 // TODO(mbelshe): DCHECK that this is a GET method? | 2109 // TODO(mbelshe): DCHECK that this is a GET method? |
| 2115 | 2110 |
| 2116 // Verify that the response had a URL for us. | 2111 // Verify that the response had a URL for us. |
| 2117 GURL gurl = GetUrlFromHeaderBlock(headers, GetProtocolVersion(), true); | 2112 GURL gurl = GetUrlFromHeaderBlock(headers, GetProtocolVersion(), true); |
| 2118 if (!gurl.is_valid()) { | 2113 if (!gurl.is_valid()) { |
| 2119 EnqueueResetStreamFrame( | 2114 EnqueueResetStreamFrame(stream_id, |
| 2120 stream_id, request_priority, RST_STREAM_PROTOCOL_ERROR, | 2115 request_priority, |
| 2121 "Pushed stream url was invalid: " + gurl.spec()); | 2116 RST_STREAM_PROTOCOL_ERROR, |
| 2117 "Pushed stream url was invalid: " + gurl.spec()); |
| 2122 return; | 2118 return; |
| 2123 } | 2119 } |
| 2124 | 2120 |
| 2125 // Verify we have a valid stream association. | 2121 // Verify we have a valid stream association. |
| 2126 ActiveStreamMap::iterator associated_it = | 2122 ActiveStreamMap::iterator associated_it = |
| 2127 active_streams_.find(associated_stream_id); | 2123 active_streams_.find(associated_stream_id); |
| 2128 // TODO(jgraettinger): (See PUSH_PROMISE comment above). | 2124 // TODO(jgraettinger): (See PUSH_PROMISE comment above). |
| 2129 if (GetProtocolVersion() < SPDY4 && associated_it == active_streams_.end()) { | 2125 if (GetProtocolVersion() < SPDY4 && associated_it == active_streams_.end()) { |
| 2130 EnqueueResetStreamFrame( | 2126 EnqueueResetStreamFrame( |
| 2131 stream_id, request_priority, RST_STREAM_INVALID_STREAM, | 2127 stream_id, |
| 2132 base::StringPrintf( | 2128 request_priority, |
| 2133 "Received OnSyn with inactive associated stream %d", | 2129 RST_STREAM_INVALID_STREAM, |
| 2134 associated_stream_id)); | 2130 base::StringPrintf("Received OnSyn with inactive associated stream %d", |
| 2131 associated_stream_id)); |
| 2135 return; | 2132 return; |
| 2136 } | 2133 } |
| 2137 | 2134 |
| 2138 // Check that the SYN advertises the same origin as its associated stream. | 2135 // Check that the SYN advertises the same origin as its associated stream. |
| 2139 // Bypass this check if and only if this session is with a SPDY proxy that | 2136 // Bypass this check if and only if this session is with a SPDY proxy that |
| 2140 // is trusted explicitly via the --trusted-spdy-proxy switch. | 2137 // is trusted explicitly via the --trusted-spdy-proxy switch. |
| 2141 if (trusted_spdy_proxy_.Equals(host_port_pair())) { | 2138 if (trusted_spdy_proxy_.Equals(host_port_pair())) { |
| 2142 // Disallow pushing of HTTPS content. | 2139 // Disallow pushing of HTTPS content. |
| 2143 if (gurl.SchemeIs("https")) { | 2140 if (gurl.SchemeIs("https")) { |
| 2144 EnqueueResetStreamFrame( | 2141 EnqueueResetStreamFrame( |
| 2145 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, | 2142 stream_id, |
| 2146 base::StringPrintf( | 2143 request_priority, |
| 2147 "Rejected push of Cross Origin HTTPS content %d", | 2144 RST_STREAM_REFUSED_STREAM, |
| 2148 associated_stream_id)); | 2145 base::StringPrintf("Rejected push of Cross Origin HTTPS content %d", |
| 2146 associated_stream_id)); |
| 2149 } | 2147 } |
| 2150 } else if (GetProtocolVersion() < SPDY4) { | 2148 } else if (GetProtocolVersion() < SPDY4) { |
| 2151 // TODO(jgraettinger): (See PUSH_PROMISE comment above). | 2149 // TODO(jgraettinger): (See PUSH_PROMISE comment above). |
| 2152 GURL associated_url(associated_it->second.stream->GetUrlFromHeaders()); | 2150 GURL associated_url(associated_it->second.stream->GetUrlFromHeaders()); |
| 2153 if (associated_url.GetOrigin() != gurl.GetOrigin()) { | 2151 if (associated_url.GetOrigin() != gurl.GetOrigin()) { |
| 2154 EnqueueResetStreamFrame( | 2152 EnqueueResetStreamFrame( |
| 2155 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, | 2153 stream_id, |
| 2156 base::StringPrintf( | 2154 request_priority, |
| 2157 "Rejected Cross Origin Push Stream %d", | 2155 RST_STREAM_REFUSED_STREAM, |
| 2158 associated_stream_id)); | 2156 base::StringPrintf("Rejected Cross Origin Push Stream %d", |
| 2157 associated_stream_id)); |
| 2159 return; | 2158 return; |
| 2160 } | 2159 } |
| 2161 } | 2160 } |
| 2162 | 2161 |
| 2163 // There should not be an existing pushed stream with the same path. | 2162 // There should not be an existing pushed stream with the same path. |
| 2164 PushedStreamMap::iterator pushed_it = | 2163 PushedStreamMap::iterator pushed_it = |
| 2165 unclaimed_pushed_streams_.lower_bound(gurl); | 2164 unclaimed_pushed_streams_.lower_bound(gurl); |
| 2166 if (pushed_it != unclaimed_pushed_streams_.end() && | 2165 if (pushed_it != unclaimed_pushed_streams_.end() && |
| 2167 pushed_it->first == gurl) { | 2166 pushed_it->first == gurl) { |
| 2168 EnqueueResetStreamFrame( | 2167 EnqueueResetStreamFrame( |
| 2169 stream_id, request_priority, RST_STREAM_PROTOCOL_ERROR, | 2168 stream_id, |
| 2170 "Received duplicate pushed stream with url: " + | 2169 request_priority, |
| 2171 gurl.spec()); | 2170 RST_STREAM_PROTOCOL_ERROR, |
| 2171 "Received duplicate pushed stream with url: " + gurl.spec()); |
| 2172 return; | 2172 return; |
| 2173 } | 2173 } |
| 2174 | 2174 |
| 2175 scoped_ptr<SpdyStream> stream( | 2175 scoped_ptr<SpdyStream> stream(new SpdyStream(SPDY_PUSH_STREAM, |
| 2176 new SpdyStream(SPDY_PUSH_STREAM, GetWeakPtr(), gurl, | 2176 GetWeakPtr(), |
| 2177 request_priority, | 2177 gurl, |
| 2178 stream_initial_send_window_size_, | 2178 request_priority, |
| 2179 stream_initial_recv_window_size_, | 2179 stream_initial_send_window_size_, |
| 2180 net_log_)); | 2180 stream_initial_recv_window_size_, |
| 2181 net_log_)); |
| 2181 stream->set_stream_id(stream_id); | 2182 stream->set_stream_id(stream_id); |
| 2182 stream->IncrementRawReceivedBytes(last_compressed_frame_len_); | 2183 stream->IncrementRawReceivedBytes(last_compressed_frame_len_); |
| 2183 last_compressed_frame_len_ = 0; | 2184 last_compressed_frame_len_ = 0; |
| 2184 | 2185 |
| 2185 DeleteExpiredPushedStreams(); | 2186 DeleteExpiredPushedStreams(); |
| 2186 PushedStreamMap::iterator inserted_pushed_it = | 2187 PushedStreamMap::iterator inserted_pushed_it = |
| 2187 unclaimed_pushed_streams_.insert( | 2188 unclaimed_pushed_streams_.insert( |
| 2188 pushed_it, | 2189 pushed_it, |
| 2189 std::make_pair(gurl, PushedStreamInfo(stream_id, time_func_()))); | 2190 std::make_pair(gurl, PushedStreamInfo(stream_id, time_func_()))); |
| 2190 DCHECK(inserted_pushed_it != pushed_it); | 2191 DCHECK(inserted_pushed_it != pushed_it); |
| 2191 | 2192 |
| 2192 InsertActivatedStream(stream.Pass()); | 2193 InsertActivatedStream(stream.Pass()); |
| 2193 | 2194 |
| 2194 ActiveStreamMap::iterator active_it = active_streams_.find(stream_id); | 2195 ActiveStreamMap::iterator active_it = active_streams_.find(stream_id); |
| 2195 if (active_it == active_streams_.end()) { | 2196 if (active_it == active_streams_.end()) { |
| 2196 NOTREACHED(); | 2197 NOTREACHED(); |
| 2197 return; | 2198 return; |
| 2198 } | 2199 } |
| 2199 | 2200 |
| 2200 // Parse the headers. | 2201 // Parse the headers. |
| 2201 if (OnInitialResponseHeadersReceived( | 2202 if (OnInitialResponseHeadersReceived(headers, |
| 2202 headers, response_time, | 2203 response_time, |
| 2203 recv_first_byte_time, active_it->second.stream) != OK) | 2204 recv_first_byte_time, |
| 2205 active_it->second.stream) != OK) |
| 2204 return; | 2206 return; |
| 2205 | 2207 |
| 2206 base::StatsCounter push_requests("spdy.pushed_streams"); | 2208 base::StatsCounter push_requests("spdy.pushed_streams"); |
| 2207 push_requests.Increment(); | 2209 push_requests.Increment(); |
| 2208 } | 2210 } |
| 2209 | 2211 |
| 2210 void SpdySession::DeleteExpiredPushedStreams() { | 2212 void SpdySession::DeleteExpiredPushedStreams() { |
| 2211 if (unclaimed_pushed_streams_.empty()) | 2213 if (unclaimed_pushed_streams_.empty()) |
| 2212 return; | 2214 return; |
| 2213 | 2215 |
| 2214 // Check that adequate time has elapsed since the last sweep. | 2216 // Check that adequate time has elapsed since the last sweep. |
| 2215 if (time_func_() < next_unclaimed_push_stream_sweep_time_) | 2217 if (time_func_() < next_unclaimed_push_stream_sweep_time_) |
| 2216 return; | 2218 return; |
| 2217 | 2219 |
| 2218 // Gather old streams to delete. | 2220 // Gather old streams to delete. |
| 2219 base::TimeTicks minimum_freshness = time_func_() - | 2221 base::TimeTicks minimum_freshness = |
| 2222 time_func_() - |
| 2220 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); | 2223 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); |
| 2221 std::vector<SpdyStreamId> streams_to_close; | 2224 std::vector<SpdyStreamId> streams_to_close; |
| 2222 for (PushedStreamMap::iterator it = unclaimed_pushed_streams_.begin(); | 2225 for (PushedStreamMap::iterator it = unclaimed_pushed_streams_.begin(); |
| 2223 it != unclaimed_pushed_streams_.end(); ++it) { | 2226 it != unclaimed_pushed_streams_.end(); |
| 2227 ++it) { |
| 2224 if (minimum_freshness > it->second.creation_time) | 2228 if (minimum_freshness > it->second.creation_time) |
| 2225 streams_to_close.push_back(it->second.stream_id); | 2229 streams_to_close.push_back(it->second.stream_id); |
| 2226 } | 2230 } |
| 2227 | 2231 |
| 2228 for (std::vector<SpdyStreamId>::const_iterator to_close_it = | 2232 for (std::vector<SpdyStreamId>::const_iterator to_close_it = |
| 2229 streams_to_close.begin(); | 2233 streams_to_close.begin(); |
| 2230 to_close_it != streams_to_close.end(); ++to_close_it) { | 2234 to_close_it != streams_to_close.end(); |
| 2235 ++to_close_it) { |
| 2231 ActiveStreamMap::iterator active_it = active_streams_.find(*to_close_it); | 2236 ActiveStreamMap::iterator active_it = active_streams_.find(*to_close_it); |
| 2232 if (active_it == active_streams_.end()) | 2237 if (active_it == active_streams_.end()) |
| 2233 continue; | 2238 continue; |
| 2234 | 2239 |
| 2235 LogAbandonedActiveStream(active_it, ERR_INVALID_SPDY_STREAM); | 2240 LogAbandonedActiveStream(active_it, ERR_INVALID_SPDY_STREAM); |
| 2236 // CloseActiveStreamIterator() will remove the stream from | 2241 // CloseActiveStreamIterator() will remove the stream from |
| 2237 // |unclaimed_pushed_streams_|. | 2242 // |unclaimed_pushed_streams_|. |
| 2238 ResetStreamIterator( | 2243 ResetStreamIterator( |
| 2239 active_it, RST_STREAM_REFUSED_STREAM, "Stream not claimed."); | 2244 active_it, RST_STREAM_REFUSED_STREAM, "Stream not claimed."); |
| 2240 } | 2245 } |
| 2241 | 2246 |
| 2242 next_unclaimed_push_stream_sweep_time_ = time_func_() + | 2247 next_unclaimed_push_stream_sweep_time_ = |
| 2248 time_func_() + |
| 2243 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); | 2249 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); |
| 2244 } | 2250 } |
| 2245 | 2251 |
| 2246 void SpdySession::OnSynReply(SpdyStreamId stream_id, | 2252 void SpdySession::OnSynReply(SpdyStreamId stream_id, |
| 2247 bool fin, | 2253 bool fin, |
| 2248 const SpdyHeaderBlock& headers) { | 2254 const SpdyHeaderBlock& headers) { |
| 2249 CHECK(in_io_loop_); | 2255 CHECK(in_io_loop_); |
| 2250 | 2256 |
| 2251 if (availability_state_ == STATE_CLOSED) | 2257 if (availability_state_ == STATE_CLOSED) |
| 2252 return; | 2258 return; |
| 2253 | 2259 |
| 2254 base::Time response_time = base::Time::Now(); | 2260 base::Time response_time = base::Time::Now(); |
| 2255 base::TimeTicks recv_first_byte_time = time_func_(); | 2261 base::TimeTicks recv_first_byte_time = time_func_(); |
| 2256 | 2262 |
| 2257 if (net_log().IsLogging()) { | 2263 if (net_log().IsLogging()) { |
| 2258 net_log().AddEvent( | 2264 net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_SYN_REPLY, |
| 2259 NetLog::TYPE_SPDY_SESSION_SYN_REPLY, | 2265 base::Bind(&NetLogSpdySynReplyOrHeadersReceivedCallback, |
| 2260 base::Bind(&NetLogSpdySynReplyOrHeadersReceivedCallback, | 2266 &headers, |
| 2261 &headers, fin, stream_id)); | 2267 fin, |
| 2268 stream_id)); |
| 2262 } | 2269 } |
| 2263 | 2270 |
| 2264 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 2271 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2265 if (it == active_streams_.end()) { | 2272 if (it == active_streams_.end()) { |
| 2266 // NOTE: it may just be that the stream was cancelled. | 2273 // NOTE: it may just be that the stream was cancelled. |
| 2267 return; | 2274 return; |
| 2268 } | 2275 } |
| 2269 | 2276 |
| 2270 SpdyStream* stream = it->second.stream; | 2277 SpdyStream* stream = it->second.stream; |
| 2271 CHECK_EQ(stream->stream_id(), stream_id); | 2278 CHECK_EQ(stream->stream_id(), stream_id); |
| 2272 | 2279 |
| 2273 stream->IncrementRawReceivedBytes(last_compressed_frame_len_); | 2280 stream->IncrementRawReceivedBytes(last_compressed_frame_len_); |
| 2274 last_compressed_frame_len_ = 0; | 2281 last_compressed_frame_len_ = 0; |
| 2275 | 2282 |
| 2276 if (GetProtocolVersion() >= SPDY4) { | 2283 if (GetProtocolVersion() >= SPDY4) { |
| 2277 const std::string& error = | 2284 const std::string& error = "SPDY4 wasn't expecting SYN_REPLY."; |
| 2278 "SPDY4 wasn't expecting SYN_REPLY."; | |
| 2279 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); | 2285 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 2280 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); | 2286 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); |
| 2281 return; | 2287 return; |
| 2282 } | 2288 } |
| 2283 if (!it->second.waiting_for_syn_reply) { | 2289 if (!it->second.waiting_for_syn_reply) { |
| 2284 const std::string& error = | 2290 const std::string& error = "Received duplicate SYN_REPLY for stream."; |
| 2285 "Received duplicate SYN_REPLY for stream."; | |
| 2286 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); | 2291 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 2287 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); | 2292 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); |
| 2288 return; | 2293 return; |
| 2289 } | 2294 } |
| 2290 it->second.waiting_for_syn_reply = false; | 2295 it->second.waiting_for_syn_reply = false; |
| 2291 | 2296 |
| 2292 ignore_result(OnInitialResponseHeadersReceived( | 2297 ignore_result(OnInitialResponseHeadersReceived( |
| 2293 headers, response_time, recv_first_byte_time, stream)); | 2298 headers, response_time, recv_first_byte_time, stream)); |
| 2294 } | 2299 } |
| 2295 | 2300 |
| 2296 void SpdySession::OnHeaders(SpdyStreamId stream_id, | 2301 void SpdySession::OnHeaders(SpdyStreamId stream_id, |
| 2297 bool fin, | 2302 bool fin, |
| 2298 const SpdyHeaderBlock& headers) { | 2303 const SpdyHeaderBlock& headers) { |
| 2299 CHECK(in_io_loop_); | 2304 CHECK(in_io_loop_); |
| 2300 | 2305 |
| 2301 if (availability_state_ == STATE_CLOSED) | 2306 if (availability_state_ == STATE_CLOSED) |
| 2302 return; | 2307 return; |
| 2303 | 2308 |
| 2304 if (net_log().IsLogging()) { | 2309 if (net_log().IsLogging()) { |
| 2305 net_log().AddEvent( | 2310 net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_RECV_HEADERS, |
| 2306 NetLog::TYPE_SPDY_SESSION_RECV_HEADERS, | 2311 base::Bind(&NetLogSpdySynReplyOrHeadersReceivedCallback, |
| 2307 base::Bind(&NetLogSpdySynReplyOrHeadersReceivedCallback, | 2312 &headers, |
| 2308 &headers, fin, stream_id)); | 2313 fin, |
| 2314 stream_id)); |
| 2309 } | 2315 } |
| 2310 | 2316 |
| 2311 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 2317 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2312 if (it == active_streams_.end()) { | 2318 if (it == active_streams_.end()) { |
| 2313 // NOTE: it may just be that the stream was cancelled. | 2319 // NOTE: it may just be that the stream was cancelled. |
| 2314 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; | 2320 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; |
| 2315 return; | 2321 return; |
| 2316 } | 2322 } |
| 2317 | 2323 |
| 2318 SpdyStream* stream = it->second.stream; | 2324 SpdyStream* stream = it->second.stream; |
| 2319 CHECK_EQ(stream->stream_id(), stream_id); | 2325 CHECK_EQ(stream->stream_id(), stream_id); |
| 2320 | 2326 |
| 2321 stream->IncrementRawReceivedBytes(last_compressed_frame_len_); | 2327 stream->IncrementRawReceivedBytes(last_compressed_frame_len_); |
| 2322 last_compressed_frame_len_ = 0; | 2328 last_compressed_frame_len_ = 0; |
| 2323 | 2329 |
| 2324 if (it->second.waiting_for_syn_reply) { | 2330 if (it->second.waiting_for_syn_reply) { |
| 2325 if (GetProtocolVersion() < SPDY4) { | 2331 if (GetProtocolVersion() < SPDY4) { |
| 2326 const std::string& error = | 2332 const std::string& error = "Was expecting SYN_REPLY, not HEADERS."; |
| 2327 "Was expecting SYN_REPLY, not HEADERS."; | |
| 2328 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); | 2333 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 2329 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); | 2334 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); |
| 2330 return; | 2335 return; |
| 2331 } | 2336 } |
| 2332 base::Time response_time = base::Time::Now(); | 2337 base::Time response_time = base::Time::Now(); |
| 2333 base::TimeTicks recv_first_byte_time = time_func_(); | 2338 base::TimeTicks recv_first_byte_time = time_func_(); |
| 2334 | 2339 |
| 2335 it->second.waiting_for_syn_reply = false; | 2340 it->second.waiting_for_syn_reply = false; |
| 2336 ignore_result(OnInitialResponseHeadersReceived( | 2341 ignore_result(OnInitialResponseHeadersReceived( |
| 2337 headers, response_time, recv_first_byte_time, stream)); | 2342 headers, response_time, recv_first_byte_time, stream)); |
| 2338 } else { | 2343 } else { |
| 2339 int rv = stream->OnAdditionalResponseHeadersReceived(headers); | 2344 int rv = stream->OnAdditionalResponseHeadersReceived(headers); |
| 2340 if (rv < 0) { | 2345 if (rv < 0) { |
| 2341 DCHECK_NE(rv, ERR_IO_PENDING); | 2346 DCHECK_NE(rv, ERR_IO_PENDING); |
| 2342 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); | 2347 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); |
| 2343 } | 2348 } |
| 2344 } | 2349 } |
| 2345 } | 2350 } |
| 2346 | 2351 |
| 2347 void SpdySession::OnRstStream(SpdyStreamId stream_id, | 2352 void SpdySession::OnRstStream(SpdyStreamId stream_id, |
| 2348 SpdyRstStreamStatus status) { | 2353 SpdyRstStreamStatus status) { |
| 2349 CHECK(in_io_loop_); | 2354 CHECK(in_io_loop_); |
| 2350 | 2355 |
| 2351 if (availability_state_ == STATE_CLOSED) | 2356 if (availability_state_ == STATE_CLOSED) |
| 2352 return; | 2357 return; |
| 2353 | 2358 |
| 2354 std::string description; | 2359 std::string description; |
| 2355 net_log().AddEvent( | 2360 net_log().AddEvent( |
| 2356 NetLog::TYPE_SPDY_SESSION_RST_STREAM, | 2361 NetLog::TYPE_SPDY_SESSION_RST_STREAM, |
| 2357 base::Bind(&NetLogSpdyRstCallback, | 2362 base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description)); |
| 2358 stream_id, status, &description)); | |
| 2359 | 2363 |
| 2360 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | 2364 ActiveStreamMap::iterator it = active_streams_.find(stream_id); |
| 2361 if (it == active_streams_.end()) { | 2365 if (it == active_streams_.end()) { |
| 2362 // NOTE: it may just be that the stream was cancelled. | 2366 // NOTE: it may just be that the stream was cancelled. |
| 2363 LOG(WARNING) << "Received RST for invalid stream" << stream_id; | 2367 LOG(WARNING) << "Received RST for invalid stream" << stream_id; |
| 2364 return; | 2368 return; |
| 2365 } | 2369 } |
| 2366 | 2370 |
| 2367 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 2371 CHECK_EQ(it->second.stream->stream_id(), stream_id); |
| 2368 | 2372 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2383 } | 2387 } |
| 2384 | 2388 |
| 2385 void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id, | 2389 void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id, |
| 2386 SpdyGoAwayStatus status) { | 2390 SpdyGoAwayStatus status) { |
| 2387 CHECK(in_io_loop_); | 2391 CHECK(in_io_loop_); |
| 2388 | 2392 |
| 2389 if (availability_state_ == STATE_CLOSED) | 2393 if (availability_state_ == STATE_CLOSED) |
| 2390 return; | 2394 return; |
| 2391 | 2395 |
| 2392 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_GOAWAY, | 2396 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_GOAWAY, |
| 2393 base::Bind(&NetLogSpdyGoAwayCallback, | 2397 base::Bind(&NetLogSpdyGoAwayCallback, |
| 2394 last_accepted_stream_id, | 2398 last_accepted_stream_id, |
| 2395 active_streams_.size(), | 2399 active_streams_.size(), |
| 2396 unclaimed_pushed_streams_.size(), | 2400 unclaimed_pushed_streams_.size(), |
| 2397 status)); | 2401 status)); |
| 2398 MakeUnavailable(); | 2402 MakeUnavailable(); |
| 2399 StartGoingAway(last_accepted_stream_id, ERR_ABORTED); | 2403 StartGoingAway(last_accepted_stream_id, ERR_ABORTED); |
| 2400 // This is to handle the case when we already don't have any active | 2404 // This is to handle the case when we already don't have any active |
| 2401 // streams (i.e., StartGoingAway() did nothing). Otherwise, we have | 2405 // streams (i.e., StartGoingAway() did nothing). Otherwise, we have |
| 2402 // active streams and so the last one being closed will finish the | 2406 // active streams and so the last one being closed will finish the |
| 2403 // going away process (see DeleteStream()). | 2407 // going away process (see DeleteStream()). |
| 2404 MaybeFinishGoingAway(); | 2408 MaybeFinishGoingAway(); |
| 2405 } | 2409 } |
| 2406 | 2410 |
| 2407 void SpdySession::OnPing(SpdyPingId unique_id, bool is_ack) { | 2411 void SpdySession::OnPing(SpdyPingId unique_id, bool is_ack) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2442 void SpdySession::OnWindowUpdate(SpdyStreamId stream_id, | 2446 void SpdySession::OnWindowUpdate(SpdyStreamId stream_id, |
| 2443 uint32 delta_window_size) { | 2447 uint32 delta_window_size) { |
| 2444 CHECK(in_io_loop_); | 2448 CHECK(in_io_loop_); |
| 2445 | 2449 |
| 2446 if (availability_state_ == STATE_CLOSED) | 2450 if (availability_state_ == STATE_CLOSED) |
| 2447 return; | 2451 return; |
| 2448 | 2452 |
| 2449 DCHECK_LE(delta_window_size, static_cast<uint32>(kint32max)); | 2453 DCHECK_LE(delta_window_size, static_cast<uint32>(kint32max)); |
| 2450 net_log_.AddEvent( | 2454 net_log_.AddEvent( |
| 2451 NetLog::TYPE_SPDY_SESSION_RECEIVED_WINDOW_UPDATE_FRAME, | 2455 NetLog::TYPE_SPDY_SESSION_RECEIVED_WINDOW_UPDATE_FRAME, |
| 2452 base::Bind(&NetLogSpdyWindowUpdateFrameCallback, | 2456 base::Bind( |
| 2453 stream_id, delta_window_size)); | 2457 &NetLogSpdyWindowUpdateFrameCallback, stream_id, delta_window_size)); |
| 2454 | 2458 |
| 2455 if (stream_id == kSessionFlowControlStreamId) { | 2459 if (stream_id == kSessionFlowControlStreamId) { |
| 2456 // WINDOW_UPDATE for the session. | 2460 // WINDOW_UPDATE for the session. |
| 2457 if (flow_control_state_ < FLOW_CONTROL_STREAM_AND_SESSION) { | 2461 if (flow_control_state_ < FLOW_CONTROL_STREAM_AND_SESSION) { |
| 2458 LOG(WARNING) << "Received WINDOW_UPDATE for session when " | 2462 LOG(WARNING) << "Received WINDOW_UPDATE for session when " |
| 2459 << "session flow control is not turned on"; | 2463 << "session flow control is not turned on"; |
| 2460 // TODO(akalin): Record an error and close the session. | 2464 // TODO(akalin): Record an error and close the session. |
| 2461 return; | 2465 return; |
| 2462 } | 2466 } |
| 2463 | 2467 |
| 2464 if (delta_window_size < 1u) { | 2468 if (delta_window_size < 1u) { |
| 2465 RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE); | 2469 RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE); |
| 2466 CloseSessionResult result = DoCloseSession( | 2470 CloseSessionResult result = DoCloseSession( |
| 2467 ERR_SPDY_PROTOCOL_ERROR, | 2471 ERR_SPDY_PROTOCOL_ERROR, |
| 2468 "Received WINDOW_UPDATE with an invalid delta_window_size " + | 2472 "Received WINDOW_UPDATE with an invalid delta_window_size " + |
| 2469 base::UintToString(delta_window_size)); | 2473 base::UintToString(delta_window_size)); |
| 2470 DCHECK_EQ(result, SESSION_CLOSED_BUT_NOT_REMOVED); | 2474 DCHECK_EQ(result, SESSION_CLOSED_BUT_NOT_REMOVED); |
| 2471 return; | 2475 return; |
| 2472 } | 2476 } |
| 2473 | 2477 |
| 2474 IncreaseSendWindowSize(static_cast<int32>(delta_window_size)); | 2478 IncreaseSendWindowSize(static_cast<int32>(delta_window_size)); |
| 2475 } else { | 2479 } else { |
| 2476 // WINDOW_UPDATE for a stream. | 2480 // WINDOW_UPDATE for a stream. |
| 2477 if (flow_control_state_ < FLOW_CONTROL_STREAM) { | 2481 if (flow_control_state_ < FLOW_CONTROL_STREAM) { |
| 2478 // TODO(akalin): Record an error and close the session. | 2482 // TODO(akalin): Record an error and close the session. |
| 2479 LOG(WARNING) << "Received WINDOW_UPDATE for stream " << stream_id | 2483 LOG(WARNING) << "Received WINDOW_UPDATE for stream " << stream_id |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2490 } | 2494 } |
| 2491 | 2495 |
| 2492 SpdyStream* stream = it->second.stream; | 2496 SpdyStream* stream = it->second.stream; |
| 2493 CHECK_EQ(stream->stream_id(), stream_id); | 2497 CHECK_EQ(stream->stream_id(), stream_id); |
| 2494 | 2498 |
| 2495 if (delta_window_size < 1u) { | 2499 if (delta_window_size < 1u) { |
| 2496 ResetStreamIterator(it, | 2500 ResetStreamIterator(it, |
| 2497 RST_STREAM_FLOW_CONTROL_ERROR, | 2501 RST_STREAM_FLOW_CONTROL_ERROR, |
| 2498 base::StringPrintf( | 2502 base::StringPrintf( |
| 2499 "Received WINDOW_UPDATE with an invalid " | 2503 "Received WINDOW_UPDATE with an invalid " |
| 2500 "delta_window_size %ud", delta_window_size)); | 2504 "delta_window_size %ud", |
| 2505 delta_window_size)); |
| 2501 return; | 2506 return; |
| 2502 } | 2507 } |
| 2503 | 2508 |
| 2504 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 2509 CHECK_EQ(it->second.stream->stream_id(), stream_id); |
| 2505 it->second.stream->IncreaseSendWindowSize( | 2510 it->second.stream->IncreaseSendWindowSize( |
| 2506 static_cast<int32>(delta_window_size)); | 2511 static_cast<int32>(delta_window_size)); |
| 2507 } | 2512 } |
| 2508 } | 2513 } |
| 2509 | 2514 |
| 2510 void SpdySession::OnPushPromise(SpdyStreamId stream_id, | 2515 void SpdySession::OnPushPromise(SpdyStreamId stream_id, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2526 DCHECK(enable_sending_initial_data_); | 2531 DCHECK(enable_sending_initial_data_); |
| 2527 DCHECK_NE(availability_state_, STATE_CLOSED); | 2532 DCHECK_NE(availability_state_, STATE_CLOSED); |
| 2528 | 2533 |
| 2529 if (send_connection_header_prefix_) { | 2534 if (send_connection_header_prefix_) { |
| 2530 DCHECK_EQ(protocol_, kProtoSPDY4); | 2535 DCHECK_EQ(protocol_, kProtoSPDY4); |
| 2531 scoped_ptr<SpdyFrame> connection_header_prefix_frame( | 2536 scoped_ptr<SpdyFrame> connection_header_prefix_frame( |
| 2532 new SpdyFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix), | 2537 new SpdyFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix), |
| 2533 kHttp2ConnectionHeaderPrefixSize, | 2538 kHttp2ConnectionHeaderPrefixSize, |
| 2534 false /* take_ownership */)); | 2539 false /* take_ownership */)); |
| 2535 // Count the prefix as part of the subsequent SETTINGS frame. | 2540 // Count the prefix as part of the subsequent SETTINGS frame. |
| 2536 EnqueueSessionWrite(HIGHEST, SETTINGS, | 2541 EnqueueSessionWrite( |
| 2537 connection_header_prefix_frame.Pass()); | 2542 HIGHEST, SETTINGS, connection_header_prefix_frame.Pass()); |
| 2538 } | 2543 } |
| 2539 | 2544 |
| 2540 // First, notify the server about the settings they should use when | 2545 // First, notify the server about the settings they should use when |
| 2541 // communicating with us. | 2546 // communicating with us. |
| 2542 SettingsMap settings_map; | 2547 SettingsMap settings_map; |
| 2543 // Create a new settings frame notifying the server of our | 2548 // Create a new settings frame notifying the server of our |
| 2544 // max concurrent streams and initial window size. | 2549 // max concurrent streams and initial window size. |
| 2545 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = | 2550 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = |
| 2546 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); | 2551 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); |
| 2547 if (flow_control_state_ >= FLOW_CONTROL_STREAM && | 2552 if (flow_control_state_ >= FLOW_CONTROL_STREAM && |
| 2548 stream_initial_recv_window_size_ != kSpdyStreamInitialWindowSize) { | 2553 stream_initial_recv_window_size_ != kSpdyStreamInitialWindowSize) { |
| 2549 settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = | 2554 settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = SettingsFlagsAndValue( |
| 2550 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, | 2555 SETTINGS_FLAG_NONE, stream_initial_recv_window_size_); |
| 2551 stream_initial_recv_window_size_); | |
| 2552 } | 2556 } |
| 2553 SendSettings(settings_map); | 2557 SendSettings(settings_map); |
| 2554 | 2558 |
| 2555 // Next, notify the server about our initial recv window size. | 2559 // Next, notify the server about our initial recv window size. |
| 2556 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { | 2560 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { |
| 2557 // Bump up the receive window size to the real initial value. This | 2561 // Bump up the receive window size to the real initial value. This |
| 2558 // has to go here since the WINDOW_UPDATE frame sent by | 2562 // has to go here since the WINDOW_UPDATE frame sent by |
| 2559 // IncreaseRecvWindowSize() call uses |buffered_spdy_framer_|. | 2563 // IncreaseRecvWindowSize() call uses |buffered_spdy_framer_|. |
| 2560 DCHECK_GT(kDefaultInitialRecvWindowSize, session_recv_window_size_); | 2564 DCHECK_GT(kDefaultInitialRecvWindowSize, session_recv_window_size_); |
| 2561 // This condition implies that |kDefaultInitialRecvWindowSize| - | 2565 // This condition implies that |kDefaultInitialRecvWindowSize| - |
| 2562 // |session_recv_window_size_| doesn't overflow. | 2566 // |session_recv_window_size_| doesn't overflow. |
| 2563 DCHECK_GT(session_recv_window_size_, 0); | 2567 DCHECK_GT(session_recv_window_size_, 0); |
| 2564 IncreaseRecvWindowSize( | 2568 IncreaseRecvWindowSize(kDefaultInitialRecvWindowSize - |
| 2565 kDefaultInitialRecvWindowSize - session_recv_window_size_); | 2569 session_recv_window_size_); |
| 2566 } | 2570 } |
| 2567 | 2571 |
| 2568 // Finally, notify the server about the settings they have | 2572 // Finally, notify the server about the settings they have |
| 2569 // previously told us to use when communicating with them (after | 2573 // previously told us to use when communicating with them (after |
| 2570 // applying them). | 2574 // applying them). |
| 2571 const SettingsMap& server_settings_map = | 2575 const SettingsMap& server_settings_map = |
| 2572 http_server_properties_->GetSpdySettings(host_port_pair()); | 2576 http_server_properties_->GetSpdySettings(host_port_pair()); |
| 2573 if (server_settings_map.empty()) | 2577 if (server_settings_map.empty()) |
| 2574 return; | 2578 return; |
| 2575 | 2579 |
| 2576 SettingsMap::const_iterator it = | 2580 SettingsMap::const_iterator it = |
| 2577 server_settings_map.find(SETTINGS_CURRENT_CWND); | 2581 server_settings_map.find(SETTINGS_CURRENT_CWND); |
| 2578 uint32 cwnd = (it != server_settings_map.end()) ? it->second.second : 0; | 2582 uint32 cwnd = (it != server_settings_map.end()) ? it->second.second : 0; |
| 2579 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwndSent", cwnd, 1, 200, 100); | 2583 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwndSent", cwnd, 1, 200, 100); |
| 2580 | 2584 |
| 2581 for (SettingsMap::const_iterator it = server_settings_map.begin(); | 2585 for (SettingsMap::const_iterator it = server_settings_map.begin(); |
| 2582 it != server_settings_map.end(); ++it) { | 2586 it != server_settings_map.end(); |
| 2587 ++it) { |
| 2583 const SpdySettingsIds new_id = it->first; | 2588 const SpdySettingsIds new_id = it->first; |
| 2584 const uint32 new_val = it->second.second; | 2589 const uint32 new_val = it->second.second; |
| 2585 HandleSetting(new_id, new_val); | 2590 HandleSetting(new_id, new_val); |
| 2586 } | 2591 } |
| 2587 | 2592 |
| 2588 SendSettings(server_settings_map); | 2593 SendSettings(server_settings_map); |
| 2589 } | 2594 } |
| 2590 | 2595 |
| 2591 | |
| 2592 void SpdySession::SendSettings(const SettingsMap& settings) { | 2596 void SpdySession::SendSettings(const SettingsMap& settings) { |
| 2593 DCHECK_NE(availability_state_, STATE_CLOSED); | 2597 DCHECK_NE(availability_state_, STATE_CLOSED); |
| 2594 | 2598 |
| 2595 net_log_.AddEvent( | 2599 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, |
| 2596 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, | 2600 base::Bind(&NetLogSpdySendSettingsCallback, &settings)); |
| 2597 base::Bind(&NetLogSpdySendSettingsCallback, &settings)); | |
| 2598 | 2601 |
| 2599 // Create the SETTINGS frame and send it. | 2602 // Create the SETTINGS frame and send it. |
| 2600 DCHECK(buffered_spdy_framer_.get()); | 2603 DCHECK(buffered_spdy_framer_.get()); |
| 2601 scoped_ptr<SpdyFrame> settings_frame( | 2604 scoped_ptr<SpdyFrame> settings_frame( |
| 2602 buffered_spdy_framer_->CreateSettings(settings)); | 2605 buffered_spdy_framer_->CreateSettings(settings)); |
| 2603 sent_settings_ = true; | 2606 sent_settings_ = true; |
| 2604 EnqueueSessionWrite(HIGHEST, SETTINGS, settings_frame.Pass()); | 2607 EnqueueSessionWrite(HIGHEST, SETTINGS, settings_frame.Pass()); |
| 2605 } | 2608 } |
| 2606 | 2609 |
| 2607 void SpdySession::HandleSetting(uint32 id, uint32 value) { | 2610 void SpdySession::HandleSetting(uint32 id, uint32 value) { |
| 2608 switch (id) { | 2611 switch (id) { |
| 2609 case SETTINGS_MAX_CONCURRENT_STREAMS: | 2612 case SETTINGS_MAX_CONCURRENT_STREAMS: |
| 2610 max_concurrent_streams_ = std::min(static_cast<size_t>(value), | 2613 max_concurrent_streams_ = |
| 2611 kMaxConcurrentStreamLimit); | 2614 std::min(static_cast<size_t>(value), kMaxConcurrentStreamLimit); |
| 2612 ProcessPendingStreamRequests(); | 2615 ProcessPendingStreamRequests(); |
| 2613 break; | 2616 break; |
| 2614 case SETTINGS_INITIAL_WINDOW_SIZE: { | 2617 case SETTINGS_INITIAL_WINDOW_SIZE: { |
| 2615 if (flow_control_state_ < FLOW_CONTROL_STREAM) { | 2618 if (flow_control_state_ < FLOW_CONTROL_STREAM) { |
| 2616 net_log().AddEvent( | 2619 net_log().AddEvent( |
| 2617 NetLog::TYPE_SPDY_SESSION_INITIAL_WINDOW_SIZE_NO_FLOW_CONTROL); | 2620 NetLog::TYPE_SPDY_SESSION_INITIAL_WINDOW_SIZE_NO_FLOW_CONTROL); |
| 2618 return; | 2621 return; |
| 2619 } | 2622 } |
| 2620 | 2623 |
| 2621 if (value > static_cast<uint32>(kint32max)) { | 2624 if (value > static_cast<uint32>(kint32max)) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2634 NetLog::TYPE_SPDY_SESSION_UPDATE_STREAMS_SEND_WINDOW_SIZE, | 2637 NetLog::TYPE_SPDY_SESSION_UPDATE_STREAMS_SEND_WINDOW_SIZE, |
| 2635 NetLog::IntegerCallback("delta_window_size", delta_window_size)); | 2638 NetLog::IntegerCallback("delta_window_size", delta_window_size)); |
| 2636 break; | 2639 break; |
| 2637 } | 2640 } |
| 2638 } | 2641 } |
| 2639 } | 2642 } |
| 2640 | 2643 |
| 2641 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) { | 2644 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) { |
| 2642 DCHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM); | 2645 DCHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM); |
| 2643 for (ActiveStreamMap::iterator it = active_streams_.begin(); | 2646 for (ActiveStreamMap::iterator it = active_streams_.begin(); |
| 2644 it != active_streams_.end(); ++it) { | 2647 it != active_streams_.end(); |
| 2648 ++it) { |
| 2645 it->second.stream->AdjustSendWindowSize(delta_window_size); | 2649 it->second.stream->AdjustSendWindowSize(delta_window_size); |
| 2646 } | 2650 } |
| 2647 | 2651 |
| 2648 for (CreatedStreamSet::const_iterator it = created_streams_.begin(); | 2652 for (CreatedStreamSet::const_iterator it = created_streams_.begin(); |
| 2649 it != created_streams_.end(); it++) { | 2653 it != created_streams_.end(); |
| 2654 it++) { |
| 2650 (*it)->AdjustSendWindowSize(delta_window_size); | 2655 (*it)->AdjustSendWindowSize(delta_window_size); |
| 2651 } | 2656 } |
| 2652 } | 2657 } |
| 2653 | 2658 |
| 2654 void SpdySession::SendPrefacePingIfNoneInFlight() { | 2659 void SpdySession::SendPrefacePingIfNoneInFlight() { |
| 2655 if (pings_in_flight_ || !enable_ping_based_connection_checking_) | 2660 if (pings_in_flight_ || !enable_ping_based_connection_checking_) |
| 2656 return; | 2661 return; |
| 2657 | 2662 |
| 2658 base::TimeTicks now = time_func_(); | 2663 base::TimeTicks now = time_func_(); |
| 2659 // If there is no activity in the session, then send a preface-PING. | 2664 // If there is no activity in the session, then send a preface-PING. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2672 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 2677 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
| 2673 if (it != active_streams_.end()) { | 2678 if (it != active_streams_.end()) { |
| 2674 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 2679 CHECK_EQ(it->second.stream->stream_id(), stream_id); |
| 2675 } else { | 2680 } else { |
| 2676 CHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); | 2681 CHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); |
| 2677 CHECK_EQ(stream_id, kSessionFlowControlStreamId); | 2682 CHECK_EQ(stream_id, kSessionFlowControlStreamId); |
| 2678 } | 2683 } |
| 2679 | 2684 |
| 2680 net_log_.AddEvent( | 2685 net_log_.AddEvent( |
| 2681 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE_FRAME, | 2686 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE_FRAME, |
| 2682 base::Bind(&NetLogSpdyWindowUpdateFrameCallback, | 2687 base::Bind( |
| 2683 stream_id, delta_window_size)); | 2688 &NetLogSpdyWindowUpdateFrameCallback, stream_id, delta_window_size)); |
| 2684 | 2689 |
| 2685 DCHECK(buffered_spdy_framer_.get()); | 2690 DCHECK(buffered_spdy_framer_.get()); |
| 2686 scoped_ptr<SpdyFrame> window_update_frame( | 2691 scoped_ptr<SpdyFrame> window_update_frame( |
| 2687 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size)); | 2692 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size)); |
| 2688 EnqueueSessionWrite(priority, WINDOW_UPDATE, window_update_frame.Pass()); | 2693 EnqueueSessionWrite(priority, WINDOW_UPDATE, window_update_frame.Pass()); |
| 2689 } | 2694 } |
| 2690 | 2695 |
| 2691 void SpdySession::WritePingFrame(uint32 unique_id, bool is_ack) { | 2696 void SpdySession::WritePingFrame(uint32 unique_id, bool is_ack) { |
| 2692 DCHECK(buffered_spdy_framer_.get()); | 2697 DCHECK(buffered_spdy_framer_.get()); |
| 2693 scoped_ptr<SpdyFrame> ping_frame( | 2698 scoped_ptr<SpdyFrame> ping_frame( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2707 } | 2712 } |
| 2708 } | 2713 } |
| 2709 | 2714 |
| 2710 void SpdySession::PlanToCheckPingStatus() { | 2715 void SpdySession::PlanToCheckPingStatus() { |
| 2711 if (check_ping_status_pending_) | 2716 if (check_ping_status_pending_) |
| 2712 return; | 2717 return; |
| 2713 | 2718 |
| 2714 check_ping_status_pending_ = true; | 2719 check_ping_status_pending_ = true; |
| 2715 base::MessageLoop::current()->PostDelayedTask( | 2720 base::MessageLoop::current()->PostDelayedTask( |
| 2716 FROM_HERE, | 2721 FROM_HERE, |
| 2717 base::Bind(&SpdySession::CheckPingStatus, weak_factory_.GetWeakPtr(), | 2722 base::Bind(&SpdySession::CheckPingStatus, |
| 2718 time_func_()), hung_interval_); | 2723 weak_factory_.GetWeakPtr(), |
| 2724 time_func_()), |
| 2725 hung_interval_); |
| 2719 } | 2726 } |
| 2720 | 2727 |
| 2721 void SpdySession::CheckPingStatus(base::TimeTicks last_check_time) { | 2728 void SpdySession::CheckPingStatus(base::TimeTicks last_check_time) { |
| 2722 CHECK(!in_io_loop_); | 2729 CHECK(!in_io_loop_); |
| 2723 DCHECK_NE(availability_state_, STATE_CLOSED); | 2730 DCHECK_NE(availability_state_, STATE_CLOSED); |
| 2724 | 2731 |
| 2725 // Check if we got a response back for all PINGs we had sent. | 2732 // Check if we got a response back for all PINGs we had sent. |
| 2726 if (pings_in_flight_ == 0) { | 2733 if (pings_in_flight_ == 0) { |
| 2727 check_ping_status_pending_ = false; | 2734 check_ping_status_pending_ = false; |
| 2728 return; | 2735 return; |
| 2729 } | 2736 } |
| 2730 | 2737 |
| 2731 DCHECK(check_ping_status_pending_); | 2738 DCHECK(check_ping_status_pending_); |
| 2732 | 2739 |
| 2733 base::TimeTicks now = time_func_(); | 2740 base::TimeTicks now = time_func_(); |
| 2734 base::TimeDelta delay = hung_interval_ - (now - last_activity_time_); | 2741 base::TimeDelta delay = hung_interval_ - (now - last_activity_time_); |
| 2735 | 2742 |
| 2736 if (delay.InMilliseconds() < 0 || last_activity_time_ < last_check_time) { | 2743 if (delay.InMilliseconds() < 0 || last_activity_time_ < last_check_time) { |
| 2737 // Track all failed PING messages in a separate bucket. | 2744 // Track all failed PING messages in a separate bucket. |
| 2738 RecordPingRTTHistogram(base::TimeDelta::Max()); | 2745 RecordPingRTTHistogram(base::TimeDelta::Max()); |
| 2739 CloseSessionResult result = | 2746 CloseSessionResult result = |
| 2740 DoCloseSession(ERR_SPDY_PING_FAILED, "Failed ping."); | 2747 DoCloseSession(ERR_SPDY_PING_FAILED, "Failed ping."); |
| 2741 DCHECK_EQ(result, SESSION_CLOSED_AND_REMOVED); | 2748 DCHECK_EQ(result, SESSION_CLOSED_AND_REMOVED); |
| 2742 return; | 2749 return; |
| 2743 } | 2750 } |
| 2744 | 2751 |
| 2745 // Check the status of connection after a delay. | 2752 // Check the status of connection after a delay. |
| 2746 base::MessageLoop::current()->PostDelayedTask( | 2753 base::MessageLoop::current()->PostDelayedTask( |
| 2747 FROM_HERE, | 2754 FROM_HERE, |
| 2748 base::Bind(&SpdySession::CheckPingStatus, weak_factory_.GetWeakPtr(), | 2755 base::Bind( |
| 2749 now), | 2756 &SpdySession::CheckPingStatus, weak_factory_.GetWeakPtr(), now), |
| 2750 delay); | 2757 delay); |
| 2751 } | 2758 } |
| 2752 | 2759 |
| 2753 void SpdySession::RecordPingRTTHistogram(base::TimeDelta duration) { | 2760 void SpdySession::RecordPingRTTHistogram(base::TimeDelta duration) { |
| 2754 UMA_HISTOGRAM_TIMES("Net.SpdyPing.RTT", duration); | 2761 UMA_HISTOGRAM_TIMES("Net.SpdyPing.RTT", duration); |
| 2755 } | 2762 } |
| 2756 | 2763 |
| 2757 void SpdySession::RecordProtocolErrorHistogram( | 2764 void SpdySession::RecordProtocolErrorHistogram( |
| 2758 SpdyProtocolErrorDetails details) { | 2765 SpdyProtocolErrorDetails details) { |
| 2759 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionErrorDetails2", details, | 2766 UMA_HISTOGRAM_ENUMERATION( |
| 2760 NUM_SPDY_PROTOCOL_ERROR_DETAILS); | 2767 "Net.SpdySessionErrorDetails2", details, NUM_SPDY_PROTOCOL_ERROR_DETAILS); |
| 2761 if (EndsWith(host_port_pair().host(), "google.com", false)) { | 2768 if (EndsWith(host_port_pair().host(), "google.com", false)) { |
| 2762 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionErrorDetails_Google2", details, | 2769 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionErrorDetails_Google2", |
| 2770 details, |
| 2763 NUM_SPDY_PROTOCOL_ERROR_DETAILS); | 2771 NUM_SPDY_PROTOCOL_ERROR_DETAILS); |
| 2764 } | 2772 } |
| 2765 } | 2773 } |
| 2766 | 2774 |
| 2767 void SpdySession::RecordHistograms() { | 2775 void SpdySession::RecordHistograms() { |
| 2768 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession", | 2776 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 2769 streams_initiated_count_, | 2777 "Net.SpdyStreamsPerSession", streams_initiated_count_, 0, 300, 50); |
| 2770 0, 300, 50); | 2778 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 2771 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedPerSession", | 2779 "Net.SpdyStreamsPushedPerSession", streams_pushed_count_, 0, 300, 50); |
| 2772 streams_pushed_count_, | |
| 2773 0, 300, 50); | |
| 2774 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedAndClaimedPerSession", | 2780 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedAndClaimedPerSession", |
| 2775 streams_pushed_and_claimed_count_, | 2781 streams_pushed_and_claimed_count_, |
| 2776 0, 300, 50); | 2782 0, |
| 2783 300, |
| 2784 50); |
| 2777 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsAbandonedPerSession", | 2785 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsAbandonedPerSession", |
| 2778 streams_abandoned_count_, | 2786 streams_abandoned_count_, |
| 2779 0, 300, 50); | 2787 0, |
| 2780 UMA_HISTOGRAM_ENUMERATION("Net.SpdySettingsSent", | 2788 300, |
| 2781 sent_settings_ ? 1 : 0, 2); | 2789 50); |
| 2782 UMA_HISTOGRAM_ENUMERATION("Net.SpdySettingsReceived", | 2790 UMA_HISTOGRAM_ENUMERATION("Net.SpdySettingsSent", sent_settings_ ? 1 : 0, 2); |
| 2783 received_settings_ ? 1 : 0, 2); | 2791 UMA_HISTOGRAM_ENUMERATION( |
| 2784 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamStallsPerSession", | 2792 "Net.SpdySettingsReceived", received_settings_ ? 1 : 0, 2); |
| 2785 stalled_streams_, | 2793 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 2786 0, 300, 50); | 2794 "Net.SpdyStreamStallsPerSession", stalled_streams_, 0, 300, 50); |
| 2787 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionsWithStalls", | 2795 UMA_HISTOGRAM_ENUMERATION( |
| 2788 stalled_streams_ > 0 ? 1 : 0, 2); | 2796 "Net.SpdySessionsWithStalls", stalled_streams_ > 0 ? 1 : 0, 2); |
| 2789 | 2797 |
| 2790 if (received_settings_) { | 2798 if (received_settings_) { |
| 2791 // Enumerate the saved settings, and set histograms for it. | 2799 // Enumerate the saved settings, and set histograms for it. |
| 2792 const SettingsMap& settings_map = | 2800 const SettingsMap& settings_map = |
| 2793 http_server_properties_->GetSpdySettings(host_port_pair()); | 2801 http_server_properties_->GetSpdySettings(host_port_pair()); |
| 2794 | 2802 |
| 2795 SettingsMap::const_iterator it; | 2803 SettingsMap::const_iterator it; |
| 2796 for (it = settings_map.begin(); it != settings_map.end(); ++it) { | 2804 for (it = settings_map.begin(); it != settings_map.end(); ++it) { |
| 2797 const SpdySettingsIds id = it->first; | 2805 const SpdySettingsIds id = it->first; |
| 2798 const uint32 val = it->second.second; | 2806 const uint32 val = it->second.second; |
| 2799 switch (id) { | 2807 switch (id) { |
| 2800 case SETTINGS_CURRENT_CWND: | 2808 case SETTINGS_CURRENT_CWND: |
| 2801 // Record several different histograms to see if cwnd converges | 2809 // Record several different histograms to see if cwnd converges |
| 2802 // for larger volumes of data being sent. | 2810 // for larger volumes of data being sent. |
| 2803 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd", | 2811 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd", val, 1, 200, 100); |
| 2804 val, 1, 200, 100); | |
| 2805 if (total_bytes_received_ > 10 * 1024) { | 2812 if (total_bytes_received_ > 10 * 1024) { |
| 2806 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd10K", | 2813 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 2807 val, 1, 200, 100); | 2814 "Net.SpdySettingsCwnd10K", val, 1, 200, 100); |
| 2808 if (total_bytes_received_ > 25 * 1024) { | 2815 if (total_bytes_received_ > 25 * 1024) { |
| 2809 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd25K", | 2816 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 2810 val, 1, 200, 100); | 2817 "Net.SpdySettingsCwnd25K", val, 1, 200, 100); |
| 2811 if (total_bytes_received_ > 50 * 1024) { | 2818 if (total_bytes_received_ > 50 * 1024) { |
| 2812 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd50K", | 2819 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 2813 val, 1, 200, 100); | 2820 "Net.SpdySettingsCwnd50K", val, 1, 200, 100); |
| 2814 if (total_bytes_received_ > 100 * 1024) { | 2821 if (total_bytes_received_ > 100 * 1024) { |
| 2815 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd100K", | 2822 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 2816 val, 1, 200, 100); | 2823 "Net.SpdySettingsCwnd100K", val, 1, 200, 100); |
| 2817 } | 2824 } |
| 2818 } | 2825 } |
| 2819 } | 2826 } |
| 2820 } | 2827 } |
| 2821 break; | 2828 break; |
| 2822 case SETTINGS_ROUND_TRIP_TIME: | 2829 case SETTINGS_ROUND_TRIP_TIME: |
| 2823 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsRTT", | 2830 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsRTT", val, 1, 1200, 100); |
| 2824 val, 1, 1200, 100); | |
| 2825 break; | 2831 break; |
| 2826 case SETTINGS_DOWNLOAD_RETRANS_RATE: | 2832 case SETTINGS_DOWNLOAD_RETRANS_RATE: |
| 2827 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsRetransRate", | 2833 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 2828 val, 1, 100, 50); | 2834 "Net.SpdySettingsRetransRate", val, 1, 100, 50); |
| 2829 break; | 2835 break; |
| 2830 default: | 2836 default: |
| 2831 break; | 2837 break; |
| 2832 } | 2838 } |
| 2833 } | 2839 } |
| 2834 } | 2840 } |
| 2835 } | 2841 } |
| 2836 | 2842 |
| 2837 void SpdySession::CompleteStreamRequest( | 2843 void SpdySession::CompleteStreamRequest( |
| 2838 const base::WeakPtr<SpdyStreamRequest>& pending_request) { | 2844 const base::WeakPtr<SpdyStreamRequest>& pending_request) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2894 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); | 2900 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); |
| 2895 DCHECK_GE(delta_window_size, 1); | 2901 DCHECK_GE(delta_window_size, 1); |
| 2896 | 2902 |
| 2897 // Check for overflow. | 2903 // Check for overflow. |
| 2898 int32 max_delta_window_size = kint32max - session_send_window_size_; | 2904 int32 max_delta_window_size = kint32max - session_send_window_size_; |
| 2899 if (delta_window_size > max_delta_window_size) { | 2905 if (delta_window_size > max_delta_window_size) { |
| 2900 RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE); | 2906 RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE); |
| 2901 CloseSessionResult result = DoCloseSession( | 2907 CloseSessionResult result = DoCloseSession( |
| 2902 ERR_SPDY_PROTOCOL_ERROR, | 2908 ERR_SPDY_PROTOCOL_ERROR, |
| 2903 "Received WINDOW_UPDATE [delta: " + | 2909 "Received WINDOW_UPDATE [delta: " + |
| 2904 base::IntToString(delta_window_size) + | 2910 base::IntToString(delta_window_size) + |
| 2905 "] for session overflows session_send_window_size_ [current: " + | 2911 "] for session overflows session_send_window_size_ [current: " + |
| 2906 base::IntToString(session_send_window_size_) + "]"); | 2912 base::IntToString(session_send_window_size_) + "]"); |
| 2907 DCHECK_NE(result, SESSION_ALREADY_CLOSED); | 2913 DCHECK_NE(result, SESSION_ALREADY_CLOSED); |
| 2908 return; | 2914 return; |
| 2909 } | 2915 } |
| 2910 | 2916 |
| 2911 session_send_window_size_ += delta_window_size; | 2917 session_send_window_size_ += delta_window_size; |
| 2912 | 2918 |
| 2913 net_log_.AddEvent( | 2919 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW, |
| 2914 NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW, | 2920 base::Bind(&NetLogSpdySessionWindowUpdateCallback, |
| 2915 base::Bind(&NetLogSpdySessionWindowUpdateCallback, | 2921 delta_window_size, |
| 2916 delta_window_size, session_send_window_size_)); | 2922 session_send_window_size_)); |
| 2917 | 2923 |
| 2918 DCHECK(!IsSendStalled()); | 2924 DCHECK(!IsSendStalled()); |
| 2919 ResumeSendStalledStreams(); | 2925 ResumeSendStalledStreams(); |
| 2920 } | 2926 } |
| 2921 | 2927 |
| 2922 void SpdySession::DecreaseSendWindowSize(int32 delta_window_size) { | 2928 void SpdySession::DecreaseSendWindowSize(int32 delta_window_size) { |
| 2923 DCHECK_NE(availability_state_, STATE_CLOSED); | 2929 DCHECK_NE(availability_state_, STATE_CLOSED); |
| 2924 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); | 2930 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); |
| 2925 | 2931 |
| 2926 // We only call this method when sending a frame. Therefore, | 2932 // We only call this method when sending a frame. Therefore, |
| 2927 // |delta_window_size| should be within the valid frame size range. | 2933 // |delta_window_size| should be within the valid frame size range. |
| 2928 DCHECK_GE(delta_window_size, 1); | 2934 DCHECK_GE(delta_window_size, 1); |
| 2929 DCHECK_LE(delta_window_size, kMaxSpdyFrameChunkSize); | 2935 DCHECK_LE(delta_window_size, kMaxSpdyFrameChunkSize); |
| 2930 | 2936 |
| 2931 // |send_window_size_| should have been at least |delta_window_size| for | 2937 // |send_window_size_| should have been at least |delta_window_size| for |
| 2932 // this call to happen. | 2938 // this call to happen. |
| 2933 DCHECK_GE(session_send_window_size_, delta_window_size); | 2939 DCHECK_GE(session_send_window_size_, delta_window_size); |
| 2934 | 2940 |
| 2935 session_send_window_size_ -= delta_window_size; | 2941 session_send_window_size_ -= delta_window_size; |
| 2936 | 2942 |
| 2937 net_log_.AddEvent( | 2943 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW, |
| 2938 NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW, | 2944 base::Bind(&NetLogSpdySessionWindowUpdateCallback, |
| 2939 base::Bind(&NetLogSpdySessionWindowUpdateCallback, | 2945 -delta_window_size, |
| 2940 -delta_window_size, session_send_window_size_)); | 2946 session_send_window_size_)); |
| 2941 } | 2947 } |
| 2942 | 2948 |
| 2943 void SpdySession::OnReadBufferConsumed( | 2949 void SpdySession::OnReadBufferConsumed( |
| 2944 size_t consume_size, | 2950 size_t consume_size, |
| 2945 SpdyBuffer::ConsumeSource consume_source) { | 2951 SpdyBuffer::ConsumeSource consume_source) { |
| 2946 // We can be called with |in_io_loop_| set if a read SpdyBuffer is | 2952 // We can be called with |in_io_loop_| set if a read SpdyBuffer is |
| 2947 // deleted (e.g., discarded by a SpdyReadQueue). | 2953 // deleted (e.g., discarded by a SpdyReadQueue). |
| 2948 | 2954 |
| 2949 if (availability_state_ == STATE_CLOSED) | 2955 if (availability_state_ == STATE_CLOSED) |
| 2950 return; | 2956 return; |
| 2951 | 2957 |
| 2952 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); | 2958 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); |
| 2953 DCHECK_GE(consume_size, 1u); | 2959 DCHECK_GE(consume_size, 1u); |
| 2954 DCHECK_LE(consume_size, static_cast<size_t>(kint32max)); | 2960 DCHECK_LE(consume_size, static_cast<size_t>(kint32max)); |
| 2955 | 2961 |
| 2956 IncreaseRecvWindowSize(static_cast<int32>(consume_size)); | 2962 IncreaseRecvWindowSize(static_cast<int32>(consume_size)); |
| 2957 } | 2963 } |
| 2958 | 2964 |
| 2959 void SpdySession::IncreaseRecvWindowSize(int32 delta_window_size) { | 2965 void SpdySession::IncreaseRecvWindowSize(int32 delta_window_size) { |
| 2960 DCHECK_NE(availability_state_, STATE_CLOSED); | 2966 DCHECK_NE(availability_state_, STATE_CLOSED); |
| 2961 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); | 2967 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); |
| 2962 DCHECK_GE(session_unacked_recv_window_bytes_, 0); | 2968 DCHECK_GE(session_unacked_recv_window_bytes_, 0); |
| 2963 DCHECK_GE(session_recv_window_size_, session_unacked_recv_window_bytes_); | 2969 DCHECK_GE(session_recv_window_size_, session_unacked_recv_window_bytes_); |
| 2964 DCHECK_GE(delta_window_size, 1); | 2970 DCHECK_GE(delta_window_size, 1); |
| 2965 // Check for overflow. | 2971 // Check for overflow. |
| 2966 DCHECK_LE(delta_window_size, kint32max - session_recv_window_size_); | 2972 DCHECK_LE(delta_window_size, kint32max - session_recv_window_size_); |
| 2967 | 2973 |
| 2968 session_recv_window_size_ += delta_window_size; | 2974 session_recv_window_size_ += delta_window_size; |
| 2969 net_log_.AddEvent( | 2975 net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW, |
| 2970 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW, | 2976 base::Bind(&NetLogSpdySessionWindowUpdateCallback, |
| 2971 base::Bind(&NetLogSpdySessionWindowUpdateCallback, | 2977 delta_window_size, |
| 2972 delta_window_size, session_recv_window_size_)); | 2978 session_recv_window_size_)); |
| 2973 | 2979 |
| 2974 session_unacked_recv_window_bytes_ += delta_window_size; | 2980 session_unacked_recv_window_bytes_ += delta_window_size; |
| 2975 if (session_unacked_recv_window_bytes_ > kSpdySessionInitialWindowSize / 2) { | 2981 if (session_unacked_recv_window_bytes_ > kSpdySessionInitialWindowSize / 2) { |
| 2976 SendWindowUpdateFrame(kSessionFlowControlStreamId, | 2982 SendWindowUpdateFrame(kSessionFlowControlStreamId, |
| 2977 session_unacked_recv_window_bytes_, | 2983 session_unacked_recv_window_bytes_, |
| 2978 HIGHEST); | 2984 HIGHEST); |
| 2979 session_unacked_recv_window_bytes_ = 0; | 2985 session_unacked_recv_window_bytes_ = 0; |
| 2980 } | 2986 } |
| 2981 } | 2987 } |
| 2982 | 2988 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2993 CloseSessionResult result = DoCloseSession( | 2999 CloseSessionResult result = DoCloseSession( |
| 2994 ERR_SPDY_PROTOCOL_ERROR, | 3000 ERR_SPDY_PROTOCOL_ERROR, |
| 2995 "delta_window_size is " + base::IntToString(delta_window_size) + | 3001 "delta_window_size is " + base::IntToString(delta_window_size) + |
| 2996 " in DecreaseRecvWindowSize, which is larger than the receive " + | 3002 " in DecreaseRecvWindowSize, which is larger than the receive " + |
| 2997 "window size of " + base::IntToString(session_recv_window_size_)); | 3003 "window size of " + base::IntToString(session_recv_window_size_)); |
| 2998 DCHECK_EQ(result, SESSION_CLOSED_BUT_NOT_REMOVED); | 3004 DCHECK_EQ(result, SESSION_CLOSED_BUT_NOT_REMOVED); |
| 2999 return; | 3005 return; |
| 3000 } | 3006 } |
| 3001 | 3007 |
| 3002 session_recv_window_size_ -= delta_window_size; | 3008 session_recv_window_size_ -= delta_window_size; |
| 3003 net_log_.AddEvent( | 3009 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_UPDATE_RECV_WINDOW, |
| 3004 NetLog::TYPE_SPDY_SESSION_UPDATE_RECV_WINDOW, | 3010 base::Bind(&NetLogSpdySessionWindowUpdateCallback, |
| 3005 base::Bind(&NetLogSpdySessionWindowUpdateCallback, | 3011 -delta_window_size, |
| 3006 -delta_window_size, session_recv_window_size_)); | 3012 session_recv_window_size_)); |
| 3007 } | 3013 } |
| 3008 | 3014 |
| 3009 void SpdySession::QueueSendStalledStream(const SpdyStream& stream) { | 3015 void SpdySession::QueueSendStalledStream(const SpdyStream& stream) { |
| 3010 DCHECK(stream.send_stalled_by_flow_control()); | 3016 DCHECK(stream.send_stalled_by_flow_control()); |
| 3011 RequestPriority priority = stream.priority(); | 3017 RequestPriority priority = stream.priority(); |
| 3012 CHECK_GE(priority, MINIMUM_PRIORITY); | 3018 CHECK_GE(priority, MINIMUM_PRIORITY); |
| 3013 CHECK_LE(priority, MAXIMUM_PRIORITY); | 3019 CHECK_LE(priority, MAXIMUM_PRIORITY); |
| 3014 stream_send_unstall_queue_[priority].push_back(stream.stream_id()); | 3020 stream_send_unstall_queue_[priority].push_back(stream.stream_id()); |
| 3015 } | 3021 } |
| 3016 | 3022 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3050 if (!queue->empty()) { | 3056 if (!queue->empty()) { |
| 3051 SpdyStreamId stream_id = queue->front(); | 3057 SpdyStreamId stream_id = queue->front(); |
| 3052 queue->pop_front(); | 3058 queue->pop_front(); |
| 3053 return stream_id; | 3059 return stream_id; |
| 3054 } | 3060 } |
| 3055 } | 3061 } |
| 3056 return 0; | 3062 return 0; |
| 3057 } | 3063 } |
| 3058 | 3064 |
| 3059 } // namespace net | 3065 } // namespace net |
| OLD | NEW |