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

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: 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
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 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after
1395 NetLog::TYPE_SPDY_SESSION_RECV_DATA, 1395 NetLog::TYPE_SPDY_SESSION_RECV_DATA,
1396 base::Bind(&NetLogSpdyDataCallback, stream_id, len, fin)); 1396 base::Bind(&NetLogSpdyDataCallback, stream_id, len, fin));
1397 } 1397 }
1398 1398
1399 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 1399 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
1400 1400
1401 // By the time data comes in, the stream may already be inactive. 1401 // By the time data comes in, the stream may already be inactive.
1402 if (it == active_streams_.end()) 1402 if (it == active_streams_.end())
1403 return; 1403 return;
1404 1404
1405 // Only decrease the window size for data for active streams.
1406 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION && len > 0)
1407 DecreaseRecvWindowSize(static_cast<int32>(len));
1408
1409 scoped_ptr<SpdyBuffer> buffer; 1405 scoped_ptr<SpdyBuffer> buffer;
1410 if (data) { 1406 if (data) {
1411 DCHECK_GT(len, 0u); 1407 DCHECK_GT(len, 0u);
1412 buffer.reset(new SpdyBuffer(data, len)); 1408 buffer.reset(new SpdyBuffer(data, len));
1409
1410 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) {
1411 DecreaseRecvWindowSize(static_cast<int32>(len));
1412 buffer->AddConsumeCallback(
1413 base::Bind(&SpdySession::IncreaseRecvWindowSize,
1414 weak_factory_.GetWeakPtr()));
1415 }
1413 } else { 1416 } else {
1414 DCHECK_EQ(len, 0u); 1417 DCHECK_EQ(len, 0u);
1415 } 1418 }
1416 it->second->OnDataReceived(buffer.Pass()); 1419 it->second->OnDataReceived(buffer.Pass());
1417 } 1420 }
1418 1421
1419 void SpdySession::OnSetting(SpdySettingsIds id, 1422 void SpdySession::OnSetting(SpdySettingsIds id,
1420 uint8 flags, 1423 uint8 flags,
1421 uint32 value) { 1424 uint32 value) {
1422 HandleSetting(id, value); 1425 HandleSetting(id, value);
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
1798 1801
1799 void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id, 1802 void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id,
1800 uint32 delta_window_size) { 1803 uint32 delta_window_size) {
1801 CHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM); 1804 CHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM);
1802 CHECK(IsStreamActive(stream_id)); 1805 CHECK(IsStreamActive(stream_id));
1803 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 1806 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
1804 CHECK_EQ(stream->stream_id(), stream_id); 1807 CHECK_EQ(stream->stream_id(), stream_id);
1805 SendWindowUpdateFrame(stream_id, delta_window_size, stream->priority()); 1808 SendWindowUpdateFrame(stream_id, delta_window_size, stream->priority());
1806 } 1809 }
1807 1810
1808 void SpdySession::IncreaseRecvWindowSize(int32 delta_window_size) {
1809 if (flow_control_state_ < FLOW_CONTROL_STREAM_AND_SESSION)
1810 return;
1811
1812 DCHECK_GE(session_unacked_recv_window_bytes_, 0);
1813 DCHECK_GE(session_recv_window_size_, session_unacked_recv_window_bytes_);
1814 DCHECK_GE(delta_window_size, 1);
1815 // Check for overflow.
1816 DCHECK_LE(delta_window_size, kint32max - session_recv_window_size_);
1817
1818 session_recv_window_size_ += delta_window_size;
1819 net_log_.AddEvent(
1820 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW,
1821 base::Bind(&NetLogSpdySessionWindowUpdateCallback,
1822 delta_window_size, session_recv_window_size_));
1823
1824 session_unacked_recv_window_bytes_ += delta_window_size;
1825 if (session_unacked_recv_window_bytes_ > kSpdySessionInitialWindowSize / 2) {
1826 SendWindowUpdateFrame(kSessionFlowControlStreamId,
1827 session_unacked_recv_window_bytes_,
1828 HIGHEST);
1829 session_unacked_recv_window_bytes_ = 0;
1830 }
1831 }
1832
1833 // Given a cwnd that we would have sent to the server, modify it based on the 1811 // Given a cwnd that we would have sent to the server, modify it based on the
1834 // field trial policy. 1812 // field trial policy.
1835 uint32 ApplyCwndFieldTrialPolicy(int cwnd) { 1813 uint32 ApplyCwndFieldTrialPolicy(int cwnd) {
1836 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd"); 1814 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd");
1837 if (!trial) { 1815 if (!trial) {
1838 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList"; 1816 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList";
1839 return cwnd; 1817 return cwnd;
1840 } 1818 }
1841 if (trial->group_name() == "cwnd10") 1819 if (trial->group_name() == "cwnd10")
1842 return 10; 1820 return 10;
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
2273 DCHECK_GE(session_send_window_size_, delta_window_size); 2251 DCHECK_GE(session_send_window_size_, delta_window_size);
2274 2252
2275 session_send_window_size_ -= delta_window_size; 2253 session_send_window_size_ -= delta_window_size;
2276 2254
2277 net_log_.AddEvent( 2255 net_log_.AddEvent(
2278 NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW, 2256 NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW,
2279 base::Bind(&NetLogSpdySessionWindowUpdateCallback, 2257 base::Bind(&NetLogSpdySessionWindowUpdateCallback,
2280 -delta_window_size, session_send_window_size_)); 2258 -delta_window_size, session_send_window_size_));
2281 } 2259 }
2282 2260
2261 void SpdySession::IncreaseRecvWindowSize(size_t delta_window_size) {
2262 if (flow_control_state_ < FLOW_CONTROL_STREAM_AND_SESSION)
2263 return;
2264
2265 DCHECK_GE(session_unacked_recv_window_bytes_, 0);
2266 DCHECK_GE(session_recv_window_size_, session_unacked_recv_window_bytes_);
2267 DCHECK_GE(delta_window_size, 1u);
2268 // Check for overflow.
2269 DCHECK_LE(delta_window_size,
2270 static_cast<size_t>(kint32max - session_recv_window_size_));
2271
2272 session_recv_window_size_ += delta_window_size;
2273 net_log_.AddEvent(
2274 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW,
2275 base::Bind(&NetLogSpdySessionWindowUpdateCallback,
2276 delta_window_size, session_recv_window_size_));
2277
2278 session_unacked_recv_window_bytes_ += delta_window_size;
2279 if (session_unacked_recv_window_bytes_ > kSpdySessionInitialWindowSize / 2) {
2280 SendWindowUpdateFrame(kSessionFlowControlStreamId,
2281 session_unacked_recv_window_bytes_,
2282 HIGHEST);
2283 session_unacked_recv_window_bytes_ = 0;
2284 }
2285 }
2286
2283 void SpdySession::DecreaseRecvWindowSize(int32 delta_window_size) { 2287 void SpdySession::DecreaseRecvWindowSize(int32 delta_window_size) {
2284 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 2288 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION);
2285 DCHECK_GE(delta_window_size, 1); 2289 DCHECK_GE(delta_window_size, 1);
2286 2290
2287 // |delta_window_size| should never cause 2291 // |delta_window_size| should never cause
2288 // |session_recv_window_size_| to go negative. If we do, it's a 2292 // |session_recv_window_size_| to go negative. If we do, it's a
2289 // client-side bug. 2293 // client-side bug.
2290 if (delta_window_size > session_recv_window_size_) { 2294 if (delta_window_size > session_recv_window_size_) {
2291 NOTREACHED() << "Received session WINDOW_UPDATE with an " 2295 NOTREACHED() << "Received session WINDOW_UPDATE with an "
2292 << "invalid delta_window_size " << delta_window_size; 2296 << "invalid delta_window_size " << delta_window_size;
2293 // TODO(akalin): Figure out whether we should instead send a 2297 // TODO(akalin): Figure out whether we should instead send a
2294 // GOAWAY and close the connection here. 2298 // GOAWAY and close the connection here.
2295 return; 2299 return;
2296 } 2300 }
2297 2301
2298 session_recv_window_size_ -= delta_window_size; 2302 session_recv_window_size_ -= delta_window_size;
2299 net_log_.AddEvent( 2303 net_log_.AddEvent(
2300 NetLog::TYPE_SPDY_SESSION_UPDATE_RECV_WINDOW, 2304 NetLog::TYPE_SPDY_SESSION_UPDATE_RECV_WINDOW,
2301 base::Bind(&NetLogSpdySessionWindowUpdateCallback, 2305 base::Bind(&NetLogSpdySessionWindowUpdateCallback,
2302 -delta_window_size, session_recv_window_size_)); 2306 -delta_window_size, session_recv_window_size_));
2303 } 2307 }
2304 2308
2305 } // namespace net 2309 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698