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

Side by Side Diff: net/spdy/spdy_stream.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_stream.h ('k') | net/spdy/spdy_stream_spdy2_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_stream.h" 5 #include "net/spdy/spdy_stream.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 DCHECK_GE(send_window_size_, delta_window_size); 304 DCHECK_GE(send_window_size_, delta_window_size);
305 305
306 send_window_size_ -= delta_window_size; 306 send_window_size_ -= delta_window_size;
307 307
308 net_log_.AddEvent( 308 net_log_.AddEvent(
309 NetLog::TYPE_SPDY_STREAM_UPDATE_SEND_WINDOW, 309 NetLog::TYPE_SPDY_STREAM_UPDATE_SEND_WINDOW,
310 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, 310 base::Bind(&NetLogSpdyStreamWindowUpdateCallback,
311 stream_id_, -delta_window_size, send_window_size_)); 311 stream_id_, -delta_window_size, send_window_size_));
312 } 312 }
313 313
314 void SpdyStream::IncreaseRecvWindowSize(int32 delta_window_size) {
315 if (session_->flow_control_state() < SpdySession::FLOW_CONTROL_STREAM)
316 return;
317
318 // Call back into the session, since this is the only
319 // window-size-related function that is called by the delegate
320 // instead of by the session.
321 session_->IncreaseRecvWindowSize(delta_window_size);
322
323 // By the time a read is processed by the delegate, this stream may
324 // already be inactive.
325 if (!session_->IsStreamActive(stream_id_))
326 return;
327
328 DCHECK_GE(unacked_recv_window_bytes_, 0);
329 DCHECK_GE(recv_window_size_, unacked_recv_window_bytes_);
330 DCHECK_GE(delta_window_size, 1);
331 // Check for overflow.
332 DCHECK_LE(delta_window_size, kint32max - recv_window_size_);
333
334 recv_window_size_ += delta_window_size;
335 net_log_.AddEvent(
336 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW,
337 base::Bind(&NetLogSpdyStreamWindowUpdateCallback,
338 stream_id_, delta_window_size, recv_window_size_));
339
340 unacked_recv_window_bytes_ += delta_window_size;
341 if (unacked_recv_window_bytes_ >
342 session_->stream_initial_recv_window_size() / 2) {
343 session_->SendStreamWindowUpdate(
344 stream_id_, static_cast<uint32>(unacked_recv_window_bytes_));
345 unacked_recv_window_bytes_ = 0;
346 }
347 }
348
349 int SpdyStream::GetPeerAddress(IPEndPoint* address) const { 314 int SpdyStream::GetPeerAddress(IPEndPoint* address) const {
350 return session_->GetPeerAddress(address); 315 return session_->GetPeerAddress(address);
351 } 316 }
352 317
353 int SpdyStream::GetLocalAddress(IPEndPoint* address) const { 318 int SpdyStream::GetLocalAddress(IPEndPoint* address) const {
354 return session_->GetLocalAddress(address); 319 return session_->GetLocalAddress(address);
355 } 320 }
356 321
357 bool SpdyStream::WasEverUsed() const { 322 bool SpdyStream::WasEverUsed() const {
358 return session_->WasEverUsed(); 323 return session_->WasEverUsed();
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 446
482 if (!buffer) { 447 if (!buffer) {
483 metrics_.StopStream(); 448 metrics_.StopStream();
484 session_->CloseStream(stream_id_, net::OK); 449 session_->CloseStream(stream_id_, net::OK);
485 // Note: |this| may be deleted after calling CloseStream. 450 // Note: |this| may be deleted after calling CloseStream.
486 return; 451 return;
487 } 452 }
488 453
489 size_t length = buffer->GetRemainingSize(); 454 size_t length = buffer->GetRemainingSize();
490 DCHECK_LE(length, session_->GetDataFrameMaximumPayload()); 455 DCHECK_LE(length, session_->GetDataFrameMaximumPayload());
491 if (session_->flow_control_state() >= SpdySession::FLOW_CONTROL_STREAM) 456 if (session_->flow_control_state() >= SpdySession::FLOW_CONTROL_STREAM) {
492 DecreaseRecvWindowSize(static_cast<int32>(length)); 457 DecreaseRecvWindowSize(static_cast<int32>(length));
458 buffer->AddConsumeCallback(
459 base::Bind(&SpdyStream::IncreaseRecvWindowSize,
460 weak_ptr_factory_.GetWeakPtr()));
461 }
493 462
494 // Track our bandwidth. 463 // Track our bandwidth.
495 metrics_.RecordBytes(length); 464 metrics_.RecordBytes(length);
496 recv_bytes_ += length; 465 recv_bytes_ += length;
497 recv_last_byte_time_ = base::TimeTicks::Now(); 466 recv_last_byte_time_ = base::TimeTicks::Now();
498 467
499 if (delegate_->OnDataReceived(buffer.Pass()) != net::OK) { 468 if (delegate_->OnDataReceived(buffer.Pass()) != net::OK) {
500 // |delegate_| rejected the data. 469 // |delegate_| rejected the data.
501 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, "Delegate rejected the data"); 470 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, "Delegate rejected the data");
502 session_->CloseStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR); 471 session_->CloseStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR);
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 recv_first_byte_time_ - send_time_); 882 recv_first_byte_time_ - send_time_);
914 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", 883 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime",
915 recv_last_byte_time_ - recv_first_byte_time_); 884 recv_last_byte_time_ - recv_first_byte_time_);
916 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", 885 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime",
917 recv_last_byte_time_ - send_time_); 886 recv_last_byte_time_ - send_time_);
918 887
919 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); 888 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_);
920 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); 889 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_);
921 } 890 }
922 891
892 void SpdyStream::IncreaseRecvWindowSize(size_t delta_window_size) {
893 if (session_->flow_control_state() < SpdySession::FLOW_CONTROL_STREAM)
894 return;
895
896 // By the time a read is processed by the delegate, this stream may
897 // already be inactive.
898 if (!session_->IsStreamActive(stream_id_))
899 return;
900
901 DCHECK_GE(unacked_recv_window_bytes_, 0);
902 DCHECK_GE(recv_window_size_, unacked_recv_window_bytes_);
903 DCHECK_GE(delta_window_size, 1u);
904 // Check for overflow.
905 DCHECK_LE(delta_window_size,
906 static_cast<size_t>(kint32max - recv_window_size_));
907
908 recv_window_size_ += delta_window_size;
909 net_log_.AddEvent(
910 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW,
911 base::Bind(&NetLogSpdyStreamWindowUpdateCallback,
912 stream_id_, delta_window_size, recv_window_size_));
913
914 unacked_recv_window_bytes_ += delta_window_size;
915 if (unacked_recv_window_bytes_ >
916 session_->stream_initial_recv_window_size() / 2) {
917 session_->SendStreamWindowUpdate(
918 stream_id_, static_cast<uint32>(unacked_recv_window_bytes_));
919 unacked_recv_window_bytes_ = 0;
920 }
921 }
922
923 void SpdyStream::DecreaseRecvWindowSize(int32 delta_window_size) { 923 void SpdyStream::DecreaseRecvWindowSize(int32 delta_window_size) {
924 DCHECK(session_->IsStreamActive(stream_id_)); 924 DCHECK(session_->IsStreamActive(stream_id_));
925 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM); 925 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM);
926 DCHECK_GE(delta_window_size, 1); 926 DCHECK_GE(delta_window_size, 1);
927 927
928 // Since we never decrease the initial window size, 928 // Since we never decrease the initial window size,
929 // |delta_window_size| should never cause |recv_window_size_| to go 929 // |delta_window_size| should never cause |recv_window_size_| to go
930 // negative. If we do, it's a client-side bug, so we use 930 // negative. If we do, it's a client-side bug, so we use
931 // PROTOCOL_ERROR for lack of a better error code. 931 // PROTOCOL_ERROR for lack of a better error code.
932 if (delta_window_size > recv_window_size_) { 932 if (delta_window_size > recv_window_size_) {
933 session_->ResetStream( 933 session_->ResetStream(
934 stream_id_, RST_STREAM_PROTOCOL_ERROR, 934 stream_id_, RST_STREAM_PROTOCOL_ERROR,
935 "Invalid delta_window_size for DecreaseRecvWindowSize"); 935 "Invalid delta_window_size for DecreaseRecvWindowSize");
936 NOTREACHED(); 936 NOTREACHED();
937 return; 937 return;
938 } 938 }
939 939
940 recv_window_size_ -= delta_window_size; 940 recv_window_size_ -= delta_window_size;
941 net_log_.AddEvent( 941 net_log_.AddEvent(
942 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW, 942 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW,
943 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, 943 base::Bind(&NetLogSpdyStreamWindowUpdateCallback,
944 stream_id_, -delta_window_size, recv_window_size_)); 944 stream_id_, -delta_window_size, recv_window_size_));
945 } 945 }
946 946
947 } // namespace net 947 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_stream.h ('k') | net/spdy/spdy_stream_spdy2_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698