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

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

Issue 10448083: Fix out of order SYN_STEAM frames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix willchan's comments Created 8 years, 5 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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/stringprintf.h" 10 #include "base/stringprintf.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 if (*i >= 'A' && *i <= 'Z') { 43 if (*i >= 'A' && *i <= 'Z') {
44 return true; 44 return true;
45 } 45 }
46 } 46 }
47 return false; 47 return false;
48 } 48 }
49 49
50 } // namespace 50 } // namespace
51 51
52 SpdyStream::SpdyStream(SpdySession* session, 52 SpdyStream::SpdyStream(SpdySession* session,
53 SpdyStreamId stream_id,
54 bool pushed, 53 bool pushed,
55 const BoundNetLog& net_log) 54 const BoundNetLog& net_log)
56 : continue_buffering_data_(true), 55 : continue_buffering_data_(true),
57 stream_id_(stream_id), 56 stream_id_(0),
58 priority_(HIGHEST), 57 priority_(HIGHEST),
59 slot_(0), 58 slot_(0),
60 stalled_by_flow_control_(false), 59 stalled_by_flow_control_(false),
61 send_window_size_(kSpdyStreamInitialWindowSize), 60 send_window_size_(kSpdyStreamInitialWindowSize),
62 recv_window_size_(kSpdyStreamInitialWindowSize), 61 recv_window_size_(kSpdyStreamInitialWindowSize),
63 unacked_recv_window_bytes_(0), 62 unacked_recv_window_bytes_(0),
64 pushed_(pushed), 63 pushed_(pushed),
65 response_received_(false), 64 response_received_(false),
66 session_(session), 65 session_(session),
67 delegate_(NULL), 66 delegate_(NULL),
68 request_time_(base::Time::Now()), 67 request_time_(base::Time::Now()),
69 response_(new SpdyHeaderBlock), 68 response_(new SpdyHeaderBlock),
70 io_state_(STATE_NONE), 69 io_state_(STATE_NONE),
71 response_status_(OK), 70 response_status_(OK),
72 cancelled_(false), 71 cancelled_(false),
73 has_upload_data_(false), 72 has_upload_data_(false),
74 net_log_(net_log), 73 net_log_(net_log),
75 send_bytes_(0), 74 send_bytes_(0),
76 recv_bytes_(0), 75 recv_bytes_(0),
77 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { 76 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) {
78 } 77 }
79 78
79 class SpdyStream::SpdyStreamIOBufferProducer
80 : public SpdySession::SpdyIOBufferProducer {
81 public:
82 SpdyStreamIOBufferProducer(SpdyStream* stream) : stream_(stream) {}
83
84 // SpdyFrameProducer
85 virtual RequestPriority GetPriority() const OVERRIDE {
86 return stream_->priority();
87 }
88
89 virtual SpdyIOBuffer* ProduceNextBuffer(SpdySession* session) OVERRIDE {
90 if (stream_->stream_id() == 0)
91 SpdySession::SpdyIOBufferProducer::ActivateStream(session, stream_);
92 SpdyFrame* frame = stream_->ProduceNextFrame();
93 return frame == NULL ? NULL :
94 SpdySession::SpdyIOBufferProducer::CreateIOBuffer(
95 frame, GetPriority(), stream_);
96 }
97
98 private:
99 scoped_refptr<SpdyStream> stream_;
100
ramant (doing other things) 2012/06/26 23:30:25 overly nit: extra blank line.
Ryan Hamilton 2012/06/27 16:58:28 Done.
101 };
102
103 void SpdyStream::SetHasWriteAvailable() {
104 session_->SetStreamHasWriteAvailable(this,
105 new SpdyStreamIOBufferProducer(this));
106 }
107
108 SpdyFrame* SpdyStream::ProduceNextFrame() {
109 if (io_state_ == STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE) {
110 CHECK(request_.get());
111 CHECK_GT(stream_id_, 0u);
112
113 std::string origin = GetUrl().GetOrigin().spec();
114 origin.erase(origin.length() - 1); // trim trailing slash
115 SpdyCredentialControlFrame* frame = session_->CreateCredentialFrame(
ramant (doing other things) 2012/06/26 23:30:25 nit: should we DCHECK that "origin" ends with slas
Ryan Hamilton 2012/06/27 16:58:28 Done.
116 origin, domain_bound_cert_type_, domain_bound_private_key_,
117 domain_bound_cert_, priority_);
118 return frame;
119 } else if (io_state_ == STATE_SEND_HEADERS_COMPLETE) {
120 CHECK(request_.get());
121 CHECK_GT(stream_id_, 0u);
122
123 SpdyControlFlags flags =
124 has_upload_data_ ? CONTROL_FLAG_NONE : CONTROL_FLAG_FIN;
125 SpdySynStreamControlFrame* frame = session_->CreateSynStream(
126 stream_id_, priority_, slot_, flags, request_);
127 set_stream_id(frame->stream_id());
ramant (doing other things) 2012/06/26 23:30:25 nit: why call set_stream_id again? stream_id_ is n
Ryan Hamilton 2012/06/27 16:58:28 I *swear* I removed that line of code earlier, but
128 send_time_ = base::TimeTicks::Now();
129 return frame;
130 } else {
131 CHECK(!cancelled());
132 // We must need to write stream data.
133 // Until the headers have been completely sent, we can not be sure
134 // that our stream_id is correct.
135 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE);
136 DCHECK_GT(stream_id_, 0u);
137 DCHECK(!pending_data_frames_.empty());
138 SpdyFrame* frame = pending_data_frames_.front();
139 pending_data_frames_.pop_front();
140 return frame;
141 }
142 }
143
80 SpdyStream::~SpdyStream() { 144 SpdyStream::~SpdyStream() {
81 UpdateHistograms(); 145 UpdateHistograms();
146 while (!pending_data_frames_.empty()) {
147 SpdyFrame* frame = pending_data_frames_.back();
148 pending_data_frames_.pop_back();
149 delete frame;
150 }
82 } 151 }
83 152
84 void SpdyStream::SetDelegate(Delegate* delegate) { 153 void SpdyStream::SetDelegate(Delegate* delegate) {
85 CHECK(delegate); 154 CHECK(delegate);
86 delegate_ = delegate; 155 delegate_ = delegate;
87 156
88 if (pushed_) { 157 if (pushed_) {
89 CHECK(response_received()); 158 CHECK(response_received());
90 MessageLoop::current()->PostTask( 159 MessageLoop::current()->PostTask(
91 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this)); 160 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this));
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 void SpdyStream::Cancel() { 534 void SpdyStream::Cancel() {
466 if (cancelled()) 535 if (cancelled())
467 return; 536 return;
468 537
469 cancelled_ = true; 538 cancelled_ = true;
470 if (session_->IsStreamActive(stream_id_)) 539 if (session_->IsStreamActive(stream_id_))
471 session_->ResetStream(stream_id_, CANCEL, ""); 540 session_->ResetStream(stream_id_, CANCEL, "");
472 } 541 }
473 542
474 void SpdyStream::Close() { 543 void SpdyStream::Close() {
475 session_->CloseStream(stream_id_, net::OK); 544 if (stream_id_ != 0)
545 session_->CloseStream(stream_id_, net::OK);
546 else
547 session_->CloseCreatedStream(this, OK);
476 } 548 }
477 549
478 int SpdyStream::SendRequest(bool has_upload_data) { 550 int SpdyStream::SendRequest(bool has_upload_data) {
479 if (delegate_) 551 if (delegate_)
480 delegate_->set_chunk_callback(this); 552 delegate_->set_chunk_callback(this);
481 553
482 // Pushed streams do not send any data, and should always be in STATE_OPEN or 554 // Pushed streams do not send any data, and should always be in STATE_OPEN or
483 // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push 555 // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push
484 // behavior. 556 // behavior.
485 has_upload_data_ = has_upload_data; 557 has_upload_data_ = has_upload_data;
486 if (pushed_) { 558 if (pushed_) {
487 send_time_ = base::TimeTicks::Now(); 559 send_time_ = base::TimeTicks::Now();
488 DCHECK(!has_upload_data_); 560 DCHECK(!has_upload_data_);
489 DCHECK(response_received()); 561 DCHECK(response_received());
490 return ERR_IO_PENDING; 562 return ERR_IO_PENDING;
491 } 563 }
492 CHECK_EQ(STATE_NONE, io_state_); 564 CHECK_EQ(STATE_NONE, io_state_);
493 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; 565 io_state_ = STATE_GET_DOMAIN_BOUND_CERT;
494 return DoLoop(OK); 566 return DoLoop(OK);
495 } 567 }
496 568
497 int SpdyStream::WriteStreamData(IOBuffer* data, int length, 569 int SpdyStream::WriteStreamData(IOBuffer* data, int length,
498 SpdyDataFlags flags) { 570 SpdyDataFlags flags) {
499 // Until the headers have been completely sent, we can not be sure 571 // Until the headers have been completely sent, we can not be sure
500 // that our stream_id is correct. 572 // that our stream_id is correct.
501 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); 573 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE);
502 return session_->WriteStreamData(stream_id_, data, length, flags); 574 CHECK_GT(stream_id_, 0u);
575
576 pending_data_frames_.push_back(
577 session_->CreateDataFrame(stream_id_, data, length, flags));
578
579 SetHasWriteAvailable();
580 return ERR_IO_PENDING;
503 } 581 }
504 582
505 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, 583 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info,
506 bool* was_npn_negotiated, 584 bool* was_npn_negotiated,
507 NextProto* protocol_negotiated) { 585 NextProto* protocol_negotiated) {
508 return session_->GetSSLInfo( 586 return session_->GetSSLInfo(
509 ssl_info, was_npn_negotiated, protocol_negotiated); 587 ssl_info, was_npn_negotiated, protocol_negotiated);
510 } 588 }
511 589
512 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { 590 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) {
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 return result; 714 return result;
637 715
638 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; 716 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT;
639 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); 717 slot_ = session_->credential_state()->SetHasCredential(GetUrl());
640 return OK; 718 return OK;
641 } 719 }
642 720
643 int SpdyStream::DoSendDomainBoundCert() { 721 int SpdyStream::DoSendDomainBoundCert() {
644 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; 722 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE;
645 CHECK(request_.get()); 723 CHECK(request_.get());
646 std::string origin = GetUrl().GetOrigin().spec(); 724 SetHasWriteAvailable();
647 origin.erase(origin.length() - 1); // trim trailing slash 725 return ERR_IO_PENDING;
648 int rv = session_->WriteCredentialFrame(
649 origin, domain_bound_cert_type_, domain_bound_private_key_,
650 domain_bound_cert_, priority_);
651 if (rv != ERR_IO_PENDING)
652 return rv;
653 return OK;
654 } 726 }
655 727
656 int SpdyStream::DoSendDomainBoundCertComplete(int result) { 728 int SpdyStream::DoSendDomainBoundCertComplete(int result) {
657 if (result < 0) 729 if (result < 0)
658 return result; 730 return result;
659 731
660 io_state_ = STATE_SEND_HEADERS; 732 io_state_ = STATE_SEND_HEADERS;
661 return OK; 733 return OK;
662 } 734 }
663 735
664 int SpdyStream::DoSendHeaders() { 736 int SpdyStream::DoSendHeaders() {
665 CHECK(!cancelled_); 737 CHECK(!cancelled_);
666 738
667 SpdyControlFlags flags = CONTROL_FLAG_NONE; 739 SetHasWriteAvailable();
668 if (!has_upload_data_)
669 flags = CONTROL_FLAG_FIN;
670
671 CHECK(request_.get());
672 int result = session_->WriteSynStream(
673 stream_id_, priority_, slot_, flags,
674 request_);
675 if (result != ERR_IO_PENDING)
676 return result;
677
678 send_time_ = base::TimeTicks::Now();
679 io_state_ = STATE_SEND_HEADERS_COMPLETE; 740 io_state_ = STATE_SEND_HEADERS_COMPLETE;
680 return ERR_IO_PENDING; 741 return ERR_IO_PENDING;
681 } 742 }
682 743
683 int SpdyStream::DoSendHeadersComplete(int result) { 744 int SpdyStream::DoSendHeadersComplete(int result) {
684 if (result < 0) 745 if (result < 0)
685 return result; 746 return result;
686 747
687 CHECK_GT(result, 0); 748 CHECK_GT(result, 0);
688 749
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", 809 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime",
749 recv_last_byte_time_ - recv_first_byte_time_); 810 recv_last_byte_time_ - recv_first_byte_time_);
750 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", 811 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime",
751 recv_last_byte_time_ - send_time_); 812 recv_last_byte_time_ - send_time_);
752 813
753 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); 814 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_);
754 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); 815 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_);
755 } 816 }
756 817
757 } // namespace net 818 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698