Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(414)

Side by Side Diff: net/spdy/spdy_session.cc

Issue 14311002: [SPDY] Avoid leaking bytes from the session flow control receive window (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/spdy/spdy_session.h ('k') | net/spdy/spdy_session_spdy3_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1412 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 NetLog::TYPE_SPDY_SESSION_RECV_DATA, 1423 NetLog::TYPE_SPDY_SESSION_RECV_DATA,
1424 base::Bind(&NetLogSpdyDataCallback, stream_id, len, fin)); 1424 base::Bind(&NetLogSpdyDataCallback, stream_id, len, fin));
1425 } 1425 }
1426 1426
1427 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 1427 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
1428 1428
1429 // By the time data comes in, the stream may already be inactive. 1429 // By the time data comes in, the stream may already be inactive.
1430 if (it == active_streams_.end()) 1430 if (it == active_streams_.end())
1431 return; 1431 return;
1432 1432
1433 // Only decrease the window size for data for active streams.
1434 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION && len > 0)
1435 DecreaseRecvWindowSize(static_cast<int32>(len));
1436
1437 scoped_ptr<SpdyBuffer> buffer; 1433 scoped_ptr<SpdyBuffer> buffer;
1438 if (data) { 1434 if (data) {
1439 DCHECK_GT(len, 0u); 1435 DCHECK_GT(len, 0u);
1440 buffer.reset(new SpdyBuffer(data, len)); 1436 buffer.reset(new SpdyBuffer(data, len));
1437
1438 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) {
1439 DecreaseRecvWindowSize(static_cast<int32>(len));
1440 buffer->AddConsumeCallback(
1441 base::Bind(&SpdySession::IncreaseRecvWindowSize,
1442 weak_factory_.GetWeakPtr()));
1443 }
1441 } else { 1444 } else {
1442 DCHECK_EQ(len, 0u); 1445 DCHECK_EQ(len, 0u);
1443 } 1446 }
1444 it->second->OnDataReceived(buffer.Pass()); 1447 it->second->OnDataReceived(buffer.Pass());
1445 } 1448 }
1446 1449
1447 void SpdySession::OnSetting(SpdySettingsIds id, 1450 void SpdySession::OnSetting(SpdySettingsIds id,
1448 uint8 flags, 1451 uint8 flags,
1449 uint32 value) { 1452 uint32 value) {
1450 HandleSetting(id, value); 1453 HandleSetting(id, value);
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
1826 1829
1827 void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id, 1830 void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id,
1828 uint32 delta_window_size) { 1831 uint32 delta_window_size) {
1829 CHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM); 1832 CHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM);
1830 CHECK(IsStreamActive(stream_id)); 1833 CHECK(IsStreamActive(stream_id));
1831 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 1834 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
1832 CHECK_EQ(stream->stream_id(), stream_id); 1835 CHECK_EQ(stream->stream_id(), stream_id);
1833 SendWindowUpdateFrame(stream_id, delta_window_size, stream->priority()); 1836 SendWindowUpdateFrame(stream_id, delta_window_size, stream->priority());
1834 } 1837 }
1835 1838
1836 void SpdySession::IncreaseRecvWindowSize(int32 delta_window_size) {
1837 if (flow_control_state_ < FLOW_CONTROL_STREAM_AND_SESSION)
1838 return;
1839
1840 DCHECK_GE(session_unacked_recv_window_bytes_, 0);
1841 DCHECK_GE(session_recv_window_size_, session_unacked_recv_window_bytes_);
1842 DCHECK_GE(delta_window_size, 1);
1843 // Check for overflow.
1844 DCHECK_LE(delta_window_size, kint32max - session_recv_window_size_);
1845
1846 session_recv_window_size_ += delta_window_size;
1847 net_log_.AddEvent(
1848 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW,
1849 base::Bind(&NetLogSpdySessionWindowUpdateCallback,
1850 delta_window_size, session_recv_window_size_));
1851
1852 session_unacked_recv_window_bytes_ += delta_window_size;
1853 if (session_unacked_recv_window_bytes_ > kSpdySessionInitialWindowSize / 2) {
1854 SendWindowUpdateFrame(kSessionFlowControlStreamId,
1855 session_unacked_recv_window_bytes_,
1856 HIGHEST);
1857 session_unacked_recv_window_bytes_ = 0;
1858 }
1859 }
1860
1861 // Given a cwnd that we would have sent to the server, modify it based on the 1839 // Given a cwnd that we would have sent to the server, modify it based on the
1862 // field trial policy. 1840 // field trial policy.
1863 uint32 ApplyCwndFieldTrialPolicy(int cwnd) { 1841 uint32 ApplyCwndFieldTrialPolicy(int cwnd) {
1864 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd"); 1842 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd");
1865 if (!trial) { 1843 if (!trial) {
1866 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList"; 1844 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList";
1867 return cwnd; 1845 return cwnd;
1868 } 1846 }
1869 if (trial->group_name() == "cwnd10") 1847 if (trial->group_name() == "cwnd10")
1870 return 10; 1848 return 10;
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
2301 DCHECK_GE(session_send_window_size_, delta_window_size); 2279 DCHECK_GE(session_send_window_size_, delta_window_size);
2302 2280
2303 session_send_window_size_ -= delta_window_size; 2281 session_send_window_size_ -= delta_window_size;
2304 2282
2305 net_log_.AddEvent( 2283 net_log_.AddEvent(
2306 NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW, 2284 NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW,
2307 base::Bind(&NetLogSpdySessionWindowUpdateCallback, 2285 base::Bind(&NetLogSpdySessionWindowUpdateCallback,
2308 -delta_window_size, session_send_window_size_)); 2286 -delta_window_size, session_send_window_size_));
2309 } 2287 }
2310 2288
2289 void SpdySession::IncreaseRecvWindowSize(size_t delta_window_size) {
2290 if (flow_control_state_ < FLOW_CONTROL_STREAM_AND_SESSION)
2291 return;
2292
2293 DCHECK_GE(session_unacked_recv_window_bytes_, 0);
2294 DCHECK_GE(session_recv_window_size_, session_unacked_recv_window_bytes_);
2295 DCHECK_GE(delta_window_size, 1u);
2296 // Check for overflow.
2297 DCHECK_LE(delta_window_size,
2298 static_cast<size_t>(kint32max - session_recv_window_size_));
2299
2300 session_recv_window_size_ += delta_window_size;
2301 net_log_.AddEvent(
2302 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW,
2303 base::Bind(&NetLogSpdySessionWindowUpdateCallback,
2304 delta_window_size, session_recv_window_size_));
2305
2306 session_unacked_recv_window_bytes_ += delta_window_size;
2307 if (session_unacked_recv_window_bytes_ > kSpdySessionInitialWindowSize / 2) {
2308 SendWindowUpdateFrame(kSessionFlowControlStreamId,
2309 session_unacked_recv_window_bytes_,
2310 HIGHEST);
2311 session_unacked_recv_window_bytes_ = 0;
2312 }
2313 }
2314
2311 void SpdySession::DecreaseRecvWindowSize(int32 delta_window_size) { 2315 void SpdySession::DecreaseRecvWindowSize(int32 delta_window_size) {
2312 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 2316 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION);
2313 DCHECK_GE(delta_window_size, 1); 2317 DCHECK_GE(delta_window_size, 1);
2314 2318
2315 // |delta_window_size| should never cause 2319 // |delta_window_size| should never cause
2316 // |session_recv_window_size_| to go negative. If we do, it's a 2320 // |session_recv_window_size_| to go negative. If we do, it's a
2317 // client-side bug. 2321 // client-side bug.
2318 if (delta_window_size > session_recv_window_size_) { 2322 if (delta_window_size > session_recv_window_size_) {
2319 NOTREACHED() << "Received session WINDOW_UPDATE with an " 2323 NOTREACHED() << "Received session WINDOW_UPDATE with an "
2320 << "invalid delta_window_size " << delta_window_size; 2324 << "invalid delta_window_size " << delta_window_size;
2321 // TODO(akalin): Figure out whether we should instead send a 2325 // TODO(akalin): Figure out whether we should instead send a
2322 // GOAWAY and close the connection here. 2326 // GOAWAY and close the connection here.
2323 return; 2327 return;
2324 } 2328 }
2325 2329
2326 session_recv_window_size_ -= delta_window_size; 2330 session_recv_window_size_ -= delta_window_size;
2327 net_log_.AddEvent( 2331 net_log_.AddEvent(
2328 NetLog::TYPE_SPDY_SESSION_UPDATE_RECV_WINDOW, 2332 NetLog::TYPE_SPDY_SESSION_UPDATE_RECV_WINDOW,
2329 base::Bind(&NetLogSpdySessionWindowUpdateCallback, 2333 base::Bind(&NetLogSpdySessionWindowUpdateCallback,
2330 -delta_window_size, session_recv_window_size_)); 2334 -delta_window_size, session_recv_window_size_));
2331 } 2335 }
2332 2336
2333 } // namespace net 2337 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_session.h ('k') | net/spdy/spdy_session_spdy3_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698