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

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

Issue 14348012: [SPDY] Close SPDY sessions on session flow control errors (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments, fix bug 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_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"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/message_loop.h" 12 #include "base/message_loop.h"
13 #include "base/stringprintf.h" 13 #include "base/stringprintf.h"
14 #include "base/strings/string_number_conversions.h"
14 #include "base/values.h" 15 #include "base/values.h"
15 #include "net/spdy/spdy_buffer_producer.h" 16 #include "net/spdy/spdy_buffer_producer.h"
16 #include "net/spdy/spdy_http_utils.h" 17 #include "net/spdy/spdy_http_utils.h"
17 #include "net/spdy/spdy_session.h" 18 #include "net/spdy/spdy_session.h"
18 19
19 namespace net { 20 namespace net {
20 21
21 namespace { 22 namespace {
22 23
23 Value* NetLogSpdyStreamErrorCallback(SpdyStreamId stream_id, 24 Value* NetLogSpdyStreamErrorCallback(SpdyStreamId stream_id,
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 pending_buffers_.release(&buffers); 182 pending_buffers_.release(&buffers);
182 for (size_t i = 0; i < buffers.size(); ++i) { 183 for (size_t i = 0; i < buffers.size(); ++i) {
183 // It is always possible that a callback to the delegate results in 184 // It is always possible that a callback to the delegate results in
184 // the delegate no longer being available. 185 // the delegate no longer being available.
185 if (!delegate_) 186 if (!delegate_)
186 break; 187 break;
187 if (buffers[i]) { 188 if (buffers[i]) {
188 delegate_->OnDataReceived(scoped_ptr<SpdyBuffer>(buffers[i])); 189 delegate_->OnDataReceived(scoped_ptr<SpdyBuffer>(buffers[i]));
189 } else { 190 } else {
190 delegate_->OnDataReceived(scoped_ptr<SpdyBuffer>()); 191 delegate_->OnDataReceived(scoped_ptr<SpdyBuffer>());
191 session_->CloseStream(stream_id_, net::OK); 192 session_->CloseStream(stream_id_, OK);
192 // Note: |this| may be deleted after calling CloseStream. 193 // Note: |this| may be deleted after calling CloseStream.
193 DCHECK_EQ(buffers.size() - 1, i); 194 DCHECK_EQ(buffers.size() - 1, i);
194 } 195 }
195 } 196 }
196 } 197 }
197 198
198 scoped_ptr<SpdyFrame> SpdyStream::ProduceSynStreamFrame() { 199 scoped_ptr<SpdyFrame> SpdyStream::ProduceSynStreamFrame() {
199 CHECK_EQ(io_state_, STATE_SEND_HEADERS_COMPLETE); 200 CHECK_EQ(io_state_, STATE_SEND_HEADERS_COMPLETE);
200 CHECK(request_.get()); 201 CHECK(request_.get());
201 CHECK_GT(stream_id_, 0u); 202 CHECK_GT(stream_id_, 0u);
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 stream_id_, static_cast<uint32>(unacked_recv_window_bytes_)); 365 stream_id_, static_cast<uint32>(unacked_recv_window_bytes_));
365 unacked_recv_window_bytes_ = 0; 366 unacked_recv_window_bytes_ = 0;
366 } 367 }
367 } 368 }
368 369
369 void SpdyStream::DecreaseRecvWindowSize(int32 delta_window_size) { 370 void SpdyStream::DecreaseRecvWindowSize(int32 delta_window_size) {
370 DCHECK(session_->IsStreamActive(stream_id_)); 371 DCHECK(session_->IsStreamActive(stream_id_));
371 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM); 372 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM);
372 DCHECK_GE(delta_window_size, 1); 373 DCHECK_GE(delta_window_size, 1);
373 374
374 // Since we never decrease the initial window size, 375 // Since we never decrease the initial receive window size,
375 // |delta_window_size| should never cause |recv_window_size_| to go 376 // |delta_window_size| should never cause |recv_window_size_| to go
376 // negative. If we do, it's a client-side bug, so we use 377 // negative. If we do, the receive window isn't being respected.
377 // PROTOCOL_ERROR for lack of a better error code.
378 if (delta_window_size > recv_window_size_) { 378 if (delta_window_size > recv_window_size_) {
379 session_->ResetStream( 379 session_->ResetStream(
380 stream_id_, RST_STREAM_PROTOCOL_ERROR, 380 stream_id_, RST_STREAM_PROTOCOL_ERROR,
381 "Invalid delta_window_size for DecreaseRecvWindowSize"); 381 "delta_window_size is " + base::IntToString(delta_window_size) +
382 NOTREACHED(); 382 " in DecreaseRecvWindowSize, which is larger than the receive " +
383 "window size of " + base::IntToString(recv_window_size_));
383 return; 384 return;
384 } 385 }
385 386
386 recv_window_size_ -= delta_window_size; 387 recv_window_size_ -= delta_window_size;
387 net_log_.AddEvent( 388 net_log_.AddEvent(
388 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW, 389 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW,
389 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, 390 base::Bind(&NetLogSpdyStreamWindowUpdateCallback,
390 stream_id_, -delta_window_size, recv_window_size_)); 391 stream_id_, -delta_window_size, recv_window_size_));
391 } 392 }
392 393
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 // Note: we leave the stream open in the session until the stream 519 // Note: we leave the stream open in the session until the stream
519 // is claimed. 520 // is claimed.
520 } 521 }
521 return; 522 return;
522 } 523 }
523 524
524 CHECK(!closed()); 525 CHECK(!closed());
525 526
526 if (!buffer) { 527 if (!buffer) {
527 metrics_.StopStream(); 528 metrics_.StopStream();
528 session_->CloseStream(stream_id_, net::OK); 529 session_->CloseStream(stream_id_, OK);
529 // Note: |this| may be deleted after calling CloseStream. 530 // Note: |this| may be deleted after calling CloseStream.
530 return; 531 return;
531 } 532 }
532 533
533 size_t length = buffer->GetRemainingSize(); 534 size_t length = buffer->GetRemainingSize();
534 DCHECK_LE(length, session_->GetDataFrameMaximumPayload()); 535 DCHECK_LE(length, session_->GetDataFrameMaximumPayload());
535 if (session_->flow_control_state() >= SpdySession::FLOW_CONTROL_STREAM) { 536 if (session_->flow_control_state() >= SpdySession::FLOW_CONTROL_STREAM) {
536 DecreaseRecvWindowSize(static_cast<int32>(length)); 537 DecreaseRecvWindowSize(static_cast<int32>(length));
537 buffer->AddConsumeCallback( 538 buffer->AddConsumeCallback(
538 base::Bind(&SpdyStream::OnReadBufferConsumed, 539 base::Bind(&SpdyStream::OnReadBufferConsumed,
539 weak_ptr_factory_.GetWeakPtr())); 540 weak_ptr_factory_.GetWeakPtr()));
540 } 541 }
541 542
542 // Track our bandwidth. 543 // Track our bandwidth.
543 metrics_.RecordBytes(length); 544 metrics_.RecordBytes(length);
544 recv_bytes_ += length; 545 recv_bytes_ += length;
545 recv_last_byte_time_ = base::TimeTicks::Now(); 546 recv_last_byte_time_ = base::TimeTicks::Now();
546 547
547 if (delegate_->OnDataReceived(buffer.Pass()) != net::OK) { 548 if (delegate_->OnDataReceived(buffer.Pass()) != OK) {
548 // |delegate_| rejected the data. 549 // |delegate_| rejected the data.
549 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, "Delegate rejected the data"); 550 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, "Delegate rejected the data");
550 session_->CloseStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR); 551 session_->CloseStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR);
551 return; 552 return;
552 } 553 }
553 } 554 }
554 555
555 void SpdyStream::OnFrameWriteComplete(SpdyFrameType frame_type, 556 void SpdyStream::OnFrameWriteComplete(SpdyFrameType frame_type,
556 size_t frame_size) { 557 size_t frame_size) {
557 if (frame_size < session_->GetFrameMinimumSize() || 558 if (frame_size < session_->GetFrameMinimumSize() ||
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 592
592 cancelled_ = true; 593 cancelled_ = true;
593 if (session_->IsStreamActive(stream_id_)) 594 if (session_->IsStreamActive(stream_id_))
594 session_->ResetStream(stream_id_, RST_STREAM_CANCEL, std::string()); 595 session_->ResetStream(stream_id_, RST_STREAM_CANCEL, std::string());
595 else if (stream_id_ == 0) 596 else if (stream_id_ == 0)
596 session_->CloseCreatedStream(this, RST_STREAM_CANCEL); 597 session_->CloseCreatedStream(this, RST_STREAM_CANCEL);
597 } 598 }
598 599
599 void SpdyStream::Close() { 600 void SpdyStream::Close() {
600 if (stream_id_ != 0) 601 if (stream_id_ != 0)
601 session_->CloseStream(stream_id_, net::OK); 602 session_->CloseStream(stream_id_, OK);
602 else 603 else
603 session_->CloseCreatedStream(this, OK); 604 session_->CloseCreatedStream(this, OK);
604 } 605 }
605 606
606 int SpdyStream::SendRequest(bool has_upload_data) { 607 int SpdyStream::SendRequest(bool has_upload_data) {
607 // Pushed streams do not send any data, and should always be 608 // Pushed streams do not send any data, and should always be
608 // idle. However, we still want to return IO_PENDING to mimic 609 // idle. However, we still want to return IO_PENDING to mimic
609 // non-push behavior. 610 // non-push behavior.
610 has_upload_data_ = has_upload_data; 611 has_upload_data_ = has_upload_data;
611 if (pushed_) { 612 if (pushed_) {
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", 979 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime",
979 recv_last_byte_time_ - recv_first_byte_time_); 980 recv_last_byte_time_ - recv_first_byte_time_);
980 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", 981 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime",
981 recv_last_byte_time_ - send_time_); 982 recv_last_byte_time_ - send_time_);
982 983
983 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); 984 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_);
984 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); 985 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_);
985 } 986 }
986 987
987 } // namespace net 988 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698