| OLD | NEW |
| 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/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 io_state_(STATE_NONE), | 76 io_state_(STATE_NONE), |
| 77 response_status_(OK), | 77 response_status_(OK), |
| 78 cancelled_(false), | 78 cancelled_(false), |
| 79 has_upload_data_(false), | 79 has_upload_data_(false), |
| 80 net_log_(net_log), | 80 net_log_(net_log), |
| 81 send_bytes_(0), | 81 send_bytes_(0), |
| 82 recv_bytes_(0), | 82 recv_bytes_(0), |
| 83 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { | 83 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { |
| 84 } | 84 } |
| 85 | 85 |
| 86 class SpdyStream::SpdyStreamIOBufferProducer | 86 // A wrapper around a stream that calls into ProduceNextFrame(). |
| 87 : public SpdySession::SpdyIOBufferProducer { | 87 class SpdyStream::SpdyStreamFrameProducer : public SpdyFrameProducer { |
| 88 public: | 88 public: |
| 89 SpdyStreamIOBufferProducer(SpdyStream* stream) : stream_(stream) {} | 89 SpdyStreamFrameProducer(const scoped_refptr<SpdyStream>& stream) |
| 90 | 90 : stream_(stream) { |
| 91 // SpdyFrameProducer | 91 DCHECK(stream_); |
| 92 virtual RequestPriority GetPriority() const OVERRIDE { | |
| 93 return stream_->priority(); | |
| 94 } | 92 } |
| 95 | 93 |
| 96 virtual SpdyIOBuffer* ProduceNextBuffer(SpdySession* session) OVERRIDE { | 94 virtual ~SpdyStreamFrameProducer() {} |
| 97 if (stream_->cancelled()) | 95 |
| 98 return NULL; | 96 virtual SpdyStream* GetStream() OVERRIDE { |
| 99 if (stream_->stream_id() == 0) | 97 return stream_.get(); |
| 100 SpdySession::SpdyIOBufferProducer::ActivateStream(session, stream_); | 98 } |
| 101 frame_ = stream_->ProduceNextFrame(); | 99 |
| 102 return frame_ == NULL ? NULL : | 100 virtual scoped_ptr<SpdyFrame> ProduceFrame() OVERRIDE { |
| 103 SpdySession::SpdyIOBufferProducer::CreateIOBuffer( | 101 DCHECK_GT(stream_->stream_id(), 0u); |
| 104 frame_.get(), GetPriority(), stream_); | 102 return stream_->ProduceNextFrame(); |
| 105 } | 103 } |
| 106 | 104 |
| 107 private: | 105 private: |
| 108 scoped_refptr<SpdyStream> stream_; | 106 const scoped_refptr<SpdyStream> stream_; |
| 109 scoped_ptr<SpdyFrame> frame_; | |
| 110 }; | 107 }; |
| 111 | 108 |
| 112 void SpdyStream::SetHasWriteAvailable() { | 109 void SpdyStream::SetHasWriteAvailable() { |
| 113 session_->SetStreamHasWriteAvailable(this, | 110 session_->SetStreamHasWriteAvailable( |
| 114 new SpdyStreamIOBufferProducer(this)); | 111 this, |
| 112 scoped_ptr<SpdyFrameProducer>(new SpdyStreamFrameProducer(this))); |
| 115 } | 113 } |
| 116 | 114 |
| 117 scoped_ptr<SpdyFrame> SpdyStream::ProduceNextFrame() { | 115 scoped_ptr<SpdyFrame> SpdyStream::ProduceNextFrame() { |
| 118 if (io_state_ == STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE) { | 116 if (io_state_ == STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE) { |
| 119 CHECK(request_.get()); | 117 CHECK(request_.get()); |
| 120 CHECK_GT(stream_id_, 0u); | 118 CHECK_GT(stream_id_, 0u); |
| 121 | 119 |
| 122 std::string origin = GetUrl().GetOrigin().spec(); | 120 std::string origin = GetUrl().GetOrigin().spec(); |
| 123 DCHECK(origin[origin.length() - 1] == '/'); | 121 DCHECK(origin[origin.length() - 1] == '/'); |
| 124 origin.erase(origin.length() - 1); // Trim trailing slash. | 122 origin.erase(origin.length() - 1); // Trim trailing slash. |
| 125 scoped_ptr<SpdyFrame> frame(session_->CreateCredentialFrame( | 123 scoped_ptr<SpdyFrame> frame(session_->CreateCredentialFrame( |
| 126 origin, domain_bound_cert_type_, domain_bound_private_key_, | 124 origin, domain_bound_cert_type_, domain_bound_private_key_, |
| 127 domain_bound_cert_, priority_)); | 125 domain_bound_cert_, priority_)); |
| 128 return frame.Pass(); | 126 return frame.Pass(); |
| 129 } else if (io_state_ == STATE_SEND_HEADERS_COMPLETE) { | 127 } |
| 128 |
| 129 if (io_state_ == STATE_SEND_HEADERS_COMPLETE) { |
| 130 CHECK(request_.get()); | 130 CHECK(request_.get()); |
| 131 CHECK_GT(stream_id_, 0u); | 131 CHECK_GT(stream_id_, 0u); |
| 132 | 132 |
| 133 SpdyControlFlags flags = | 133 SpdyControlFlags flags = |
| 134 has_upload_data_ ? CONTROL_FLAG_NONE : CONTROL_FLAG_FIN; | 134 has_upload_data_ ? CONTROL_FLAG_NONE : CONTROL_FLAG_FIN; |
| 135 scoped_ptr<SpdyFrame> frame(session_->CreateSynStream( | 135 scoped_ptr<SpdyFrame> frame(session_->CreateSynStream( |
| 136 stream_id_, priority_, slot_, flags, *request_)); | 136 stream_id_, priority_, slot_, flags, *request_)); |
| 137 send_time_ = base::TimeTicks::Now(); | 137 send_time_ = base::TimeTicks::Now(); |
| 138 return frame.Pass(); | 138 return frame.Pass(); |
| 139 } else { | 139 } |
| 140 CHECK(!cancelled()); | |
| 141 // We must need to write stream data. | |
| 142 // Until the headers have been completely sent, we can not be sure | |
| 143 // that our stream_id is correct. | |
| 144 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); | |
| 145 DCHECK_GT(stream_id_, 0u); | |
| 146 DCHECK(!pending_frames_.empty()); | |
| 147 | 140 |
| 148 PendingFrame frame = pending_frames_.front(); | 141 CHECK(!cancelled()); |
| 149 pending_frames_.pop_front(); | 142 // We must need to write stream data. |
| 143 // Until the headers have been completely sent, we can not be sure |
| 144 // that our stream_id is correct. |
| 145 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); |
| 146 DCHECK_GT(stream_id_, 0u); |
| 147 DCHECK(!pending_frames_.empty()); |
| 150 | 148 |
| 151 waiting_completions_.push_back(frame.type); | 149 PendingFrame frame = pending_frames_.front(); |
| 150 pending_frames_.pop_front(); |
| 152 | 151 |
| 153 if (frame.type == TYPE_DATA) { | 152 waiting_completions_.push_back(frame.type); |
| 154 // Send queued data frame. | 153 |
| 155 return scoped_ptr<SpdyFrame>(frame.data_frame); | 154 if (frame.type == TYPE_DATA) { |
| 156 } else { | 155 // Send queued data frame. |
| 157 DCHECK(frame.type == TYPE_HEADERS); | 156 return scoped_ptr<SpdyFrame>(frame.data_frame); |
| 158 // Create actual HEADERS frame just in time because it depends on | |
| 159 // compression context and should not be reordered after the creation. | |
| 160 scoped_ptr<SpdyFrame> header_frame(session_->CreateHeadersFrame( | |
| 161 stream_id_, *frame.header_block, SpdyControlFlags())); | |
| 162 delete frame.header_block; | |
| 163 return header_frame.Pass(); | |
| 164 } | |
| 165 } | 157 } |
| 166 NOTREACHED(); | 158 |
| 159 DCHECK(frame.type == TYPE_HEADERS); |
| 160 // Create actual HEADERS frame just in time because it depends on |
| 161 // compression context and should not be reordered after the creation. |
| 162 scoped_ptr<SpdyFrame> header_frame(session_->CreateHeadersFrame( |
| 163 stream_id_, *frame.header_block, SpdyControlFlags())); |
| 164 delete frame.header_block; |
| 165 return header_frame.Pass(); |
| 167 } | 166 } |
| 168 | 167 |
| 169 SpdyStream::~SpdyStream() { | 168 SpdyStream::~SpdyStream() { |
| 170 UpdateHistograms(); | 169 UpdateHistograms(); |
| 171 while (!pending_frames_.empty()) { | 170 while (!pending_frames_.empty()) { |
| 172 PendingFrame frame = pending_frames_.back(); | 171 PendingFrame frame = pending_frames_.back(); |
| 173 pending_frames_.pop_back(); | 172 pending_frames_.pop_back(); |
| 174 if (frame.type == TYPE_DATA) | 173 if (frame.type == TYPE_DATA) |
| 175 delete frame.data_frame; | 174 delete frame.data_frame; |
| 176 else | 175 else |
| (...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 883 } | 882 } |
| 884 | 883 |
| 885 recv_window_size_ -= delta_window_size; | 884 recv_window_size_ -= delta_window_size; |
| 886 net_log_.AddEvent( | 885 net_log_.AddEvent( |
| 887 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW, | 886 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW, |
| 888 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, | 887 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, |
| 889 stream_id_, -delta_window_size, recv_window_size_)); | 888 stream_id_, -delta_window_size, recv_window_size_)); |
| 890 } | 889 } |
| 891 | 890 |
| 892 } // namespace net | 891 } // namespace net |
| OLD | NEW |