| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/linked_ptr.h" | 9 #include "base/memory/linked_ptr.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 } | 165 } |
| 166 | 166 |
| 167 private: | 167 private: |
| 168 ~NetLogSpdyRstParameter() {} | 168 ~NetLogSpdyRstParameter() {} |
| 169 const spdy::SpdyStreamId stream_id_; | 169 const spdy::SpdyStreamId stream_id_; |
| 170 const int status_; | 170 const int status_; |
| 171 | 171 |
| 172 DISALLOW_COPY_AND_ASSIGN(NetLogSpdyRstParameter); | 172 DISALLOW_COPY_AND_ASSIGN(NetLogSpdyRstParameter); |
| 173 }; | 173 }; |
| 174 | 174 |
| 175 class NetLogSpdyPingParameter : public NetLog::EventParameters { |
| 176 public: |
| 177 explicit NetLogSpdyPingParameter(uint32 unique_id) : unique_id_(unique_id) {} |
| 178 |
| 179 virtual Value* ToValue() const { |
| 180 DictionaryValue* dict = new DictionaryValue(); |
| 181 dict->SetInteger("unique_id", unique_id_); |
| 182 return dict; |
| 183 } |
| 184 |
| 185 private: |
| 186 ~NetLogSpdyPingParameter() {} |
| 187 const uint32 unique_id_; |
| 188 |
| 189 DISALLOW_COPY_AND_ASSIGN(NetLogSpdyPingParameter); |
| 190 }; |
| 191 |
| 175 class NetLogSpdyGoAwayParameter : public NetLog::EventParameters { | 192 class NetLogSpdyGoAwayParameter : public NetLog::EventParameters { |
| 176 public: | 193 public: |
| 177 NetLogSpdyGoAwayParameter(spdy::SpdyStreamId last_stream_id, | 194 NetLogSpdyGoAwayParameter(spdy::SpdyStreamId last_stream_id, |
| 178 int active_streams, | 195 int active_streams, |
| 179 int unclaimed_streams) | 196 int unclaimed_streams) |
| 180 : last_stream_id_(last_stream_id), | 197 : last_stream_id_(last_stream_id), |
| 181 active_streams_(active_streams), | 198 active_streams_(active_streams), |
| 182 unclaimed_streams_(unclaimed_streams) {} | 199 unclaimed_streams_(unclaimed_streams) {} |
| 183 | 200 |
| 184 virtual Value* ToValue() const { | 201 virtual Value* ToValue() const { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 206 | 223 |
| 207 // static | 224 // static |
| 208 bool SpdySession::use_flow_control_ = false; | 225 bool SpdySession::use_flow_control_ = false; |
| 209 | 226 |
| 210 // static | 227 // static |
| 211 size_t SpdySession::init_max_concurrent_streams_ = 10; | 228 size_t SpdySession::init_max_concurrent_streams_ = 10; |
| 212 | 229 |
| 213 // static | 230 // static |
| 214 size_t SpdySession::max_concurrent_stream_limit_ = 256; | 231 size_t SpdySession::max_concurrent_stream_limit_ = 256; |
| 215 | 232 |
| 233 // static |
| 234 bool SpdySession::enable_ping_based_connection_checking_ = true; |
| 235 |
| 236 // static |
| 237 int SpdySession::connection_at_risk_of_loss_ms_ = 0; |
| 238 |
| 239 // static |
| 240 int SpdySession::trailing_ping_delay_time_ms_ = 1000; |
| 241 |
| 242 // static |
| 243 int SpdySession::hung_interval_ms_ = 10000; |
| 244 |
| 216 SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair, | 245 SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair, |
| 217 SpdySessionPool* spdy_session_pool, | 246 SpdySessionPool* spdy_session_pool, |
| 218 SpdySettingsStorage* spdy_settings, | 247 SpdySettingsStorage* spdy_settings, |
| 219 bool verify_domain_authentication, | 248 bool verify_domain_authentication, |
| 220 NetLog* net_log) | 249 NetLog* net_log) |
| 221 : ALLOW_THIS_IN_INITIALIZER_LIST( | 250 : ALLOW_THIS_IN_INITIALIZER_LIST( |
| 222 read_callback_(this, &SpdySession::OnReadComplete)), | 251 read_callback_(this, &SpdySession::OnReadComplete)), |
| 223 ALLOW_THIS_IN_INITIALIZER_LIST( | 252 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 224 write_callback_(this, &SpdySession::OnWriteComplete)), | 253 write_callback_(this, &SpdySession::OnWriteComplete)), |
| 225 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), | 254 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), |
| (...skipping 13 matching lines...) Expand all Loading... |
| 239 max_concurrent_streams_(init_max_concurrent_streams_), | 268 max_concurrent_streams_(init_max_concurrent_streams_), |
| 240 streams_initiated_count_(0), | 269 streams_initiated_count_(0), |
| 241 streams_pushed_count_(0), | 270 streams_pushed_count_(0), |
| 242 streams_pushed_and_claimed_count_(0), | 271 streams_pushed_and_claimed_count_(0), |
| 243 streams_abandoned_count_(0), | 272 streams_abandoned_count_(0), |
| 244 frames_received_(0), | 273 frames_received_(0), |
| 245 bytes_received_(0), | 274 bytes_received_(0), |
| 246 sent_settings_(false), | 275 sent_settings_(false), |
| 247 received_settings_(false), | 276 received_settings_(false), |
| 248 stalled_streams_(0), | 277 stalled_streams_(0), |
| 278 pings_in_flight_(0), |
| 279 next_ping_id_(1), |
| 280 received_data_time_(base::TimeTicks::Now()), |
| 281 trailing_ping_pending_(false), |
| 282 check_ping_status_pending_(false), |
| 283 last_sent_was_ping_(false), |
| 249 initial_send_window_size_(spdy::kSpdyStreamInitialWindowSize), | 284 initial_send_window_size_(spdy::kSpdyStreamInitialWindowSize), |
| 250 initial_recv_window_size_(spdy::kSpdyStreamInitialWindowSize), | 285 initial_recv_window_size_(spdy::kSpdyStreamInitialWindowSize), |
| 251 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)), | 286 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)), |
| 252 verify_domain_authentication_(verify_domain_authentication) { | 287 verify_domain_authentication_(verify_domain_authentication) { |
| 253 DCHECK(HttpStreamFactory::spdy_enabled()); | 288 DCHECK(HttpStreamFactory::spdy_enabled()); |
| 254 net_log_.BeginEvent( | 289 net_log_.BeginEvent( |
| 255 NetLog::TYPE_SPDY_SESSION, | 290 NetLog::TYPE_SPDY_SESSION, |
| 256 make_scoped_refptr( | 291 make_scoped_refptr( |
| 257 new NetLogSpdySessionParameter(host_port_proxy_pair_))); | 292 new NetLogSpdySessionParameter(host_port_proxy_pair_))); |
| 258 | 293 |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 spdy::SpdyStreamId stream_id, | 502 spdy::SpdyStreamId stream_id, |
| 468 RequestPriority priority, | 503 RequestPriority priority, |
| 469 spdy::SpdyControlFlags flags, | 504 spdy::SpdyControlFlags flags, |
| 470 const linked_ptr<spdy::SpdyHeaderBlock>& headers) { | 505 const linked_ptr<spdy::SpdyHeaderBlock>& headers) { |
| 471 // Find our stream | 506 // Find our stream |
| 472 if (!IsStreamActive(stream_id)) | 507 if (!IsStreamActive(stream_id)) |
| 473 return ERR_INVALID_SPDY_STREAM; | 508 return ERR_INVALID_SPDY_STREAM; |
| 474 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; | 509 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; |
| 475 CHECK_EQ(stream->stream_id(), stream_id); | 510 CHECK_EQ(stream->stream_id(), stream_id); |
| 476 | 511 |
| 512 SendPrefacePingIfNoneInFlight(); |
| 513 |
| 477 scoped_ptr<spdy::SpdySynStreamControlFrame> syn_frame( | 514 scoped_ptr<spdy::SpdySynStreamControlFrame> syn_frame( |
| 478 spdy_framer_.CreateSynStream( | 515 spdy_framer_.CreateSynStream( |
| 479 stream_id, 0, | 516 stream_id, 0, |
| 480 ConvertRequestPriorityToSpdyPriority(priority), | 517 ConvertRequestPriorityToSpdyPriority(priority), |
| 481 flags, false, headers.get())); | 518 flags, false, headers.get())); |
| 482 QueueFrame(syn_frame.get(), priority, stream); | 519 QueueFrame(syn_frame.get(), priority, stream); |
| 483 | 520 |
| 484 base::StatsCounter spdy_requests("spdy.requests"); | 521 base::StatsCounter spdy_requests("spdy.requests"); |
| 485 spdy_requests.Increment(); | 522 spdy_requests.Increment(); |
| 486 streams_initiated_count_++; | 523 streams_initiated_count_++; |
| 487 | 524 |
| 488 if (net_log().IsLoggingAllEvents()) { | 525 if (net_log().IsLoggingAllEvents()) { |
| 489 net_log().AddEvent( | 526 net_log().AddEvent( |
| 490 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, | 527 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, |
| 491 make_scoped_refptr( | 528 make_scoped_refptr( |
| 492 new NetLogSpdySynParameter(headers, flags, stream_id, 0))); | 529 new NetLogSpdySynParameter(headers, flags, stream_id, 0))); |
| 493 } | 530 } |
| 531 last_sent_was_ping_ = false; |
| 494 | 532 |
| 495 return ERR_IO_PENDING; | 533 return ERR_IO_PENDING; |
| 496 } | 534 } |
| 497 | 535 |
| 498 int SpdySession::WriteStreamData(spdy::SpdyStreamId stream_id, | 536 int SpdySession::WriteStreamData(spdy::SpdyStreamId stream_id, |
| 499 net::IOBuffer* data, int len, | 537 net::IOBuffer* data, int len, |
| 500 spdy::SpdyDataFlags flags) { | 538 spdy::SpdyDataFlags flags) { |
| 501 // Find our stream | 539 // Find our stream |
| 502 DCHECK(IsStreamActive(stream_id)); | 540 DCHECK(IsStreamActive(stream_id)); |
| 503 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 541 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
| 504 CHECK_EQ(stream->stream_id(), stream_id); | 542 CHECK_EQ(stream->stream_id(), stream_id); |
| 505 if (!stream) | 543 if (!stream) |
| 506 return ERR_INVALID_SPDY_STREAM; | 544 return ERR_INVALID_SPDY_STREAM; |
| 507 | 545 |
| 546 SendPrefacePingIfNoneInFlight(); |
| 547 |
| 508 if (len > kMaxSpdyFrameChunkSize) { | 548 if (len > kMaxSpdyFrameChunkSize) { |
| 509 len = kMaxSpdyFrameChunkSize; | 549 len = kMaxSpdyFrameChunkSize; |
| 510 flags = static_cast<spdy::SpdyDataFlags>(flags & ~spdy::DATA_FLAG_FIN); | 550 flags = static_cast<spdy::SpdyDataFlags>(flags & ~spdy::DATA_FLAG_FIN); |
| 511 } | 551 } |
| 512 | 552 |
| 513 // Obey send window size of the stream if flow control is enabled. | 553 // Obey send window size of the stream if flow control is enabled. |
| 514 if (use_flow_control_) { | 554 if (use_flow_control_) { |
| 515 if (stream->send_window_size() <= 0) { | 555 if (stream->send_window_size() <= 0) { |
| 516 // Because we queue frames onto the session, it is possible that | 556 // Because we queue frames onto the session, it is possible that |
| 517 // a stream was not flow controlled at the time it attempted the | 557 // a stream was not flow controlled at the time it attempted the |
| (...skipping 19 matching lines...) Expand all Loading... |
| 537 if (net_log().IsLoggingAllEvents()) { | 577 if (net_log().IsLoggingAllEvents()) { |
| 538 net_log().AddEvent( | 578 net_log().AddEvent( |
| 539 NetLog::TYPE_SPDY_SESSION_SEND_DATA, | 579 NetLog::TYPE_SPDY_SESSION_SEND_DATA, |
| 540 make_scoped_refptr(new NetLogSpdyDataParameter(stream_id, len, flags))); | 580 make_scoped_refptr(new NetLogSpdyDataParameter(stream_id, len, flags))); |
| 541 } | 581 } |
| 542 | 582 |
| 543 // TODO(mbelshe): reduce memory copies here. | 583 // TODO(mbelshe): reduce memory copies here. |
| 544 scoped_ptr<spdy::SpdyDataFrame> frame( | 584 scoped_ptr<spdy::SpdyDataFrame> frame( |
| 545 spdy_framer_.CreateDataFrame(stream_id, data->data(), len, flags)); | 585 spdy_framer_.CreateDataFrame(stream_id, data->data(), len, flags)); |
| 546 QueueFrame(frame.get(), stream->priority(), stream); | 586 QueueFrame(frame.get(), stream->priority(), stream); |
| 587 last_sent_was_ping_ = false; |
| 547 return ERR_IO_PENDING; | 588 return ERR_IO_PENDING; |
| 548 } | 589 } |
| 549 | 590 |
| 550 void SpdySession::CloseStream(spdy::SpdyStreamId stream_id, int status) { | 591 void SpdySession::CloseStream(spdy::SpdyStreamId stream_id, int status) { |
| 551 // TODO(mbelshe): We should send a RST_STREAM control frame here | 592 // TODO(mbelshe): We should send a RST_STREAM control frame here |
| 552 // so that the server can cancel a large send. | 593 // so that the server can cancel a large send. |
| 553 | 594 |
| 554 DeleteStream(stream_id, status); | 595 DeleteStream(stream_id, status); |
| 555 } | 596 } |
| 556 | 597 |
| 557 void SpdySession::ResetStream( | 598 void SpdySession::ResetStream( |
| 558 spdy::SpdyStreamId stream_id, spdy::SpdyStatusCodes status) { | 599 spdy::SpdyStreamId stream_id, spdy::SpdyStatusCodes status) { |
| 559 | 600 |
| 560 net_log().AddEvent( | 601 net_log().AddEvent( |
| 561 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM, | 602 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM, |
| 562 make_scoped_refptr(new NetLogSpdyRstParameter(stream_id, status))); | 603 make_scoped_refptr(new NetLogSpdyRstParameter(stream_id, status))); |
| 563 | 604 |
| 564 scoped_ptr<spdy::SpdyRstStreamControlFrame> rst_frame( | 605 scoped_ptr<spdy::SpdyRstStreamControlFrame> rst_frame( |
| 565 spdy_framer_.CreateRstStream(stream_id, status)); | 606 spdy_framer_.CreateRstStream(stream_id, status)); |
| 566 | 607 |
| 567 // Default to lowest priority unless we know otherwise. | 608 // Default to lowest priority unless we know otherwise. |
| 568 int priority = 3; | 609 int priority = 3; |
| 569 if(IsStreamActive(stream_id)) { | 610 if(IsStreamActive(stream_id)) { |
| 570 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 611 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
| 571 priority = stream->priority(); | 612 priority = stream->priority(); |
| 572 } | 613 } |
| 573 QueueFrame(rst_frame.get(), priority, NULL); | 614 QueueFrame(rst_frame.get(), priority, NULL); |
| 574 | 615 last_sent_was_ping_ = false; |
| 575 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); | 616 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); |
| 576 } | 617 } |
| 577 | 618 |
| 578 bool SpdySession::IsStreamActive(spdy::SpdyStreamId stream_id) const { | 619 bool SpdySession::IsStreamActive(spdy::SpdyStreamId stream_id) const { |
| 579 return ContainsKey(active_streams_, stream_id); | 620 return ContainsKey(active_streams_, stream_id); |
| 580 } | 621 } |
| 581 | 622 |
| 582 LoadState SpdySession::GetLoadState() const { | 623 LoadState SpdySession::GetLoadState() const { |
| 583 // NOTE: The application only queries the LoadState via the | 624 // NOTE: The application only queries the LoadState via the |
| 584 // SpdyNetworkTransaction, and details are only needed when | 625 // SpdyNetworkTransaction, and details are only needed when |
| (...skipping 20 matching lines...) Expand all Loading... |
| 605 // Session is tearing down. | 646 // Session is tearing down. |
| 606 net::Error error = static_cast<net::Error>(bytes_read); | 647 net::Error error = static_cast<net::Error>(bytes_read); |
| 607 if (bytes_read == 0) | 648 if (bytes_read == 0) |
| 608 error = ERR_CONNECTION_CLOSED; | 649 error = ERR_CONNECTION_CLOSED; |
| 609 CloseSessionOnError(error, true); | 650 CloseSessionOnError(error, true); |
| 610 return; | 651 return; |
| 611 } | 652 } |
| 612 | 653 |
| 613 bytes_received_ += bytes_read; | 654 bytes_received_ += bytes_read; |
| 614 | 655 |
| 656 received_data_time_ = base::TimeTicks::Now(); |
| 657 |
| 615 // The SpdyFramer will use callbacks onto |this| as it parses frames. | 658 // The SpdyFramer will use callbacks onto |this| as it parses frames. |
| 616 // When errors occur, those callbacks can lead to teardown of all references | 659 // When errors occur, those callbacks can lead to teardown of all references |
| 617 // to |this|, so maintain a reference to self during this call for safe | 660 // to |this|, so maintain a reference to self during this call for safe |
| 618 // cleanup. | 661 // cleanup. |
| 619 scoped_refptr<SpdySession> self(this); | 662 scoped_refptr<SpdySession> self(this); |
| 620 | 663 |
| 621 char *data = read_buffer_->data(); | 664 char *data = read_buffer_->data(); |
| 622 while (bytes_read && | 665 while (bytes_read && |
| 623 spdy_framer_.error_code() == spdy::SpdyFramer::SPDY_NO_ERROR) { | 666 spdy_framer_.error_code() == spdy::SpdyFramer::SPDY_NO_ERROR) { |
| 624 uint32 bytes_processed = spdy_framer_.ProcessInput(data, bytes_read); | 667 uint32 bytes_processed = spdy_framer_.ProcessInput(data, bytes_read); |
| (...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1222 return; | 1265 return; |
| 1223 } | 1266 } |
| 1224 } | 1267 } |
| 1225 | 1268 |
| 1226 frames_received_++; | 1269 frames_received_++; |
| 1227 | 1270 |
| 1228 switch (type) { | 1271 switch (type) { |
| 1229 case spdy::GOAWAY: | 1272 case spdy::GOAWAY: |
| 1230 OnGoAway(*reinterpret_cast<const spdy::SpdyGoAwayControlFrame*>(frame)); | 1273 OnGoAway(*reinterpret_cast<const spdy::SpdyGoAwayControlFrame*>(frame)); |
| 1231 break; | 1274 break; |
| 1275 case spdy::PING: |
| 1276 OnPing(*reinterpret_cast<const spdy::SpdyPingControlFrame*>(frame)); |
| 1277 break; |
| 1232 case spdy::SETTINGS: | 1278 case spdy::SETTINGS: |
| 1233 OnSettings( | 1279 OnSettings( |
| 1234 *reinterpret_cast<const spdy::SpdySettingsControlFrame*>(frame)); | 1280 *reinterpret_cast<const spdy::SpdySettingsControlFrame*>(frame)); |
| 1235 break; | 1281 break; |
| 1236 case spdy::RST_STREAM: | 1282 case spdy::RST_STREAM: |
| 1237 OnRst(*reinterpret_cast<const spdy::SpdyRstStreamControlFrame*>(frame)); | 1283 OnRst(*reinterpret_cast<const spdy::SpdyRstStreamControlFrame*>(frame)); |
| 1238 break; | 1284 break; |
| 1239 case spdy::SYN_STREAM: | 1285 case spdy::SYN_STREAM: |
| 1240 OnSyn(*reinterpret_cast<const spdy::SpdySynStreamControlFrame*>(frame), | 1286 OnSyn(*reinterpret_cast<const spdy::SpdySynStreamControlFrame*>(frame), |
| 1241 headers); | 1287 headers); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1310 CloseAllStreams(net::ERR_ABORTED); | 1356 CloseAllStreams(net::ERR_ABORTED); |
| 1311 | 1357 |
| 1312 // TODO(willchan): Cancel any streams that are past the GoAway frame's | 1358 // TODO(willchan): Cancel any streams that are past the GoAway frame's |
| 1313 // |last_accepted_stream_id|. | 1359 // |last_accepted_stream_id|. |
| 1314 | 1360 |
| 1315 // Don't bother killing any streams that are still reading. They'll either | 1361 // Don't bother killing any streams that are still reading. They'll either |
| 1316 // complete successfully or get an ERR_CONNECTION_CLOSED when the socket is | 1362 // complete successfully or get an ERR_CONNECTION_CLOSED when the socket is |
| 1317 // closed. | 1363 // closed. |
| 1318 } | 1364 } |
| 1319 | 1365 |
| 1366 void SpdySession::OnPing(const spdy::SpdyPingControlFrame& frame) { |
| 1367 net_log_.AddEvent( |
| 1368 NetLog::TYPE_SPDY_SESSION_PING, |
| 1369 make_scoped_refptr(new NetLogSpdyPingParameter(frame.unique_id()))); |
| 1370 |
| 1371 // Send response to a PING from server. |
| 1372 if (frame.unique_id() % 2 == 0) { |
| 1373 WritePingFrame(frame.unique_id()); |
| 1374 return; |
| 1375 } |
| 1376 |
| 1377 --pings_in_flight_; |
| 1378 if (pings_in_flight_ < 0) { |
| 1379 CloseSessionOnError(net::ERR_SPDY_PROTOCOL_ERROR, true); |
| 1380 return; |
| 1381 } |
| 1382 |
| 1383 if (pings_in_flight_ > 0) |
| 1384 return; |
| 1385 |
| 1386 if (last_sent_was_ping_) |
| 1387 return; |
| 1388 |
| 1389 PlanToSendTrailingPing(); |
| 1390 } |
| 1391 |
| 1320 void SpdySession::OnSettings(const spdy::SpdySettingsControlFrame& frame) { | 1392 void SpdySession::OnSettings(const spdy::SpdySettingsControlFrame& frame) { |
| 1321 spdy::SpdySettings settings; | 1393 spdy::SpdySettings settings; |
| 1322 if (spdy_framer_.ParseSettings(&frame, &settings)) { | 1394 if (spdy_framer_.ParseSettings(&frame, &settings)) { |
| 1323 HandleSettings(settings); | 1395 HandleSettings(settings); |
| 1324 spdy_settings_->Set(host_port_pair(), settings); | 1396 spdy_settings_->Set(host_port_pair(), settings); |
| 1325 } | 1397 } |
| 1326 | 1398 |
| 1327 received_settings_ = true; | 1399 received_settings_ = true; |
| 1328 | 1400 |
| 1329 net_log_.AddEvent( | 1401 net_log_.AddEvent( |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1367 CHECK_EQ(stream->stream_id(), stream_id); | 1439 CHECK_EQ(stream->stream_id(), stream_id); |
| 1368 | 1440 |
| 1369 net_log_.AddEvent( | 1441 net_log_.AddEvent( |
| 1370 NetLog::TYPE_SPDY_SESSION_RECV_WINDOW_UPDATE, | 1442 NetLog::TYPE_SPDY_SESSION_RECV_WINDOW_UPDATE, |
| 1371 make_scoped_refptr(new NetLogSpdyWindowUpdateParameter( | 1443 make_scoped_refptr(new NetLogSpdyWindowUpdateParameter( |
| 1372 stream_id, delta_window_size, stream->recv_window_size()))); | 1444 stream_id, delta_window_size, stream->recv_window_size()))); |
| 1373 | 1445 |
| 1374 scoped_ptr<spdy::SpdyWindowUpdateControlFrame> window_update_frame( | 1446 scoped_ptr<spdy::SpdyWindowUpdateControlFrame> window_update_frame( |
| 1375 spdy_framer_.CreateWindowUpdate(stream_id, delta_window_size)); | 1447 spdy_framer_.CreateWindowUpdate(stream_id, delta_window_size)); |
| 1376 QueueFrame(window_update_frame.get(), stream->priority(), stream); | 1448 QueueFrame(window_update_frame.get(), stream->priority(), stream); |
| 1449 last_sent_was_ping_ = false; |
| 1377 } | 1450 } |
| 1378 | 1451 |
| 1379 // Given a cwnd that we would have sent to the server, modify it based on the | 1452 // Given a cwnd that we would have sent to the server, modify it based on the |
| 1380 // field trial policy. | 1453 // field trial policy. |
| 1381 uint32 ApplyCwndFieldTrialPolicy(int cwnd) { | 1454 uint32 ApplyCwndFieldTrialPolicy(int cwnd) { |
| 1382 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd"); | 1455 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd"); |
| 1383 if (!trial) { | 1456 if (!trial) { |
| 1384 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList"; | 1457 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList"; |
| 1385 return cwnd; | 1458 return cwnd; |
| 1386 } | 1459 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1431 | 1504 |
| 1432 net_log_.AddEvent( | 1505 net_log_.AddEvent( |
| 1433 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, | 1506 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, |
| 1434 make_scoped_refptr(new NetLogSpdySettingsParameter(settings))); | 1507 make_scoped_refptr(new NetLogSpdySettingsParameter(settings))); |
| 1435 | 1508 |
| 1436 // Create the SETTINGS frame and send it. | 1509 // Create the SETTINGS frame and send it. |
| 1437 scoped_ptr<spdy::SpdySettingsControlFrame> settings_frame( | 1510 scoped_ptr<spdy::SpdySettingsControlFrame> settings_frame( |
| 1438 spdy_framer_.CreateSettings(settings)); | 1511 spdy_framer_.CreateSettings(settings)); |
| 1439 sent_settings_ = true; | 1512 sent_settings_ = true; |
| 1440 QueueFrame(settings_frame.get(), 0, NULL); | 1513 QueueFrame(settings_frame.get(), 0, NULL); |
| 1514 last_sent_was_ping_ = false; |
| 1441 } | 1515 } |
| 1442 | 1516 |
| 1443 void SpdySession::HandleSettings(const spdy::SpdySettings& settings) { | 1517 void SpdySession::HandleSettings(const spdy::SpdySettings& settings) { |
| 1444 for (spdy::SpdySettings::const_iterator i = settings.begin(), | 1518 for (spdy::SpdySettings::const_iterator i = settings.begin(), |
| 1445 end = settings.end(); i != end; ++i) { | 1519 end = settings.end(); i != end; ++i) { |
| 1446 const uint32 id = i->first.id(); | 1520 const uint32 id = i->first.id(); |
| 1447 const uint32 val = i->second; | 1521 const uint32 val = i->second; |
| 1448 switch (id) { | 1522 switch (id) { |
| 1449 case spdy::SETTINGS_MAX_CONCURRENT_STREAMS: | 1523 case spdy::SETTINGS_MAX_CONCURRENT_STREAMS: |
| 1450 max_concurrent_streams_ = std::min(static_cast<size_t>(val), | 1524 max_concurrent_streams_ = std::min(static_cast<size_t>(val), |
| 1451 max_concurrent_stream_limit_); | 1525 max_concurrent_stream_limit_); |
| 1452 ProcessPendingCreateStreams(); | 1526 ProcessPendingCreateStreams(); |
| 1453 break; | 1527 break; |
| 1454 } | 1528 } |
| 1455 } | 1529 } |
| 1456 } | 1530 } |
| 1457 | 1531 |
| 1532 void SpdySession::SendPrefacePingIfNoneInFlight() { |
| 1533 if (pings_in_flight_ || trailing_ping_pending_ || |
| 1534 !enable_ping_based_connection_checking_) |
| 1535 return; |
| 1536 |
| 1537 const base::TimeDelta kConnectionAtRiskOfLoss = |
| 1538 base::TimeDelta::FromMilliseconds(connection_at_risk_of_loss_ms_); |
| 1539 |
| 1540 base::TimeTicks now = base::TimeTicks::Now(); |
| 1541 // If we haven't heard from server, then send a preface-PING. |
| 1542 if ((now - received_data_time_) > kConnectionAtRiskOfLoss) |
| 1543 SendPrefacePing(); |
| 1544 |
| 1545 PlanToSendTrailingPing(); |
| 1546 } |
| 1547 |
| 1548 void SpdySession::SendPrefacePing() { |
| 1549 WritePingFrame(next_ping_id_); |
| 1550 } |
| 1551 |
| 1552 void SpdySession::PlanToSendTrailingPing() { |
| 1553 if (trailing_ping_pending_) |
| 1554 return; |
| 1555 |
| 1556 trailing_ping_pending_ = true; |
| 1557 MessageLoop::current()->PostDelayedTask( |
| 1558 FROM_HERE, |
| 1559 method_factory_.NewRunnableMethod(&SpdySession::SendTrailingPing), |
| 1560 trailing_ping_delay_time_ms_); |
| 1561 } |
| 1562 |
| 1563 void SpdySession::SendTrailingPing() { |
| 1564 DCHECK(trailing_ping_pending_); |
| 1565 trailing_ping_pending_ = false; |
| 1566 WritePingFrame(next_ping_id_); |
| 1567 } |
| 1568 |
| 1569 void SpdySession::WritePingFrame(uint32 unique_id) { |
| 1570 scoped_ptr<spdy::SpdyPingControlFrame> ping_frame( |
| 1571 spdy_framer_.CreatePingFrame(next_ping_id_)); |
| 1572 QueueFrame(ping_frame.get(), SPDY_PRIORITY_HIGHEST, NULL); |
| 1573 |
| 1574 if (net_log().IsLoggingAllEvents()) { |
| 1575 net_log().AddEvent( |
| 1576 NetLog::TYPE_SPDY_SESSION_PING, |
| 1577 make_scoped_refptr(new NetLogSpdyPingParameter(next_ping_id_))); |
| 1578 } |
| 1579 if (unique_id % 2 != 0) { |
| 1580 next_ping_id_ += 2; |
| 1581 ++pings_in_flight_; |
| 1582 last_sent_was_ping_ = true; |
| 1583 PlanToCheckPingStatus(); |
| 1584 } |
| 1585 } |
| 1586 |
| 1587 void SpdySession::PlanToCheckPingStatus() { |
| 1588 if (check_ping_status_pending_) |
| 1589 return; |
| 1590 |
| 1591 check_ping_status_pending_ = true; |
| 1592 MessageLoop::current()->PostDelayedTask( |
| 1593 FROM_HERE, |
| 1594 method_factory_.NewRunnableMethod( |
| 1595 &SpdySession::CheckPingStatus, base::TimeTicks::Now()), |
| 1596 hung_interval_ms_); |
| 1597 } |
| 1598 |
| 1599 void SpdySession::CheckPingStatus(base::TimeTicks last_check_time) { |
| 1600 // Check if we got a response back for all PINGs we had sent. |
| 1601 if (pings_in_flight_ == 0) { |
| 1602 check_ping_status_pending_ = false; |
| 1603 return; |
| 1604 } |
| 1605 |
| 1606 DCHECK(check_ping_status_pending_); |
| 1607 |
| 1608 const base::TimeDelta kHungInterval = |
| 1609 base::TimeDelta::FromMilliseconds(hung_interval_ms_); |
| 1610 |
| 1611 base::TimeTicks now = base::TimeTicks::Now(); |
| 1612 base::TimeDelta delay = kHungInterval - (now - received_data_time_); |
| 1613 |
| 1614 if (delay.InMilliseconds() < 0 || received_data_time_ < last_check_time) { |
| 1615 DCHECK(now - received_data_time_ > kHungInterval); |
| 1616 CloseSessionOnError(net::ERR_SPDY_PING_FAILED, true); |
| 1617 return; |
| 1618 } |
| 1619 |
| 1620 // Check the status of connection after a delay. |
| 1621 MessageLoop::current()->PostDelayedTask( |
| 1622 FROM_HERE, |
| 1623 method_factory_.NewRunnableMethod(&SpdySession::CheckPingStatus, now), |
| 1624 delay.InMilliseconds()); |
| 1625 } |
| 1626 |
| 1458 void SpdySession::RecordHistograms() { | 1627 void SpdySession::RecordHistograms() { |
| 1459 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession", | 1628 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession", |
| 1460 streams_initiated_count_, | 1629 streams_initiated_count_, |
| 1461 0, 300, 50); | 1630 0, 300, 50); |
| 1462 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedPerSession", | 1631 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedPerSession", |
| 1463 streams_pushed_count_, | 1632 streams_pushed_count_, |
| 1464 0, 300, 50); | 1633 0, 300, 50); |
| 1465 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedAndClaimedPerSession", | 1634 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedAndClaimedPerSession", |
| 1466 streams_pushed_and_claimed_count_, | 1635 streams_pushed_and_claimed_count_, |
| 1467 0, 300, 50); | 1636 0, 300, 50); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1536 if (it == pending_callback_map_.end()) | 1705 if (it == pending_callback_map_.end()) |
| 1537 return; | 1706 return; |
| 1538 | 1707 |
| 1539 OldCompletionCallback* callback = it->second.callback; | 1708 OldCompletionCallback* callback = it->second.callback; |
| 1540 int result = it->second.result; | 1709 int result = it->second.result; |
| 1541 pending_callback_map_.erase(it); | 1710 pending_callback_map_.erase(it); |
| 1542 callback->Run(result); | 1711 callback->Run(result); |
| 1543 } | 1712 } |
| 1544 | 1713 |
| 1545 } // namespace net | 1714 } // namespace net |
| OLD | NEW |