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 |