blob: 18d20e8d3a46eecc6b7ec889ea2832c94b45f8ac [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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
3// found in the LICENSE file.
4
5#include "net/spdy/spdy_stream.h"
6
7#include "base/bind.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008#include "base/compiler_specific.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009#include "base/logging.h"
Ben Murdoch9ab55632013-07-18 11:57:30 +010010#include "base/message_loop/message_loop.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010011#include "base/strings/string_number_conversions.h"
Ben Murdoch9ab55632013-07-18 11:57:30 +010012#include "base/strings/stringprintf.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000013#include "base/values.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010014#include "net/spdy/spdy_buffer_producer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000015#include "net/spdy/spdy_http_utils.h"
16#include "net/spdy/spdy_session.h"
17
18namespace net {
19
20namespace {
21
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010022base::Value* NetLogSpdyStreamErrorCallback(SpdyStreamId stream_id,
23 int status,
24 const std::string* description,
25 NetLog::LogLevel /* log_level */) {
26 base::DictionaryValue* dict = new base::DictionaryValue();
Torne (Richard Coles)58218062012-11-14 11:43:16 +000027 dict->SetInteger("stream_id", static_cast<int>(stream_id));
28 dict->SetInteger("status", status);
29 dict->SetString("description", *description);
30 return dict;
31}
32
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010033base::Value* NetLogSpdyStreamWindowUpdateCallback(
34 SpdyStreamId stream_id,
35 int32 delta,
36 int32 window_size,
37 NetLog::LogLevel /* log_level */) {
38 base::DictionaryValue* dict = new base::DictionaryValue();
Torne (Richard Coles)58218062012-11-14 11:43:16 +000039 dict->SetInteger("stream_id", stream_id);
40 dict->SetInteger("delta", delta);
41 dict->SetInteger("window_size", window_size);
42 return dict;
43}
44
Ben Murdocheb525c52013-07-10 11:40:50 +010045bool ContainsUppercaseAscii(const std::string& str) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000046 for (std::string::const_iterator i(str.begin()); i != str.end(); ++i) {
47 if (*i >= 'A' && *i <= 'Z') {
48 return true;
49 }
50 }
51 return false;
52}
53
54} // namespace
55
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010056// A wrapper around a stream that calls into ProduceSynStreamFrame().
57class SpdyStream::SynStreamBufferProducer : public SpdyBufferProducer {
58 public:
59 SynStreamBufferProducer(const base::WeakPtr<SpdyStream>& stream)
60 : stream_(stream) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010061 DCHECK(stream_.get());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010062 }
63
64 virtual ~SynStreamBufferProducer() {}
65
66 virtual scoped_ptr<SpdyBuffer> ProduceBuffer() OVERRIDE {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010067 if (!stream_.get()) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010068 NOTREACHED();
69 return scoped_ptr<SpdyBuffer>();
70 }
71 DCHECK_GT(stream_->stream_id(), 0u);
72 return scoped_ptr<SpdyBuffer>(
73 new SpdyBuffer(stream_->ProduceSynStreamFrame()));
74 }
75
76 private:
77 const base::WeakPtr<SpdyStream> stream_;
78};
79
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010080SpdyStream::SpdyStream(SpdyStreamType type,
Ben Murdochca12bfa2013-07-23 11:17:05 +010081 const base::WeakPtr<SpdySession>& session,
82 const GURL& url,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000083 RequestPriority priority,
84 int32 initial_send_window_size,
85 int32 initial_recv_window_size,
Torne (Richard Coles)58218062012-11-14 11:43:16 +000086 const BoundNetLog& net_log)
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010087 : type_(type),
88 weak_ptr_factory_(this),
89 in_do_loop_(false),
Ben Murdocheb525c52013-07-10 11:40:50 +010090 continue_buffering_data_(type_ == SPDY_PUSH_STREAM),
Torne (Richard Coles)58218062012-11-14 11:43:16 +000091 stream_id_(0),
Ben Murdochca12bfa2013-07-23 11:17:05 +010092 url_(url),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000093 priority_(priority),
Torne (Richard Coles)58218062012-11-14 11:43:16 +000094 slot_(0),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000095 send_stalled_by_flow_control_(false),
96 send_window_size_(initial_send_window_size),
97 recv_window_size_(initial_recv_window_size),
Torne (Richard Coles)58218062012-11-14 11:43:16 +000098 unacked_recv_window_bytes_(0),
Torne (Richard Coles)58218062012-11-14 11:43:16 +000099 session_(session),
100 delegate_(NULL),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100101 send_status_(
102 (type_ == SPDY_PUSH_STREAM) ?
103 NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000104 request_time_(base::Time::Now()),
Ben Murdocheb525c52013-07-10 11:40:50 +0100105 response_headers_status_(RESPONSE_HEADERS_ARE_INCOMPLETE),
106 io_state_((type_ == SPDY_PUSH_STREAM) ? STATE_IDLE : STATE_NONE),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000107 response_status_(OK),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000108 net_log_(net_log),
109 send_bytes_(0),
110 recv_bytes_(0),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100111 just_completed_frame_type_(DATA),
112 just_completed_frame_size_(0) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100113 CHECK(type_ == SPDY_BIDIRECTIONAL_STREAM ||
114 type_ == SPDY_REQUEST_RESPONSE_STREAM ||
115 type_ == SPDY_PUSH_STREAM);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000116}
117
118SpdyStream::~SpdyStream() {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100119 CHECK(!in_do_loop_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000120 UpdateHistograms();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000121}
122
123void SpdyStream::SetDelegate(Delegate* delegate) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100124 CHECK(!delegate_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000125 CHECK(delegate);
126 delegate_ = delegate;
127
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100128 if (type_ == SPDY_PUSH_STREAM) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100129 DCHECK(continue_buffering_data_);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100130 base::MessageLoop::current()->PostTask(
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100131 FROM_HERE,
132 base::Bind(&SpdyStream::PushedStreamReplayData, GetWeakPtr()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000133 }
134}
135
Ben Murdocheb525c52013-07-10 11:40:50 +0100136void SpdyStream::PushedStreamReplayData() {
137 DCHECK_EQ(type_, SPDY_PUSH_STREAM);
138 DCHECK_NE(stream_id_, 0u);
139 DCHECK(continue_buffering_data_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000140
141 continue_buffering_data_ = false;
142
Ben Murdocheb525c52013-07-10 11:40:50 +0100143 // The delegate methods called below may delete |this|, so use
144 // |weak_this| to detect that.
145 base::WeakPtr<SpdyStream> weak_this = GetWeakPtr();
146
147 CHECK(delegate_);
148 SpdyResponseHeadersStatus status =
149 delegate_->OnResponseHeadersUpdated(response_headers_);
150 if (status == RESPONSE_HEADERS_ARE_INCOMPLETE) {
151 // Since RESPONSE_HEADERS_ARE_INCOMPLETE was returned, we must not
152 // have been closed. Since we don't have complete headers, assume
153 // we're waiting for another HEADERS frame, and we had better not
154 // have any pending data frames.
155 CHECK(weak_this);
156 if (!pending_buffers_.empty()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000157 LogStreamError(ERR_SPDY_PROTOCOL_ERROR,
Ben Murdocheb525c52013-07-10 11:40:50 +0100158 "Data received with incomplete headers.");
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100159 session_->CloseActiveStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000160 }
161 return;
162 }
163
Ben Murdocheb525c52013-07-10 11:40:50 +0100164 // OnResponseHeadersUpdated() may have closed |this|.
165 if (!weak_this)
166 return;
167
168 response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE;
169
170 while (!pending_buffers_.empty()) {
171 // Take ownership of the first element of |pending_buffers_|.
172 scoped_ptr<SpdyBuffer> buffer(pending_buffers_.front());
173 pending_buffers_.weak_erase(pending_buffers_.begin());
174
175 bool eof = (buffer == NULL);
176
177 CHECK(delegate_);
178 delegate_->OnDataReceived(buffer.Pass());
179
180 // OnDataReceived() may have closed |this|.
181 if (!weak_this)
182 return;
183
184 if (eof) {
185 DCHECK(pending_buffers_.empty());
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100186 session_->CloseActiveStream(stream_id_, OK);
Ben Murdocheb525c52013-07-10 11:40:50 +0100187 DCHECK(!weak_this);
188 // |pending_buffers_| is invalid at this point.
189 break;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000190 }
191 }
192}
193
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100194scoped_ptr<SpdyFrame> SpdyStream::ProduceSynStreamFrame() {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100195 CHECK_EQ(io_state_, STATE_SEND_REQUEST_HEADERS_COMPLETE);
Ben Murdocheb525c52013-07-10 11:40:50 +0100196 CHECK(request_headers_);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100197 CHECK_GT(stream_id_, 0u);
198
199 SpdyControlFlags flags =
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100200 (send_status_ == NO_MORE_DATA_TO_SEND) ?
201 CONTROL_FLAG_FIN : CONTROL_FLAG_NONE;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100202 scoped_ptr<SpdyFrame> frame(session_->CreateSynStream(
Ben Murdocheb525c52013-07-10 11:40:50 +0100203 stream_id_, priority_, slot_, flags, *request_headers_));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100204 send_time_ = base::TimeTicks::Now();
205 return frame.Pass();
206}
207
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000208void SpdyStream::DetachDelegate() {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100209 CHECK(!in_do_loop_);
Ben Murdocheb525c52013-07-10 11:40:50 +0100210 DCHECK(!IsClosed());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000211 delegate_ = NULL;
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100212 Cancel();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000213}
214
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000215void SpdyStream::AdjustSendWindowSize(int32 delta_window_size) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000216 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM);
217
Ben Murdocheb525c52013-07-10 11:40:50 +0100218 if (IsClosed())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000219 return;
220
221 // Check for wraparound.
222 if (send_window_size_ > 0) {
223 DCHECK_LE(delta_window_size, kint32max - send_window_size_);
224 }
225 if (send_window_size_ < 0) {
226 DCHECK_GE(delta_window_size, kint32min - send_window_size_);
227 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000228 send_window_size_ += delta_window_size;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000229 PossiblyResumeIfSendStalled();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000230}
231
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100232void SpdyStream::OnWriteBufferConsumed(
233 size_t frame_payload_size,
234 size_t consume_size,
235 SpdyBuffer::ConsumeSource consume_source) {
236 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM);
237 if (consume_source == SpdyBuffer::DISCARD) {
238 // If we're discarding a frame or part of it, increase the send
239 // window by the number of discarded bytes. (Although if we're
240 // discarding part of a frame, it's probably because of a write
241 // error and we'll be tearing down the stream soon.)
242 size_t remaining_payload_bytes = std::min(consume_size, frame_payload_size);
243 DCHECK_GT(remaining_payload_bytes, 0u);
244 IncreaseSendWindowSize(static_cast<int32>(remaining_payload_bytes));
245 }
246 // For consumed bytes, the send window is increased when we receive
247 // a WINDOW_UPDATE frame.
248}
249
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000250void SpdyStream::IncreaseSendWindowSize(int32 delta_window_size) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000251 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100252 DCHECK_GE(delta_window_size, 1);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000253
254 // Ignore late WINDOW_UPDATEs.
Ben Murdocheb525c52013-07-10 11:40:50 +0100255 if (IsClosed())
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000256 return;
257
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000258 if (send_window_size_ > 0) {
259 // Check for overflow.
260 int32 max_delta_window_size = kint32max - send_window_size_;
261 if (delta_window_size > max_delta_window_size) {
262 std::string desc = base::StringPrintf(
263 "Received WINDOW_UPDATE [delta: %d] for stream %d overflows "
264 "send_window_size_ [current: %d]", delta_window_size, stream_id_,
265 send_window_size_);
Ben Murdocheb525c52013-07-10 11:40:50 +0100266 session_->ResetStream(stream_id_, RST_STREAM_FLOW_CONTROL_ERROR, desc);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000267 return;
268 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000269 }
270
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000271 send_window_size_ += delta_window_size;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000272
273 net_log_.AddEvent(
274 NetLog::TYPE_SPDY_STREAM_UPDATE_SEND_WINDOW,
275 base::Bind(&NetLogSpdyStreamWindowUpdateCallback,
276 stream_id_, delta_window_size, send_window_size_));
277
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000278 PossiblyResumeIfSendStalled();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000279}
280
281void SpdyStream::DecreaseSendWindowSize(int32 delta_window_size) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000282 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM);
283
Ben Murdocheb525c52013-07-10 11:40:50 +0100284 if (IsClosed())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000285 return;
286
287 // We only call this method when sending a frame. Therefore,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000288 // |delta_window_size| should be within the valid frame size range.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100289 DCHECK_GE(delta_window_size, 1);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000290 DCHECK_LE(delta_window_size, kMaxSpdyFrameChunkSize);
291
292 // |send_window_size_| should have been at least |delta_window_size| for
293 // this call to happen.
294 DCHECK_GE(send_window_size_, delta_window_size);
295
296 send_window_size_ -= delta_window_size;
297
298 net_log_.AddEvent(
299 NetLog::TYPE_SPDY_STREAM_UPDATE_SEND_WINDOW,
300 base::Bind(&NetLogSpdyStreamWindowUpdateCallback,
301 stream_id_, -delta_window_size, send_window_size_));
302}
303
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100304void SpdyStream::OnReadBufferConsumed(
305 size_t consume_size,
306 SpdyBuffer::ConsumeSource consume_source) {
307 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM);
308 DCHECK_GE(consume_size, 1u);
309 DCHECK_LE(consume_size, static_cast<size_t>(kint32max));
310 IncreaseRecvWindowSize(static_cast<int32>(consume_size));
311}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000312
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100313void SpdyStream::IncreaseRecvWindowSize(int32 delta_window_size) {
314 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000315
316 // By the time a read is processed by the delegate, this stream may
317 // already be inactive.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000318 if (!session_->IsStreamActive(stream_id_))
319 return;
320
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000321 DCHECK_GE(unacked_recv_window_bytes_, 0);
322 DCHECK_GE(recv_window_size_, unacked_recv_window_bytes_);
323 DCHECK_GE(delta_window_size, 1);
324 // Check for overflow.
325 DCHECK_LE(delta_window_size, kint32max - recv_window_size_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000326
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000327 recv_window_size_ += delta_window_size;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000328 net_log_.AddEvent(
329 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW,
330 base::Bind(&NetLogSpdyStreamWindowUpdateCallback,
331 stream_id_, delta_window_size, recv_window_size_));
332
333 unacked_recv_window_bytes_ += delta_window_size;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000334 if (unacked_recv_window_bytes_ >
335 session_->stream_initial_recv_window_size() / 2) {
336 session_->SendStreamWindowUpdate(
337 stream_id_, static_cast<uint32>(unacked_recv_window_bytes_));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000338 unacked_recv_window_bytes_ = 0;
339 }
340}
341
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100342void SpdyStream::DecreaseRecvWindowSize(int32 delta_window_size) {
343 DCHECK(session_->IsStreamActive(stream_id_));
344 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM);
345 DCHECK_GE(delta_window_size, 1);
346
347 // Since we never decrease the initial receive window size,
348 // |delta_window_size| should never cause |recv_window_size_| to go
349 // negative. If we do, the receive window isn't being respected.
350 if (delta_window_size > recv_window_size_) {
351 session_->ResetStream(
Ben Murdocheb525c52013-07-10 11:40:50 +0100352 stream_id_, RST_STREAM_PROTOCOL_ERROR,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100353 "delta_window_size is " + base::IntToString(delta_window_size) +
354 " in DecreaseRecvWindowSize, which is larger than the receive " +
355 "window size of " + base::IntToString(recv_window_size_));
356 return;
357 }
358
359 recv_window_size_ -= delta_window_size;
360 net_log_.AddEvent(
361 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW,
362 base::Bind(&NetLogSpdyStreamWindowUpdateCallback,
363 stream_id_, -delta_window_size, recv_window_size_));
364}
365
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000366int SpdyStream::GetPeerAddress(IPEndPoint* address) const {
367 return session_->GetPeerAddress(address);
368}
369
370int SpdyStream::GetLocalAddress(IPEndPoint* address) const {
371 return session_->GetLocalAddress(address);
372}
373
374bool SpdyStream::WasEverUsed() const {
375 return session_->WasEverUsed();
376}
377
378base::Time SpdyStream::GetRequestTime() const {
379 return request_time_;
380}
381
382void SpdyStream::SetRequestTime(base::Time t) {
383 request_time_ = t;
384}
385
Ben Murdocheb525c52013-07-10 11:40:50 +0100386int SpdyStream::OnInitialResponseHeadersReceived(
387 const SpdyHeaderBlock& initial_response_headers,
388 base::Time response_time,
389 base::TimeTicks recv_first_byte_time) {
390 // SpdySession guarantees that this is called at most once.
391 CHECK(response_headers_.empty());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000392
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100393 // Check to make sure that we don't receive the response headers
394 // before we're ready for it.
395 switch (type_) {
396 case SPDY_BIDIRECTIONAL_STREAM:
397 // For a bidirectional stream, we're ready for the response
398 // headers once we've finished sending the request headers.
Ben Murdocheb525c52013-07-10 11:40:50 +0100399 if (io_state_ < STATE_IDLE) {
400 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
401 "Response received before request sent");
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100402 return ERR_SPDY_PROTOCOL_ERROR;
Ben Murdocheb525c52013-07-10 11:40:50 +0100403 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100404 break;
405
406 case SPDY_REQUEST_RESPONSE_STREAM:
407 // For a request/response stream, we're ready for the response
408 // headers once we've finished sending the request headers and
409 // the request body (if we have one).
Ben Murdocheb525c52013-07-10 11:40:50 +0100410 if ((io_state_ < STATE_IDLE) || (send_status_ == MORE_DATA_TO_SEND) ||
411 pending_send_data_.get()) {
412 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
413 "Response received before request sent");
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100414 return ERR_SPDY_PROTOCOL_ERROR;
Ben Murdocheb525c52013-07-10 11:40:50 +0100415 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100416 break;
417
418 case SPDY_PUSH_STREAM:
419 // For a push stream, we're ready immediately.
420 DCHECK_EQ(send_status_, NO_MORE_DATA_TO_SEND);
Ben Murdocheb525c52013-07-10 11:40:50 +0100421 DCHECK_EQ(io_state_, STATE_IDLE);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100422 break;
423 }
424
Ben Murdocheb525c52013-07-10 11:40:50 +0100425 metrics_.StartStream();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100426
Ben Murdocheb525c52013-07-10 11:40:50 +0100427 DCHECK_EQ(io_state_, STATE_IDLE);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000428
Ben Murdocheb525c52013-07-10 11:40:50 +0100429 response_time_ = response_time;
430 recv_first_byte_time_ = recv_first_byte_time;
431 return MergeWithResponseHeaders(initial_response_headers);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000432}
433
Ben Murdocheb525c52013-07-10 11:40:50 +0100434int SpdyStream::OnAdditionalResponseHeadersReceived(
435 const SpdyHeaderBlock& additional_response_headers) {
436 if (type_ == SPDY_REQUEST_RESPONSE_STREAM) {
437 session_->ResetStream(
438 stream_id_, RST_STREAM_PROTOCOL_ERROR,
439 "Additional headers received for request/response stream");
440 return ERR_SPDY_PROTOCOL_ERROR;
441 } else if (type_ == SPDY_PUSH_STREAM &&
442 response_headers_status_ == RESPONSE_HEADERS_ARE_COMPLETE) {
443 session_->ResetStream(
444 stream_id_, RST_STREAM_PROTOCOL_ERROR,
445 "Additional headers received for push stream");
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000446 return ERR_SPDY_PROTOCOL_ERROR;
447 }
Ben Murdocheb525c52013-07-10 11:40:50 +0100448 return MergeWithResponseHeaders(additional_response_headers);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000449}
450
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100451void SpdyStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000452 DCHECK(session_->IsStreamActive(stream_id_));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000453
Ben Murdocheb525c52013-07-10 11:40:50 +0100454 // If we're still buffering data for a push stream, we will do the
455 // check for data received with incomplete headers in
456 // PushedStreamReplayData().
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000457 if (!delegate_ || continue_buffering_data_) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100458 DCHECK_EQ(type_, SPDY_PUSH_STREAM);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000459 // It should be valid for this to happen in the server push case.
460 // We'll return received data when delegate gets attached to the stream.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100461 if (buffer) {
462 pending_buffers_.push_back(buffer.release());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000463 } else {
464 pending_buffers_.push_back(NULL);
465 metrics_.StopStream();
466 // Note: we leave the stream open in the session until the stream
467 // is claimed.
468 }
469 return;
470 }
471
Ben Murdocheb525c52013-07-10 11:40:50 +0100472 // If we have response headers but the delegate has indicated that
473 // it's still incomplete, then that's a protocol error.
474 if (response_headers_status_ == RESPONSE_HEADERS_ARE_INCOMPLETE) {
475 LogStreamError(ERR_SPDY_PROTOCOL_ERROR,
476 "Data received with incomplete headers.");
477 session_->CloseActiveStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR);
478 return;
479 }
480
481 CHECK(!IsClosed());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000482
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100483 if (!buffer) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000484 metrics_.StopStream();
Ben Murdocheb525c52013-07-10 11:40:50 +0100485 // Deletes |this|.
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100486 session_->CloseActiveStream(stream_id_, OK);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000487 return;
488 }
489
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100490 size_t length = buffer->GetRemainingSize();
491 DCHECK_LE(length, session_->GetDataFrameMaximumPayload());
492 if (session_->flow_control_state() >= SpdySession::FLOW_CONTROL_STREAM) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000493 DecreaseRecvWindowSize(static_cast<int32>(length));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100494 buffer->AddConsumeCallback(
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100495 base::Bind(&SpdyStream::OnReadBufferConsumed, GetWeakPtr()));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100496 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000497
498 // Track our bandwidth.
499 metrics_.RecordBytes(length);
500 recv_bytes_ += length;
501 recv_last_byte_time_ = base::TimeTicks::Now();
502
Ben Murdocheb525c52013-07-10 11:40:50 +0100503 // May close |this|.
504 delegate_->OnDataReceived(buffer.Pass());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000505}
506
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100507void SpdyStream::OnFrameWriteComplete(SpdyFrameType frame_type,
508 size_t frame_size) {
509 if (frame_size < session_->GetFrameMinimumSize() ||
510 frame_size > session_->GetFrameMaximumSize()) {
511 NOTREACHED();
512 return;
513 }
Ben Murdocheb525c52013-07-10 11:40:50 +0100514 if (IsClosed())
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000515 return;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100516 just_completed_frame_type_ = frame_type;
517 just_completed_frame_size_ = frame_size;
518 DoLoop(OK);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000519}
520
521int SpdyStream::GetProtocolVersion() const {
522 return session_->GetProtocolVersion();
523}
524
525void SpdyStream::LogStreamError(int status, const std::string& description) {
526 net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ERROR,
527 base::Bind(&NetLogSpdyStreamErrorCallback,
528 stream_id_, status, &description));
529}
530
531void SpdyStream::OnClose(int status) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100532 CHECK(!in_do_loop_);
Ben Murdocheb525c52013-07-10 11:40:50 +0100533 io_state_ = STATE_CLOSED;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000534 response_status_ = status;
535 Delegate* delegate = delegate_;
536 delegate_ = NULL;
537 if (delegate)
538 delegate->OnClose(status);
Ben Murdocheb525c52013-07-10 11:40:50 +0100539 // Unset |stream_id_| last so that the delegate can look it up.
540 stream_id_ = 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000541}
542
543void SpdyStream::Cancel() {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100544 CHECK(!in_do_loop_);
Ben Murdocheb525c52013-07-10 11:40:50 +0100545 // We may be called again from a delegate's OnClose().
546 if (io_state_ == STATE_CLOSED)
547 return;
548
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100549 if (stream_id_ != 0) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100550 session_->ResetStream(stream_id_, RST_STREAM_CANCEL, std::string());
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100551 } else {
552 session_->CloseCreatedStream(GetWeakPtr(), RST_STREAM_CANCEL);
553 }
Ben Murdocheb525c52013-07-10 11:40:50 +0100554 // |this| is invalid at this point.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000555}
556
557void SpdyStream::Close() {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100558 CHECK(!in_do_loop_);
Ben Murdocheb525c52013-07-10 11:40:50 +0100559 // We may be called again from a delegate's OnClose().
560 if (io_state_ == STATE_CLOSED)
561 return;
562
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100563 if (stream_id_ != 0) {
564 session_->CloseActiveStream(stream_id_, OK);
565 } else {
566 session_->CloseCreatedStream(GetWeakPtr(), OK);
567 }
Ben Murdocheb525c52013-07-10 11:40:50 +0100568 // |this| is invalid at this point.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000569}
570
Ben Murdocheb525c52013-07-10 11:40:50 +0100571base::WeakPtr<SpdyStream> SpdyStream::GetWeakPtr() {
572 return weak_ptr_factory_.GetWeakPtr();
573}
574
575int SpdyStream::SendRequestHeaders(scoped_ptr<SpdyHeaderBlock> request_headers,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100576 SpdySendStatus send_status) {
577 CHECK_NE(type_, SPDY_PUSH_STREAM);
578 CHECK_EQ(send_status_, MORE_DATA_TO_SEND);
Ben Murdocheb525c52013-07-10 11:40:50 +0100579 CHECK(!request_headers_);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100580 CHECK(!pending_send_data_.get());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100581 CHECK_EQ(io_state_, STATE_NONE);
Ben Murdocheb525c52013-07-10 11:40:50 +0100582 request_headers_ = request_headers.Pass();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100583 send_status_ = send_status;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000584 io_state_ = STATE_GET_DOMAIN_BOUND_CERT;
585 return DoLoop(OK);
586}
587
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100588void SpdyStream::SendData(IOBuffer* data,
589 int length,
590 SpdySendStatus send_status) {
591 CHECK_NE(type_, SPDY_PUSH_STREAM);
592 CHECK_EQ(send_status_, MORE_DATA_TO_SEND);
593 CHECK_GE(io_state_, STATE_SEND_REQUEST_HEADERS_COMPLETE);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100594 CHECK(!pending_send_data_.get());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100595 pending_send_data_ = new DrainableIOBuffer(data, length);
596 send_status_ = send_status;
597 QueueNextDataFrame();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000598}
599
600bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info,
601 bool* was_npn_negotiated,
602 NextProto* protocol_negotiated) {
603 return session_->GetSSLInfo(
604 ssl_info, was_npn_negotiated, protocol_negotiated);
605}
606
607bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) {
608 return session_->GetSSLCertRequestInfo(cert_request_info);
609}
610
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000611void SpdyStream::PossiblyResumeIfSendStalled() {
Ben Murdocheb525c52013-07-10 11:40:50 +0100612 DCHECK(!IsClosed());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000613
614 if (send_stalled_by_flow_control_ && !session_->IsSendStalled() &&
615 send_window_size_ > 0) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100616 net_log_.AddEvent(
617 NetLog::TYPE_SPDY_STREAM_FLOW_CONTROL_UNSTALLED,
618 NetLog::IntegerCallback("stream_id", stream_id_));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000619 send_stalled_by_flow_control_ = false;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100620 QueueNextDataFrame();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000621 }
622}
623
Ben Murdocheb525c52013-07-10 11:40:50 +0100624bool SpdyStream::IsClosed() const {
625 return io_state_ == STATE_CLOSED;
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100626}
627
Ben Murdocheb525c52013-07-10 11:40:50 +0100628bool SpdyStream::IsIdle() const {
629 return io_state_ == STATE_IDLE;
630}
631
Ben Murdoch558790d2013-07-30 15:19:42 +0100632NextProto SpdyStream::GetProtocol() const {
633 return session_->protocol();
634}
635
Ben Murdocheb525c52013-07-10 11:40:50 +0100636bool SpdyStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
637 if (stream_id_ == 0)
638 return false;
639
640 return session_->GetLoadTimingInfo(stream_id_, load_timing_info);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000641}
642
Ben Murdochca12bfa2013-07-23 11:17:05 +0100643GURL SpdyStream::GetUrlFromHeaders() const {
Ben Murdocheb525c52013-07-10 11:40:50 +0100644 if (type_ != SPDY_PUSH_STREAM && !request_headers_)
645 return GURL();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000646
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100647 const SpdyHeaderBlock& headers =
Ben Murdocheb525c52013-07-10 11:40:50 +0100648 (type_ == SPDY_PUSH_STREAM) ? response_headers_ : *request_headers_;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100649 return GetUrlFromHeaderBlock(headers, GetProtocolVersion(),
650 type_ == SPDY_PUSH_STREAM);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000651}
652
Ben Murdochca12bfa2013-07-23 11:17:05 +0100653bool SpdyStream::HasUrlFromHeaders() const {
654 return !GetUrlFromHeaders().is_empty();
Ben Murdocheb525c52013-07-10 11:40:50 +0100655}
656
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000657void SpdyStream::OnGetDomainBoundCertComplete(int result) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100658 DCHECK_EQ(io_state_, STATE_GET_DOMAIN_BOUND_CERT_COMPLETE);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000659 DoLoop(result);
660}
661
662int SpdyStream::DoLoop(int result) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100663 CHECK(!in_do_loop_);
664 in_do_loop_ = true;
665
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000666 do {
667 State state = io_state_;
668 io_state_ = STATE_NONE;
669 switch (state) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000670 case STATE_GET_DOMAIN_BOUND_CERT:
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100671 CHECK_EQ(result, OK);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000672 result = DoGetDomainBoundCert();
673 break;
674 case STATE_GET_DOMAIN_BOUND_CERT_COMPLETE:
675 result = DoGetDomainBoundCertComplete(result);
676 break;
677 case STATE_SEND_DOMAIN_BOUND_CERT:
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100678 CHECK_EQ(result, OK);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000679 result = DoSendDomainBoundCert();
680 break;
681 case STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE:
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100682 result = DoSendDomainBoundCertComplete(result);
683 break;
684 case STATE_SEND_REQUEST_HEADERS:
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100685 CHECK_EQ(result, OK);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100686 result = DoSendRequestHeaders();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000687 break;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100688 case STATE_SEND_REQUEST_HEADERS_COMPLETE:
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100689 CHECK_EQ(result, OK);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100690 result = DoSendRequestHeadersComplete();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000691 break;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100692
693 // For request/response streams, no data is sent from the client
694 // while in the OPEN state, so OnFrameWriteComplete is never
695 // called here. The HTTP body is handled in the OnDataReceived
696 // callback, which does not call into DoLoop.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000697 //
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100698 // For bidirectional streams, we'll send and receive data once
699 // the connection is established. Received data is handled in
700 // OnDataReceived. Sent data is handled in
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100701 // OnFrameWriteComplete, which calls DoOpen().
Ben Murdocheb525c52013-07-10 11:40:50 +0100702 case STATE_IDLE:
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100703 CHECK_EQ(result, OK);
704 result = DoOpen();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000705 break;
706
Ben Murdocheb525c52013-07-10 11:40:50 +0100707 case STATE_CLOSED:
708 DCHECK_NE(result, ERR_IO_PENDING);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000709 break;
710 default:
711 NOTREACHED() << io_state_;
712 break;
713 }
714 } while (result != ERR_IO_PENDING && io_state_ != STATE_NONE &&
Ben Murdocheb525c52013-07-10 11:40:50 +0100715 io_state_ != STATE_IDLE);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000716
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100717 CHECK(in_do_loop_);
718 in_do_loop_ = false;
719
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000720 return result;
721}
722
723int SpdyStream::DoGetDomainBoundCert() {
Ben Murdocheb525c52013-07-10 11:40:50 +0100724 CHECK(request_headers_);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100725 DCHECK_NE(type_, SPDY_PUSH_STREAM);
Ben Murdochca12bfa2013-07-23 11:17:05 +0100726 GURL url = GetUrlFromHeaders();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100727 if (!session_->NeedsCredentials() || !url.SchemeIs("https")) {
728 // Proceed directly to sending the request headers
729 io_state_ = STATE_SEND_REQUEST_HEADERS;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000730 return OK;
731 }
732
Ben Murdochca12bfa2013-07-23 11:17:05 +0100733 slot_ = session_->credential_state()->FindCredentialSlot(GetUrlFromHeaders());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000734 if (slot_ != SpdyCredentialState::kNoEntry) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100735 // Proceed directly to sending the request headers
736 io_state_ = STATE_SEND_REQUEST_HEADERS;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000737 return OK;
738 }
739
740 io_state_ = STATE_GET_DOMAIN_BOUND_CERT_COMPLETE;
741 ServerBoundCertService* sbc_service = session_->GetServerBoundCertService();
742 DCHECK(sbc_service != NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000743 int rv = sbc_service->GetDomainBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100744 url.GetOrigin().host(),
745 &domain_bound_private_key_,
746 &domain_bound_cert_,
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100747 base::Bind(&SpdyStream::OnGetDomainBoundCertComplete, GetWeakPtr()),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000748 &domain_bound_cert_request_handle_);
749 return rv;
750}
751
752int SpdyStream::DoGetDomainBoundCertComplete(int result) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100753 DCHECK_NE(type_, SPDY_PUSH_STREAM);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000754 if (result != OK)
755 return result;
756
757 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT;
Ben Murdochca12bfa2013-07-23 11:17:05 +0100758 slot_ = session_->credential_state()->SetHasCredential(GetUrlFromHeaders());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000759 return OK;
760}
761
762int SpdyStream::DoSendDomainBoundCert() {
Ben Murdocheb525c52013-07-10 11:40:50 +0100763 CHECK(request_headers_);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100764 DCHECK_NE(type_, SPDY_PUSH_STREAM);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000765 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100766
Ben Murdochca12bfa2013-07-23 11:17:05 +0100767 std::string origin = GetUrlFromHeaders().GetOrigin().spec();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100768 DCHECK(origin[origin.length() - 1] == '/');
769 origin.erase(origin.length() - 1); // Trim trailing slash.
770 scoped_ptr<SpdyFrame> frame;
771 int rv = session_->CreateCredentialFrame(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100772 origin,
773 domain_bound_private_key_,
774 domain_bound_cert_,
775 priority_,
776 &frame);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100777 if (rv != OK) {
778 DCHECK_NE(rv, ERR_IO_PENDING);
779 return rv;
780 }
781
782 DCHECK(frame);
783 // TODO(akalin): Fix the following race condition:
784 //
785 // Since this is decoupled from sending the SYN_STREAM frame, it is
786 // possible that other domain-bound cert frames will clobber ours
787 // before our SYN_STREAM frame gets sent. This can be solved by
788 // immediately enqueueing the SYN_STREAM frame here and adjusting
789 // the state machine appropriately.
790 session_->EnqueueStreamWrite(
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100791 GetWeakPtr(), CREDENTIAL,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100792 scoped_ptr<SpdyBufferProducer>(
793 new SimpleBufferProducer(
794 scoped_ptr<SpdyBuffer>(new SpdyBuffer(frame.Pass())))));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000795 return ERR_IO_PENDING;
796}
797
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100798int SpdyStream::DoSendDomainBoundCertComplete(int result) {
799 DCHECK_NE(type_, SPDY_PUSH_STREAM);
800 if (result != OK)
801 return result;
802
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100803 DCHECK_EQ(just_completed_frame_type_, CREDENTIAL);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100804 io_state_ = STATE_SEND_REQUEST_HEADERS;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000805 return OK;
806}
807
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100808int SpdyStream::DoSendRequestHeaders() {
809 DCHECK_NE(type_, SPDY_PUSH_STREAM);
810 io_state_ = STATE_SEND_REQUEST_HEADERS_COMPLETE;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100811
812 session_->EnqueueStreamWrite(
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100813 GetWeakPtr(), SYN_STREAM,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100814 scoped_ptr<SpdyBufferProducer>(
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100815 new SynStreamBufferProducer(GetWeakPtr())));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000816 return ERR_IO_PENDING;
817}
818
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100819namespace {
820
Ben Murdocheb525c52013-07-10 11:40:50 +0100821// Assuming we're in STATE_IDLE, maps the given type (which must not
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100822// be SPDY_PUSH_STREAM) and send status to a result to return from
823// DoSendRequestHeadersComplete() or DoOpen().
824int GetOpenStateResult(SpdyStreamType type, SpdySendStatus send_status) {
825 switch (type) {
826 case SPDY_BIDIRECTIONAL_STREAM:
827 // For bidirectional streams, there's nothing else to do.
828 DCHECK_EQ(send_status, MORE_DATA_TO_SEND);
829 return OK;
830
831 case SPDY_REQUEST_RESPONSE_STREAM:
832 // For request/response streams, wait for the delegate to send
833 // data if there's request data to send; we'll get called back
834 // when the send finishes.
835 if (send_status == MORE_DATA_TO_SEND)
836 return ERR_IO_PENDING;
837
838 return OK;
839
840 case SPDY_PUSH_STREAM:
841 // This should never be called for push streams.
842 break;
843 }
844
845 CHECK(false);
846 return ERR_UNEXPECTED;
847}
848
849} // namespace
850
851int SpdyStream::DoSendRequestHeadersComplete() {
852 DCHECK_NE(type_, SPDY_PUSH_STREAM);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100853 DCHECK_EQ(just_completed_frame_type_, SYN_STREAM);
854 DCHECK_NE(stream_id_, 0u);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000855
Ben Murdocheb525c52013-07-10 11:40:50 +0100856 io_state_ = STATE_IDLE;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100857
858 CHECK(delegate_);
Ben Murdocheb525c52013-07-10 11:40:50 +0100859 // Must not close |this|; if it does, it will trigger the |in_do_loop_|
860 // check in the destructor.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100861 delegate_->OnRequestHeadersSent();
862
Ben Murdocheb525c52013-07-10 11:40:50 +0100863 return GetOpenStateResult(type_, send_status_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000864}
865
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100866int SpdyStream::DoOpen() {
867 DCHECK_NE(type_, SPDY_PUSH_STREAM);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000868
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100869 if (just_completed_frame_type_ != DATA) {
870 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000871 return ERR_UNEXPECTED;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100872 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000873
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100874 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) {
875 NOTREACHED();
876 return ERR_UNEXPECTED;
877 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000878
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100879 size_t frame_payload_size =
880 just_completed_frame_size_ - session_->GetDataFrameMinimumSize();
881 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) {
882 NOTREACHED();
883 return ERR_UNEXPECTED;
884 }
885
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100886 // Set |io_state_| first as |delegate_| may check it.
Ben Murdocheb525c52013-07-10 11:40:50 +0100887 io_state_ = STATE_IDLE;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100888
889 send_bytes_ += frame_payload_size;
890
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100891 pending_send_data_->DidConsume(frame_payload_size);
892 if (pending_send_data_->BytesRemaining() > 0) {
893 QueueNextDataFrame();
894 return ERR_IO_PENDING;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100895 }
896
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100897 pending_send_data_ = NULL;
898
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100899 CHECK(delegate_);
Ben Murdocheb525c52013-07-10 11:40:50 +0100900 // Must not close |this|; if it does, it will trigger the
901 // |in_do_loop_| check in the destructor.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100902 delegate_->OnDataSent();
903
Ben Murdocheb525c52013-07-10 11:40:50 +0100904 return GetOpenStateResult(type_, send_status_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000905}
906
907void SpdyStream::UpdateHistograms() {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100908 // We need at least the receive timers to be filled in, as otherwise
909 // metrics can be bogus.
910 if (recv_first_byte_time_.is_null() || recv_last_byte_time_.is_null())
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000911 return;
912
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100913 base::TimeTicks effective_send_time;
914 if (type_ == SPDY_PUSH_STREAM) {
915 // Push streams shouldn't have |send_time_| filled in.
916 DCHECK(send_time_.is_null());
917 effective_send_time = recv_first_byte_time_;
918 } else {
919 // For non-push streams, we also need |send_time_| to be filled
920 // in.
921 if (send_time_.is_null())
922 return;
923 effective_send_time = send_time_;
924 }
925
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000926 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTimeToFirstByte",
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100927 recv_first_byte_time_ - effective_send_time);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000928 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime",
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100929 recv_last_byte_time_ - recv_first_byte_time_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000930 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime",
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100931 recv_last_byte_time_ - effective_send_time);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000932
933 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_);
934 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_);
935}
936
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100937void SpdyStream::QueueNextDataFrame() {
938 // Until the request has been completely sent, we cannot be sure
939 // that our stream_id is correct.
940 DCHECK_GT(io_state_, STATE_SEND_REQUEST_HEADERS_COMPLETE);
941 CHECK_GT(stream_id_, 0u);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100942 CHECK(pending_send_data_.get());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100943 CHECK_GT(pending_send_data_->BytesRemaining(), 0);
944
945 SpdyDataFlags flags =
946 (send_status_ == NO_MORE_DATA_TO_SEND) ?
947 DATA_FLAG_FIN : DATA_FLAG_NONE;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100948 scoped_ptr<SpdyBuffer> data_buffer(
949 session_->CreateDataBuffer(stream_id_,
950 pending_send_data_.get(),
951 pending_send_data_->BytesRemaining(),
952 flags));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100953 // We'll get called again by PossiblyResumeIfSendStalled().
954 if (!data_buffer)
955 return;
956
957 if (session_->flow_control_state() >= SpdySession::FLOW_CONTROL_STREAM) {
958 DCHECK_GE(data_buffer->GetRemainingSize(),
959 session_->GetDataFrameMinimumSize());
960 size_t payload_size =
961 data_buffer->GetRemainingSize() - session_->GetDataFrameMinimumSize();
962 DCHECK_LE(payload_size, session_->GetDataFrameMaximumPayload());
963 DecreaseSendWindowSize(static_cast<int32>(payload_size));
964 // This currently isn't strictly needed, since write frames are
965 // discarded only if the stream is about to be closed. But have it
966 // here anyway just in case this changes.
967 data_buffer->AddConsumeCallback(
968 base::Bind(&SpdyStream::OnWriteBufferConsumed,
969 GetWeakPtr(), payload_size));
970 }
971
972 session_->EnqueueStreamWrite(
973 GetWeakPtr(), DATA,
974 scoped_ptr<SpdyBufferProducer>(
975 new SimpleBufferProducer(data_buffer.Pass())));
976}
977
Ben Murdocheb525c52013-07-10 11:40:50 +0100978int SpdyStream::MergeWithResponseHeaders(
979 const SpdyHeaderBlock& new_response_headers) {
980 if (new_response_headers.find("transfer-encoding") !=
981 new_response_headers.end()) {
982 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
983 "Received transfer-encoding header");
984 return ERR_SPDY_PROTOCOL_ERROR;
985 }
986
987 for (SpdyHeaderBlock::const_iterator it = new_response_headers.begin();
988 it != new_response_headers.end(); ++it) {
989 // Disallow uppercase headers.
990 if (ContainsUppercaseAscii(it->first)) {
991 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
992 "Upper case characters in header: " + it->first);
993 return ERR_SPDY_PROTOCOL_ERROR;
994 }
995
996 SpdyHeaderBlock::iterator it2 = response_headers_.lower_bound(it->first);
997 // Disallow duplicate headers. This is just to be conservative.
998 if (it2 != response_headers_.end() && it2->first == it->first) {
999 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
1000 "Duplicate header: " + it->first);
1001 return ERR_SPDY_PROTOCOL_ERROR;
1002 }
1003
1004 response_headers_.insert(it2, *it);
1005 }
1006
1007 // If delegate_ is not yet attached, we'll call
1008 // OnResponseHeadersUpdated() after the delegate gets attached to
1009 // the stream.
1010 if (delegate_) {
1011 // The call to OnResponseHeadersUpdated() below may delete |this|,
1012 // so use |weak_this| to detect that.
1013 base::WeakPtr<SpdyStream> weak_this = GetWeakPtr();
1014
1015 SpdyResponseHeadersStatus status =
1016 delegate_->OnResponseHeadersUpdated(response_headers_);
1017 if (status == RESPONSE_HEADERS_ARE_INCOMPLETE) {
1018 // Since RESPONSE_HEADERS_ARE_INCOMPLETE was returned, we must not
1019 // have been closed.
1020 CHECK(weak_this);
1021 // Incomplete headers are OK only for push streams.
1022 if (type_ != SPDY_PUSH_STREAM) {
1023 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR,
1024 "Incomplete headers");
1025 return ERR_INCOMPLETE_SPDY_HEADERS;
1026 }
1027 } else if (weak_this) {
1028 response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE;
1029 }
1030 }
1031
1032 return OK;
1033}
1034
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001035} // namespace net