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 |