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 |