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

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: Make SpdyFrameProducer a nested class in SpdySession. Created 8 years, 6 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 if (*i >= 'A' && *i <= 'Z') { 65 if (*i >= 'A' && *i <= 'Z') {
66 return true; 66 return true;
67 } 67 }
68 } 68 }
69 return false; 69 return false;
70 } 70 }
71 71
72 } // namespace 72 } // namespace
73 73
74 SpdyStream::SpdyStream(SpdySession* session, 74 SpdyStream::SpdyStream(SpdySession* session,
75 SpdyStreamId stream_id,
76 bool pushed, 75 bool pushed,
77 const BoundNetLog& net_log) 76 const BoundNetLog& net_log)
78 : continue_buffering_data_(true), 77 : continue_buffering_data_(true),
79 stream_id_(stream_id), 78 stream_id_(0),
80 priority_(HIGHEST), 79 priority_(HIGHEST),
81 slot_(0), 80 slot_(0),
82 stalled_by_flow_control_(false), 81 stalled_by_flow_control_(false),
83 send_window_size_(kSpdyStreamInitialWindowSize), 82 send_window_size_(kSpdyStreamInitialWindowSize),
84 recv_window_size_(kSpdyStreamInitialWindowSize), 83 recv_window_size_(kSpdyStreamInitialWindowSize),
85 unacked_recv_window_bytes_(0), 84 unacked_recv_window_bytes_(0),
86 pushed_(pushed), 85 pushed_(pushed),
87 response_received_(false), 86 response_received_(false),
88 session_(session), 87 session_(session),
89 delegate_(NULL), 88 delegate_(NULL),
90 request_time_(base::Time::Now()), 89 request_time_(base::Time::Now()),
91 response_(new SpdyHeaderBlock), 90 response_(new SpdyHeaderBlock),
92 io_state_(STATE_NONE), 91 io_state_(STATE_NONE),
93 response_status_(OK), 92 response_status_(OK),
94 cancelled_(false), 93 cancelled_(false),
95 has_upload_data_(false), 94 has_upload_data_(false),
96 net_log_(net_log), 95 net_log_(net_log),
97 send_bytes_(0), 96 send_bytes_(0),
98 recv_bytes_(0), 97 recv_bytes_(0),
99 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { 98 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) {
100 } 99 }
101 100
101 class SpdyStream::SpdyStreamFrameProducer
102 : public SpdySession::SpdyFrameProducer {
103 public:
104 SpdyStreamFrameProducer(SpdyStream* stream) : stream_(stream) {}
105
106 // SpdyFrameProducer
107 virtual RequestPriority GetPriority() const OVERRIDE {
108 return stream_->priority();
109 }
110 virtual SpdyFrame* ProduceNextFrame(SpdySession* spdy_session) OVERRIDE {
111 if (stream_->stream_id() == 0)
112 ActivateStream(spdy_session, stream_);
113 return stream_->ProduceNextFrame();
114 }
115 virtual SpdyStream* GetSpdyStream() OVERRIDE {
116 return stream_.get();
117 }
118
119 private:
120 scoped_refptr<SpdyStream> stream_;
121
122 };
123
124 SpdySession::SpdyFrameProducer* SpdyStream::CreateProducer() {
125 return new SpdyStreamFrameProducer(this);
126 }
127
128 SpdyFrame* SpdyStream::ProduceNextFrame() {
129 if (io_state_ == STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE) {
130 CHECK(request_.get());
131 CHECK_GT(stream_id_, 0u);
132
133 std::string origin = GetUrl().GetOrigin().spec();
134 origin.erase(origin.length() - 1); // trim trailing slash
135 SpdyCredentialControlFrame* frame = session_->CreateCredentialFrame(
136 origin, domain_bound_cert_type_, domain_bound_private_key_,
137 domain_bound_cert_, priority_);
138 return frame;
139 } else if (io_state_ == STATE_SEND_HEADERS_COMPLETE) {
140 CHECK(request_.get());
141 CHECK_GT(stream_id_, 0u);
142
143 SpdyControlFlags flags =
144 has_upload_data_ ? CONTROL_FLAG_NONE : CONTROL_FLAG_FIN;
145 SpdySynStreamControlFrame* frame = session_->CreateSynStream(
146 stream_id_, priority_, slot_, flags, request_);
147 set_stream_id(frame->stream_id());
148 send_time_ = base::TimeTicks::Now();
149 return frame;
150 } else {
151 CHECK(!cancelled());
152 // We must need to write stream data.
153 // Until the headers have been completely sent, we can not be sure
154 // that our stream_id is correct.
155 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE);
156 DCHECK_GT(stream_id_, 0u);
157 DCHECK(!pending_data_frames_.empty());
158 SpdyFrame* frame = pending_data_frames_.front();
159 pending_data_frames_.pop_front();
160 return frame;
161 }
162 }
163
102 SpdyStream::~SpdyStream() { 164 SpdyStream::~SpdyStream() {
103 UpdateHistograms(); 165 UpdateHistograms();
166 while (!pending_data_frames_.empty()) {
167 SpdyFrame* frame = pending_data_frames_.back();
168 pending_data_frames_.pop_back();
169 delete frame;
170 }
104 } 171 }
105 172
106 void SpdyStream::SetDelegate(Delegate* delegate) { 173 void SpdyStream::SetDelegate(Delegate* delegate) {
107 CHECK(delegate); 174 CHECK(delegate);
108 delegate_ = delegate; 175 delegate_ = delegate;
109 176
110 if (pushed_) { 177 if (pushed_) {
111 CHECK(response_received()); 178 CHECK(response_received());
112 MessageLoop::current()->PostTask( 179 MessageLoop::current()->PostTask(
113 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this)); 180 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this));
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 void SpdyStream::Cancel() { 555 void SpdyStream::Cancel() {
489 if (cancelled()) 556 if (cancelled())
490 return; 557 return;
491 558
492 cancelled_ = true; 559 cancelled_ = true;
493 if (session_->IsStreamActive(stream_id_)) 560 if (session_->IsStreamActive(stream_id_))
494 session_->ResetStream(stream_id_, CANCEL, ""); 561 session_->ResetStream(stream_id_, CANCEL, "");
495 } 562 }
496 563
497 void SpdyStream::Close() { 564 void SpdyStream::Close() {
498 session_->CloseStream(stream_id_, net::OK); 565 if (stream_id_ != 0)
566 session_->CloseStream(stream_id_, net::OK);
567 else
568 session_->CloseCreatedStream(this, OK);
499 } 569 }
500 570
501 int SpdyStream::SendRequest(bool has_upload_data) { 571 int SpdyStream::SendRequest(bool has_upload_data) {
502 if (delegate_) 572 if (delegate_)
503 delegate_->set_chunk_callback(this); 573 delegate_->set_chunk_callback(this);
504 574
505 // Pushed streams do not send any data, and should always be in STATE_OPEN or 575 // Pushed streams do not send any data, and should always be in STATE_OPEN or
506 // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push 576 // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push
507 // behavior. 577 // behavior.
508 has_upload_data_ = has_upload_data; 578 has_upload_data_ = has_upload_data;
509 if (pushed_) { 579 if (pushed_) {
510 send_time_ = base::TimeTicks::Now(); 580 send_time_ = base::TimeTicks::Now();
511 DCHECK(!has_upload_data_); 581 DCHECK(!has_upload_data_);
512 DCHECK(response_received()); 582 DCHECK(response_received());
513 return ERR_IO_PENDING; 583 return ERR_IO_PENDING;
514 } 584 }
515 CHECK_EQ(STATE_NONE, io_state_); 585 CHECK_EQ(STATE_NONE, io_state_);
516 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; 586 io_state_ = STATE_GET_DOMAIN_BOUND_CERT;
517 return DoLoop(OK); 587 return DoLoop(OK);
518 } 588 }
519 589
520 int SpdyStream::WriteStreamData(IOBuffer* data, int length, 590 int SpdyStream::WriteStreamData(IOBuffer* data, int length,
521 SpdyDataFlags flags) { 591 SpdyDataFlags flags) {
522 // Until the headers have been completely sent, we can not be sure 592 // Until the headers have been completely sent, we can not be sure
523 // that our stream_id is correct. 593 // that our stream_id is correct.
524 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); 594 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE);
525 return session_->WriteStreamData(stream_id_, data, length, flags); 595 CHECK_GT(stream_id_, 0u);
596
597 pending_data_frames_.push_back(
598 session_->CreateDataFrame(stream_id_, data, length, flags));
599
600 session_->SetStreamHasWriteAvailable(this);
601 return ERR_IO_PENDING;
526 } 602 }
527 603
528 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, 604 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info,
529 bool* was_npn_negotiated, 605 bool* was_npn_negotiated,
530 NextProto* protocol_negotiated) { 606 NextProto* protocol_negotiated) {
531 return session_->GetSSLInfo( 607 return session_->GetSSLInfo(
532 ssl_info, was_npn_negotiated, protocol_negotiated); 608 ssl_info, was_npn_negotiated, protocol_negotiated);
533 } 609 }
534 610
535 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { 611 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) {
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 return result; 735 return result;
660 736
661 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; 737 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT;
662 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); 738 slot_ = session_->credential_state()->SetHasCredential(GetUrl());
663 return OK; 739 return OK;
664 } 740 }
665 741
666 int SpdyStream::DoSendDomainBoundCert() { 742 int SpdyStream::DoSendDomainBoundCert() {
667 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; 743 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE;
668 CHECK(request_.get()); 744 CHECK(request_.get());
669 std::string origin = GetUrl().GetOrigin().spec(); 745 session_->SetStreamHasWriteAvailable(this);
670 origin.erase(origin.length() - 1); // trim trailing slash 746 return ERR_IO_PENDING;
671 int rv = session_->WriteCredentialFrame(
672 origin, domain_bound_cert_type_, domain_bound_private_key_,
673 domain_bound_cert_, priority_);
674 if (rv != ERR_IO_PENDING)
675 return rv;
676 return OK;
677 } 747 }
678 748
679 int SpdyStream::DoSendDomainBoundCertComplete(int result) { 749 int SpdyStream::DoSendDomainBoundCertComplete(int result) {
680 if (result < 0) 750 if (result < 0)
681 return result; 751 return result;
682 752
683 io_state_ = STATE_SEND_HEADERS; 753 io_state_ = STATE_SEND_HEADERS;
684 return OK; 754 return OK;
685 } 755 }
686 756
687 int SpdyStream::DoSendHeaders() { 757 int SpdyStream::DoSendHeaders() {
688 CHECK(!cancelled_); 758 CHECK(!cancelled_);
689 759
690 SpdyControlFlags flags = CONTROL_FLAG_NONE; 760 session_->SetStreamHasWriteAvailable(this);
691 if (!has_upload_data_)
692 flags = CONTROL_FLAG_FIN;
693
694 CHECK(request_.get());
695 int result = session_->WriteSynStream(
696 stream_id_, priority_, slot_, flags,
697 request_);
698 if (result != ERR_IO_PENDING)
699 return result;
700
701 send_time_ = base::TimeTicks::Now();
702 io_state_ = STATE_SEND_HEADERS_COMPLETE; 761 io_state_ = STATE_SEND_HEADERS_COMPLETE;
703 return ERR_IO_PENDING; 762 return ERR_IO_PENDING;
704 } 763 }
705 764
706 int SpdyStream::DoSendHeadersComplete(int result) { 765 int SpdyStream::DoSendHeadersComplete(int result) {
707 if (result < 0) 766 if (result < 0)
708 return result; 767 return result;
709 768
710 CHECK_GT(result, 0); 769 CHECK_GT(result, 0);
711 770
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", 830 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime",
772 recv_last_byte_time_ - recv_first_byte_time_); 831 recv_last_byte_time_ - recv_first_byte_time_);
773 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", 832 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime",
774 recv_last_byte_time_ - send_time_); 833 recv_last_byte_time_ - send_time_);
775 834
776 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); 835 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_);
777 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); 836 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_);
778 } 837 }
779 838
780 } // namespace net 839 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698