| 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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 // static | 227 // static |
| 228 size_t SpdySession::init_max_concurrent_streams_ = 10; | 228 size_t SpdySession::init_max_concurrent_streams_ = 10; |
| 229 | 229 |
| 230 // static | 230 // static |
| 231 size_t SpdySession::max_concurrent_stream_limit_ = 256; | 231 size_t SpdySession::max_concurrent_stream_limit_ = 256; |
| 232 | 232 |
| 233 // static | 233 // static |
| 234 bool SpdySession::enable_ping_based_connection_checking_ = true; | 234 bool SpdySession::enable_ping_based_connection_checking_ = true; |
| 235 | 235 |
| 236 // static | 236 // static |
| 237 int SpdySession::connection_at_risk_of_loss_ms_ = 0; | 237 int SpdySession::connection_at_risk_of_loss_seconds_ = 10; |
| 238 | 238 |
| 239 // static | 239 // static |
| 240 int SpdySession::trailing_ping_delay_time_ms_ = 1000; | 240 int SpdySession::trailing_ping_delay_time_ms_ = 1000; |
| 241 | 241 |
| 242 // static | 242 // static |
| 243 int SpdySession::hung_interval_ms_ = 10000; | 243 int SpdySession::hung_interval_ms_ = 10000; |
| 244 | 244 |
| 245 SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair, | 245 SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair, |
| 246 SpdySessionPool* spdy_session_pool, | 246 SpdySessionPool* spdy_session_pool, |
| 247 SpdySettingsStorage* spdy_settings, | 247 SpdySettingsStorage* spdy_settings, |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 streams_initiated_count_++; | 523 streams_initiated_count_++; |
| 524 | 524 |
| 525 if (net_log().IsLoggingAllEvents()) { | 525 if (net_log().IsLoggingAllEvents()) { |
| 526 net_log().AddEvent( | 526 net_log().AddEvent( |
| 527 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, | 527 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, |
| 528 make_scoped_refptr( | 528 make_scoped_refptr( |
| 529 new NetLogSpdySynParameter(headers, flags, stream_id, 0))); | 529 new NetLogSpdySynParameter(headers, flags, stream_id, 0))); |
| 530 } | 530 } |
| 531 | 531 |
| 532 // Some servers don't like too many pings, so we limit our current sending to | 532 // Some servers don't like too many pings, so we limit our current sending to |
| 533 // no more than one ping for any syn sent. To do this, we avoid ever setting | 533 // no more than two pings for any syn frame or data frame sent. To do this, |
| 534 // this to true unless we send a syn (which we have just done). This approach | 534 // we avoid ever setting this to true unless we send a syn (which we have just |
| 535 // may change over time as servers change their responses to pings. | 535 // done) or data frame. This approach may change over time as servers change |
| 536 // their responses to pings. |
| 536 need_to_send_ping_ = true; | 537 need_to_send_ping_ = true; |
| 537 | 538 |
| 538 return ERR_IO_PENDING; | 539 return ERR_IO_PENDING; |
| 539 } | 540 } |
| 540 | 541 |
| 541 int SpdySession::WriteStreamData(spdy::SpdyStreamId stream_id, | 542 int SpdySession::WriteStreamData(spdy::SpdyStreamId stream_id, |
| 542 net::IOBuffer* data, int len, | 543 net::IOBuffer* data, int len, |
| 543 spdy::SpdyDataFlags flags) { | 544 spdy::SpdyDataFlags flags) { |
| 544 // Find our stream | 545 // Find our stream |
| 545 DCHECK(IsStreamActive(stream_id)); | 546 DCHECK(IsStreamActive(stream_id)); |
| 546 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 547 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
| 547 CHECK_EQ(stream->stream_id(), stream_id); | 548 CHECK_EQ(stream->stream_id(), stream_id); |
| 548 if (!stream) | 549 if (!stream) |
| 549 return ERR_INVALID_SPDY_STREAM; | 550 return ERR_INVALID_SPDY_STREAM; |
| 550 | 551 |
| 551 SendPrefacePingIfNoneInFlight(); | |
| 552 | |
| 553 if (len > kMaxSpdyFrameChunkSize) { | 552 if (len > kMaxSpdyFrameChunkSize) { |
| 554 len = kMaxSpdyFrameChunkSize; | 553 len = kMaxSpdyFrameChunkSize; |
| 555 flags = static_cast<spdy::SpdyDataFlags>(flags & ~spdy::DATA_FLAG_FIN); | 554 flags = static_cast<spdy::SpdyDataFlags>(flags & ~spdy::DATA_FLAG_FIN); |
| 556 } | 555 } |
| 557 | 556 |
| 558 // Obey send window size of the stream if flow control is enabled. | 557 // Obey send window size of the stream if flow control is enabled. |
| 559 if (use_flow_control_) { | 558 if (use_flow_control_) { |
| 560 if (stream->send_window_size() <= 0) { | 559 if (stream->send_window_size() <= 0) { |
| 561 // Because we queue frames onto the session, it is possible that | 560 // Because we queue frames onto the session, it is possible that |
| 562 // a stream was not flow controlled at the time it attempted the | 561 // a stream was not flow controlled at the time it attempted the |
| (...skipping 15 matching lines...) Expand all Loading... |
| 578 } | 577 } |
| 579 stream->DecreaseSendWindowSize(len); | 578 stream->DecreaseSendWindowSize(len); |
| 580 } | 579 } |
| 581 | 580 |
| 582 if (net_log().IsLoggingAllEvents()) { | 581 if (net_log().IsLoggingAllEvents()) { |
| 583 net_log().AddEvent( | 582 net_log().AddEvent( |
| 584 NetLog::TYPE_SPDY_SESSION_SEND_DATA, | 583 NetLog::TYPE_SPDY_SESSION_SEND_DATA, |
| 585 make_scoped_refptr(new NetLogSpdyDataParameter(stream_id, len, flags))); | 584 make_scoped_refptr(new NetLogSpdyDataParameter(stream_id, len, flags))); |
| 586 } | 585 } |
| 587 | 586 |
| 587 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. |
| 588 if (len > 0) |
| 589 SendPrefacePingIfNoneInFlight(); |
| 590 |
| 588 // TODO(mbelshe): reduce memory copies here. | 591 // TODO(mbelshe): reduce memory copies here. |
| 589 scoped_ptr<spdy::SpdyDataFrame> frame( | 592 scoped_ptr<spdy::SpdyDataFrame> frame( |
| 590 spdy_framer_.CreateDataFrame(stream_id, data->data(), len, flags)); | 593 spdy_framer_.CreateDataFrame(stream_id, data->data(), len, flags)); |
| 591 QueueFrame(frame.get(), stream->priority(), stream); | 594 QueueFrame(frame.get(), stream->priority(), stream); |
| 595 |
| 596 // Some servers don't like too many pings, so we limit our current sending to |
| 597 // no more than two pings for any syn frame or data frame sent. To do this, |
| 598 // we avoid ever setting this to true unless we send a syn (which we have just |
| 599 // done) or data frame. This approach may change over time as servers change |
| 600 // their responses to pings. |
| 601 if (len > 0) |
| 602 need_to_send_ping_ = true; |
| 603 |
| 592 return ERR_IO_PENDING; | 604 return ERR_IO_PENDING; |
| 593 } | 605 } |
| 594 | 606 |
| 595 void SpdySession::CloseStream(spdy::SpdyStreamId stream_id, int status) { | 607 void SpdySession::CloseStream(spdy::SpdyStreamId stream_id, int status) { |
| 596 // TODO(mbelshe): We should send a RST_STREAM control frame here | 608 // TODO(mbelshe): We should send a RST_STREAM control frame here |
| 597 // so that the server can cancel a large send. | 609 // so that the server can cancel a large send. |
| 598 | 610 |
| 599 DeleteStream(stream_id, status); | 611 DeleteStream(stream_id, status); |
| 600 } | 612 } |
| 601 | 613 |
| (...skipping 931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1533 } | 1545 } |
| 1534 } | 1546 } |
| 1535 } | 1547 } |
| 1536 | 1548 |
| 1537 void SpdySession::SendPrefacePingIfNoneInFlight() { | 1549 void SpdySession::SendPrefacePingIfNoneInFlight() { |
| 1538 if (pings_in_flight_ || trailing_ping_pending_ || | 1550 if (pings_in_flight_ || trailing_ping_pending_ || |
| 1539 !enable_ping_based_connection_checking_) | 1551 !enable_ping_based_connection_checking_) |
| 1540 return; | 1552 return; |
| 1541 | 1553 |
| 1542 const base::TimeDelta kConnectionAtRiskOfLoss = | 1554 const base::TimeDelta kConnectionAtRiskOfLoss = |
| 1543 base::TimeDelta::FromMilliseconds(connection_at_risk_of_loss_ms_); | 1555 base::TimeDelta::FromSeconds(connection_at_risk_of_loss_seconds_); |
| 1544 | 1556 |
| 1545 base::TimeTicks now = base::TimeTicks::Now(); | 1557 base::TimeTicks now = base::TimeTicks::Now(); |
| 1546 // If we haven't heard from server, then send a preface-PING. | 1558 // If we haven't heard from server, then send a preface-PING. |
| 1547 if ((now - received_data_time_) > kConnectionAtRiskOfLoss) | 1559 if ((now - received_data_time_) > kConnectionAtRiskOfLoss) |
| 1548 SendPrefacePing(); | 1560 SendPrefacePing(); |
| 1549 | 1561 |
| 1550 PlanToSendTrailingPing(); | 1562 PlanToSendTrailingPing(); |
| 1551 } | 1563 } |
| 1552 | 1564 |
| 1553 void SpdySession::SendPrefacePing() { | 1565 void SpdySession::SendPrefacePing() { |
| 1554 // TODO(rtenneti): Send preface pings when more servers support additional | 1566 WritePingFrame(next_ping_id_); |
| 1555 // pings. | |
| 1556 // WritePingFrame(next_ping_id_); | |
| 1557 } | 1567 } |
| 1558 | 1568 |
| 1559 void SpdySession::PlanToSendTrailingPing() { | 1569 void SpdySession::PlanToSendTrailingPing() { |
| 1560 if (trailing_ping_pending_) | 1570 if (trailing_ping_pending_) |
| 1561 return; | 1571 return; |
| 1562 | 1572 |
| 1563 trailing_ping_pending_ = true; | 1573 trailing_ping_pending_ = true; |
| 1564 MessageLoop::current()->PostDelayedTask( | 1574 MessageLoop::current()->PostDelayedTask( |
| 1565 FROM_HERE, | 1575 FROM_HERE, |
| 1566 method_factory_.NewRunnableMethod(&SpdySession::SendTrailingPing), | 1576 method_factory_.NewRunnableMethod(&SpdySession::SendTrailingPing), |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1720 if (it == pending_callback_map_.end()) | 1730 if (it == pending_callback_map_.end()) |
| 1721 return; | 1731 return; |
| 1722 | 1732 |
| 1723 OldCompletionCallback* callback = it->second.callback; | 1733 OldCompletionCallback* callback = it->second.callback; |
| 1724 int result = it->second.result; | 1734 int result = it->second.result; |
| 1725 pending_callback_map_.erase(it); | 1735 pending_callback_map_.erase(it); |
| 1726 callback->Run(result); | 1736 callback->Run(result); |
| 1727 } | 1737 } |
| 1728 | 1738 |
| 1729 } // namespace net | 1739 } // namespace net |
| OLD | NEW |