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

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: Rebase 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
« 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 "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
101 };
102
103 SpdySession::SpdyIOBufferProducer* SpdyStream::CreateProducer() {
willchan no longer on Chromium 2012/06/26 17:07:27 I don't feel strongly. I don't really know why I f
Ryan Hamilton 2012/06/26 17:55:24 Done. Heh, fair enough. Both approaches work for
104 return new SpdyStreamIOBufferProducer(this);
105 }
106
107 SpdyFrame* SpdyStream::ProduceNextFrame() {
108 if (io_state_ == STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE) {
109 CHECK(request_.get());
110 CHECK_GT(stream_id_, 0u);
111
112 std::string origin = GetUrl().GetOrigin().spec();
113 origin.erase(origin.length() - 1); // trim trailing slash
114 SpdyCredentialControlFrame* frame = session_->CreateCredentialFrame(
115 origin, domain_bound_cert_type_, domain_bound_private_key_,
116 domain_bound_cert_, priority_);
117 return frame;
118 } else if (io_state_ == STATE_SEND_HEADERS_COMPLETE) {
119 CHECK(request_.get());
120 CHECK_GT(stream_id_, 0u);
121
122 SpdyControlFlags flags =
123 has_upload_data_ ? CONTROL_FLAG_NONE : CONTROL_FLAG_FIN;
124 SpdySynStreamControlFrame* frame = session_->CreateSynStream(
125 stream_id_, priority_, slot_, flags, request_);
126 set_stream_id(frame->stream_id());
127 send_time_ = base::TimeTicks::Now();
128 return frame;
129 } else {
130 CHECK(!cancelled());
131 // We must need to write stream data.
132 // Until the headers have been completely sent, we can not be sure
133 // that our stream_id is correct.
134 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE);
135 DCHECK_GT(stream_id_, 0u);
136 DCHECK(!pending_data_frames_.empty());
137 SpdyFrame* frame = pending_data_frames_.front();
138 pending_data_frames_.pop_front();
139 return frame;
140 }
141 }
142
80 SpdyStream::~SpdyStream() { 143 SpdyStream::~SpdyStream() {
81 UpdateHistograms(); 144 UpdateHistograms();
145 while (!pending_data_frames_.empty()) {
146 SpdyFrame* frame = pending_data_frames_.back();
147 pending_data_frames_.pop_back();
148 delete frame;
149 }
82 } 150 }
83 151
84 void SpdyStream::SetDelegate(Delegate* delegate) { 152 void SpdyStream::SetDelegate(Delegate* delegate) {
85 CHECK(delegate); 153 CHECK(delegate);
86 delegate_ = delegate; 154 delegate_ = delegate;
87 155
88 if (pushed_) { 156 if (pushed_) {
89 CHECK(response_received()); 157 CHECK(response_received());
90 MessageLoop::current()->PostTask( 158 MessageLoop::current()->PostTask(
91 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this)); 159 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this));
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 void SpdyStream::Cancel() { 533 void SpdyStream::Cancel() {
466 if (cancelled()) 534 if (cancelled())
467 return; 535 return;
468 536
469 cancelled_ = true; 537 cancelled_ = true;
470 if (session_->IsStreamActive(stream_id_)) 538 if (session_->IsStreamActive(stream_id_))
471 session_->ResetStream(stream_id_, CANCEL, ""); 539 session_->ResetStream(stream_id_, CANCEL, "");
472 } 540 }
473 541
474 void SpdyStream::Close() { 542 void SpdyStream::Close() {
475 session_->CloseStream(stream_id_, net::OK); 543 if (stream_id_ != 0)
544 session_->CloseStream(stream_id_, net::OK);
545 else
546 session_->CloseCreatedStream(this, OK);
476 } 547 }
477 548
478 int SpdyStream::SendRequest(bool has_upload_data) { 549 int SpdyStream::SendRequest(bool has_upload_data) {
479 if (delegate_) 550 if (delegate_)
480 delegate_->set_chunk_callback(this); 551 delegate_->set_chunk_callback(this);
481 552
482 // Pushed streams do not send any data, and should always be in STATE_OPEN or 553 // 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 554 // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push
484 // behavior. 555 // behavior.
485 has_upload_data_ = has_upload_data; 556 has_upload_data_ = has_upload_data;
486 if (pushed_) { 557 if (pushed_) {
487 send_time_ = base::TimeTicks::Now(); 558 send_time_ = base::TimeTicks::Now();
488 DCHECK(!has_upload_data_); 559 DCHECK(!has_upload_data_);
489 DCHECK(response_received()); 560 DCHECK(response_received());
490 return ERR_IO_PENDING; 561 return ERR_IO_PENDING;
491 } 562 }
492 CHECK_EQ(STATE_NONE, io_state_); 563 CHECK_EQ(STATE_NONE, io_state_);
493 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; 564 io_state_ = STATE_GET_DOMAIN_BOUND_CERT;
494 return DoLoop(OK); 565 return DoLoop(OK);
495 } 566 }
496 567
497 int SpdyStream::WriteStreamData(IOBuffer* data, int length, 568 int SpdyStream::WriteStreamData(IOBuffer* data, int length,
498 SpdyDataFlags flags) { 569 SpdyDataFlags flags) {
499 // Until the headers have been completely sent, we can not be sure 570 // Until the headers have been completely sent, we can not be sure
500 // that our stream_id is correct. 571 // that our stream_id is correct.
501 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); 572 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE);
502 return session_->WriteStreamData(stream_id_, data, length, flags); 573 CHECK_GT(stream_id_, 0u);
574
575 pending_data_frames_.push_back(
576 session_->CreateDataFrame(stream_id_, data, length, flags));
577
578 session_->SetStreamHasWriteAvailable(this);
579 return ERR_IO_PENDING;
503 } 580 }
504 581
505 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, 582 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info,
506 bool* was_npn_negotiated, 583 bool* was_npn_negotiated,
507 NextProto* protocol_negotiated) { 584 NextProto* protocol_negotiated) {
508 return session_->GetSSLInfo( 585 return session_->GetSSLInfo(
509 ssl_info, was_npn_negotiated, protocol_negotiated); 586 ssl_info, was_npn_negotiated, protocol_negotiated);
510 } 587 }
511 588
512 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { 589 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) {
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 return result; 713 return result;
637 714
638 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; 715 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT;
639 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); 716 slot_ = session_->credential_state()->SetHasCredential(GetUrl());
640 return OK; 717 return OK;
641 } 718 }
642 719
643 int SpdyStream::DoSendDomainBoundCert() { 720 int SpdyStream::DoSendDomainBoundCert() {
644 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; 721 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE;
645 CHECK(request_.get()); 722 CHECK(request_.get());
646 std::string origin = GetUrl().GetOrigin().spec(); 723 session_->SetStreamHasWriteAvailable(this);
647 origin.erase(origin.length() - 1); // trim trailing slash 724 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 } 725 }
655 726
656 int SpdyStream::DoSendDomainBoundCertComplete(int result) { 727 int SpdyStream::DoSendDomainBoundCertComplete(int result) {
657 if (result < 0) 728 if (result < 0)
658 return result; 729 return result;
659 730
660 io_state_ = STATE_SEND_HEADERS; 731 io_state_ = STATE_SEND_HEADERS;
661 return OK; 732 return OK;
662 } 733 }
663 734
664 int SpdyStream::DoSendHeaders() { 735 int SpdyStream::DoSendHeaders() {
665 CHECK(!cancelled_); 736 CHECK(!cancelled_);
666 737
667 SpdyControlFlags flags = CONTROL_FLAG_NONE; 738 session_->SetStreamHasWriteAvailable(this);
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; 739 io_state_ = STATE_SEND_HEADERS_COMPLETE;
680 return ERR_IO_PENDING; 740 return ERR_IO_PENDING;
681 } 741 }
682 742
683 int SpdyStream::DoSendHeadersComplete(int result) { 743 int SpdyStream::DoSendHeadersComplete(int result) {
684 if (result < 0) 744 if (result < 0)
685 return result; 745 return result;
686 746
687 CHECK_GT(result, 0); 747 CHECK_GT(result, 0);
688 748
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", 808 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime",
749 recv_last_byte_time_ - recv_first_byte_time_); 809 recv_last_byte_time_ - recv_first_byte_time_);
750 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", 810 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime",
751 recv_last_byte_time_ - send_time_); 811 recv_last_byte_time_ - send_time_);
752 812
753 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); 813 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_);
754 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); 814 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_);
755 } 815 }
756 816
757 } // namespace net 817 } // 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