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_http_stream.h" | 5 #include "net/spdy/spdy_http_stream.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <list> | 8 #include <list> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
23 #include "net/spdy/spdy_protocol.h" | 23 #include "net/spdy/spdy_protocol.h" |
24 #include "net/spdy/spdy_session.h" | 24 #include "net/spdy/spdy_session.h" |
25 | 25 |
26 namespace net { | 26 namespace net { |
27 | 27 |
28 SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, | 28 SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, |
29 bool direct) | 29 bool direct) |
30 : weak_factory_(this), | 30 : weak_factory_(this), |
31 spdy_session_(spdy_session), | 31 spdy_session_(spdy_session), |
32 stream_closed_(false), | 32 stream_closed_(false), |
33 closed_stream_pushed_(false), | |
34 closed_stream_status_(ERR_FAILED), | 33 closed_stream_status_(ERR_FAILED), |
35 closed_stream_id_(0), | 34 closed_stream_id_(0), |
36 request_info_(NULL), | 35 request_info_(NULL), |
37 has_upload_data_(false), | 36 has_upload_data_(false), |
38 response_info_(NULL), | 37 response_info_(NULL), |
39 response_headers_received_(false), | 38 response_headers_received_(false), |
40 user_buffer_len_(0), | 39 user_buffer_len_(0), |
41 raw_request_body_buf_size_(0), | 40 raw_request_body_buf_size_(0), |
42 buffered_read_callback_pending_(false), | 41 buffered_read_callback_pending_(false), |
43 more_read_data_pending_(false), | 42 more_read_data_pending_(false), |
(...skipping 16 matching lines...) Expand all Loading... | |
60 int SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info, | 59 int SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info, |
61 RequestPriority priority, | 60 RequestPriority priority, |
62 const BoundNetLog& stream_net_log, | 61 const BoundNetLog& stream_net_log, |
63 const CompletionCallback& callback) { | 62 const CompletionCallback& callback) { |
64 DCHECK(!stream_.get()); | 63 DCHECK(!stream_.get()); |
65 if (spdy_session_->IsClosed()) | 64 if (spdy_session_->IsClosed()) |
66 return ERR_CONNECTION_CLOSED; | 65 return ERR_CONNECTION_CLOSED; |
67 | 66 |
68 request_info_ = request_info; | 67 request_info_ = request_info; |
69 if (request_info_->method == "GET") { | 68 if (request_info_->method == "GET") { |
70 int error = spdy_session_->GetPushStream(request_info_->url, &stream_, | 69 int error = spdy_session_->GetPushStream(request_info_->url, &stream_, |
Ryan Hamilton
2013/05/26 15:33:49
Oh, I see. it does know that it's using a push st
| |
71 stream_net_log); | 70 stream_net_log); |
72 if (error != OK) | 71 if (error != OK) |
73 return error; | 72 return error; |
74 | 73 |
75 // |stream_| may be NULL even if OK was returned. | 74 // |stream_| may be NULL even if OK was returned. |
76 if (stream_) { | 75 if (stream_) { |
76 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); | |
77 stream_->SetDelegate(this); | 77 stream_->SetDelegate(this); |
78 return OK; | 78 return OK; |
79 } | 79 } |
80 } | 80 } |
81 | 81 |
82 int rv = stream_request_.StartRequest( | 82 int rv = stream_request_.StartRequest( |
83 spdy_session_, request_info_->url, priority, | 83 SPDY_REQUEST_RESPONSE_STREAM, spdy_session_, request_info_->url, |
84 stream_net_log, | 84 priority, stream_net_log, |
85 base::Bind(&SpdyHttpStream::OnStreamCreated, | 85 base::Bind(&SpdyHttpStream::OnStreamCreated, |
86 weak_factory_.GetWeakPtr(), callback)); | 86 weak_factory_.GetWeakPtr(), callback)); |
87 | 87 |
88 if (rv == OK) { | 88 if (rv == OK) { |
89 stream_ = stream_request_.ReleaseStream(); | 89 stream_ = stream_request_.ReleaseStream(); |
90 stream_->SetDelegate(this); | 90 stream_->SetDelegate(this); |
91 } | 91 } |
92 | 92 |
93 return rv; | 93 return rv; |
94 } | 94 } |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
196 if (stream_id == 0) | 196 if (stream_id == 0) |
197 return false; | 197 return false; |
198 | 198 |
199 return spdy_session_->GetLoadTimingInfo(stream_id, load_timing_info); | 199 return spdy_session_->GetLoadTimingInfo(stream_id, load_timing_info); |
200 } | 200 } |
201 | 201 |
202 int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, | 202 int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, |
203 HttpResponseInfo* response, | 203 HttpResponseInfo* response, |
204 const CompletionCallback& callback) { | 204 const CompletionCallback& callback) { |
205 if (stream_closed_) { | 205 if (stream_closed_) { |
206 if (stream_->pushed()) | 206 if (stream_->type() == SPDY_PUSH_STREAM) |
207 return closed_stream_status_; | 207 return closed_stream_status_; |
208 | 208 |
209 return (closed_stream_status_ == OK) ? ERR_FAILED : closed_stream_status_; | 209 return (closed_stream_status_ == OK) ? ERR_FAILED : closed_stream_status_; |
210 } | 210 } |
211 | 211 |
212 base::Time request_time = base::Time::Now(); | 212 base::Time request_time = base::Time::Now(); |
213 CHECK(stream_.get()); | 213 CHECK(stream_.get()); |
214 | 214 |
215 stream_->SetRequestTime(request_time); | 215 stream_->SetRequestTime(request_time); |
216 // This should only get called in the case of a request occurring | 216 // This should only get called in the case of a request occurring |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
249 | 249 |
250 response_info_ = response; | 250 response_info_ = response; |
251 | 251 |
252 // Put the peer's IP address and port into the response. | 252 // Put the peer's IP address and port into the response. |
253 IPEndPoint address; | 253 IPEndPoint address; |
254 int result = stream_->GetPeerAddress(&address); | 254 int result = stream_->GetPeerAddress(&address); |
255 if (result != OK) | 255 if (result != OK) |
256 return result; | 256 return result; |
257 response_info_->socket_address = HostPortPair::FromIPEndPoint(address); | 257 response_info_->socket_address = HostPortPair::FromIPEndPoint(address); |
258 | 258 |
259 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); | 259 if (stream_->type() == SPDY_PUSH_STREAM) { |
260 CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, | 260 // Pushed streams do not send any data, and should always be |
261 headers.get(), stream_->GetProtocolVersion(), | 261 // idle. However, we still want to return ERR_IO_PENDING to mimic |
262 direct_); | 262 // non-push behavior. The callback will be called when the |
263 stream_->net_log().AddEvent( | 263 // response is received. |
264 NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, | 264 result = ERR_IO_PENDING; |
265 base::Bind(&SpdyHeaderBlockNetLogCallback, headers.get())); | 265 } else { |
266 result = | 266 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); |
267 stream_->SendRequestHeaders( | 267 CreateSpdyHeadersFromHttpRequest( |
268 headers.Pass(), | 268 *request_info_, request_headers, |
269 has_upload_data_ ? MORE_DATA_TO_SEND : NO_MORE_DATA_TO_SEND); | 269 headers.get(), stream_->GetProtocolVersion(), |
270 direct_); | |
271 stream_->net_log().AddEvent( | |
272 NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, | |
273 base::Bind(&SpdyHeaderBlockNetLogCallback, headers.get())); | |
274 result = | |
275 stream_->SendRequestHeaders( | |
276 headers.Pass(), | |
277 has_upload_data_ ? MORE_DATA_TO_SEND : NO_MORE_DATA_TO_SEND); | |
278 } | |
279 | |
270 if (result == ERR_IO_PENDING) { | 280 if (result == ERR_IO_PENDING) { |
271 CHECK(callback_.is_null()); | 281 CHECK(callback_.is_null()); |
272 callback_ = callback; | 282 callback_ = callback; |
273 } | 283 } |
274 return result; | 284 return result; |
275 } | 285 } |
276 | 286 |
277 void SpdyHttpStream::Cancel() { | 287 void SpdyHttpStream::Cancel() { |
278 callback_.Reset(); | 288 callback_.Reset(); |
279 if (stream_) { | 289 if (stream_) { |
280 stream_->Cancel(); | 290 stream_->Cancel(); |
281 DCHECK(!stream_); | 291 DCHECK(!stream_); |
282 } | 292 } |
283 } | 293 } |
284 | 294 |
285 SpdySendStatus SpdyHttpStream::OnSendRequestHeadersComplete() { | 295 void SpdyHttpStream::OnSendRequestHeadersComplete() { |
286 if (!callback_.is_null()) | 296 if (!callback_.is_null()) |
287 DoCallback(OK); | 297 DoCallback(OK); |
288 return has_upload_data_ ? MORE_DATA_TO_SEND : NO_MORE_DATA_TO_SEND; | |
289 } | 298 } |
290 | 299 |
291 void SpdyHttpStream::OnSendBody() { | 300 void SpdyHttpStream::OnSendBody() { |
292 CHECK(request_info_ && request_info_->upload_data_stream); | 301 CHECK(request_info_ && request_info_->upload_data_stream); |
293 if (raw_request_body_buf_size_ > 0) { | 302 if (raw_request_body_buf_size_ > 0) { |
294 SendRequestBodyData(); | 303 SendRequestBodyData(); |
295 } else { | 304 } else { |
296 // We shouldn't be called if there's no more data to read. | 305 // We shouldn't be called if there's no more data to read. |
297 CHECK(!request_info_->upload_data_stream->IsEOF()); | 306 CHECK(!request_info_->upload_data_stream->IsEOF()); |
298 ReadAndSendRequestBodyData(); | 307 ReadAndSendRequestBodyData(); |
299 } | 308 } |
300 } | 309 } |
301 | 310 |
302 void SpdyHttpStream::OnSendBodyComplete() { | 311 void SpdyHttpStream::OnSendBodyComplete() { |
303 // |status| is the number of bytes written to the SPDY stream. | 312 // |status| is the number of bytes written to the SPDY stream. |
304 CHECK(request_info_ && request_info_->upload_data_stream); | 313 CHECK(request_info_ && request_info_->upload_data_stream); |
305 raw_request_body_buf_size_ = 0; | 314 raw_request_body_buf_size_ = 0; |
306 } | 315 } |
307 | 316 |
308 int SpdyHttpStream::OnResponseReceived(const SpdyHeaderBlock& response, | 317 int SpdyHttpStream::OnResponseReceived(const SpdyHeaderBlock& response, |
309 base::Time response_time, | 318 base::Time response_time, |
310 int status) { | 319 int status) { |
311 if (!response_info_) { | 320 if (!response_info_) { |
312 DCHECK(stream_->pushed()); | 321 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); |
313 push_response_info_.reset(new HttpResponseInfo); | 322 push_response_info_.reset(new HttpResponseInfo); |
314 response_info_ = push_response_info_.get(); | 323 response_info_ = push_response_info_.get(); |
315 } | 324 } |
316 | 325 |
317 // If the response is already received, these headers are too late. | 326 // If the response is already received, these headers are too late. |
318 if (response_headers_received_) { | 327 if (response_headers_received_) { |
319 LOG(WARNING) << "SpdyHttpStream headers received after response started."; | 328 LOG(WARNING) << "SpdyHttpStream headers received after response started."; |
320 return OK; | 329 return OK; |
321 } | 330 } |
322 | 331 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
369 // SpdyStream won't call us with data if the header block didn't contain a | 378 // SpdyStream won't call us with data if the header block didn't contain a |
370 // valid set of headers. So we don't expect to not have headers received | 379 // valid set of headers. So we don't expect to not have headers received |
371 // here. | 380 // here. |
372 if (!response_headers_received_) | 381 if (!response_headers_received_) |
373 return ERR_INCOMPLETE_SPDY_HEADERS; | 382 return ERR_INCOMPLETE_SPDY_HEADERS; |
374 | 383 |
375 // Note that data may be received for a SpdyStream prior to the user calling | 384 // Note that data may be received for a SpdyStream prior to the user calling |
376 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often | 385 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often |
377 // happen for server initiated streams. | 386 // happen for server initiated streams. |
378 DCHECK(stream_.get()); | 387 DCHECK(stream_.get()); |
379 DCHECK(!stream_->closed() || stream_->pushed()); | 388 DCHECK(!stream_->closed() || stream_->type() == SPDY_PUSH_STREAM); |
380 if (buffer) { | 389 if (buffer) { |
381 response_body_queue_.Enqueue(buffer.Pass()); | 390 response_body_queue_.Enqueue(buffer.Pass()); |
382 | 391 |
383 if (user_buffer_) { | 392 if (user_buffer_) { |
384 // Handing small chunks of data to the caller creates measurable overhead. | 393 // Handing small chunks of data to the caller creates measurable overhead. |
385 // We buffer data in short time-spans and send a single read notification. | 394 // We buffer data in short time-spans and send a single read notification. |
386 ScheduleBufferedReadCallback(); | 395 ScheduleBufferedReadCallback(); |
387 } | 396 } |
388 } | 397 } |
389 return OK; | 398 return OK; |
390 } | 399 } |
391 | 400 |
392 void SpdyHttpStream::OnDataSent() { | 401 void SpdyHttpStream::OnDataSent() { |
393 // For HTTP streams, no data is sent from the client while in the OPEN state, | 402 // For HTTP streams, no data is sent from the client while in the OPEN state, |
394 // so it is never called. | 403 // so it is never called. |
395 CHECK(false); | 404 CHECK(false); |
396 } | 405 } |
397 | 406 |
398 void SpdyHttpStream::OnClose(int status) { | 407 void SpdyHttpStream::OnClose(int status) { |
399 if (stream_) { | 408 if (stream_) { |
400 stream_closed_ = true; | 409 stream_closed_ = true; |
401 closed_stream_pushed_ = stream_->pushed(); | |
402 closed_stream_status_ = status; | 410 closed_stream_status_ = status; |
403 closed_stream_id_ = stream_->stream_id(); | 411 closed_stream_id_ = stream_->stream_id(); |
404 } | 412 } |
405 stream_.reset(); | 413 stream_.reset(); |
406 bool invoked_callback = false; | 414 bool invoked_callback = false; |
407 if (status == net::OK) { | 415 if (status == net::OK) { |
408 // We need to complete any pending buffered read now. | 416 // We need to complete any pending buffered read now. |
409 invoked_callback = DoBufferedReadCallback(); | 417 invoked_callback = DoBufferedReadCallback(); |
410 } | 418 } |
411 if (!invoked_callback && !callback_.is_null()) | 419 if (!invoked_callback && !callback_.is_null()) |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
547 bool SpdyHttpStream::IsSpdyHttpStream() const { | 555 bool SpdyHttpStream::IsSpdyHttpStream() const { |
548 return true; | 556 return true; |
549 } | 557 } |
550 | 558 |
551 void SpdyHttpStream::Drain(HttpNetworkSession* session) { | 559 void SpdyHttpStream::Drain(HttpNetworkSession* session) { |
552 Close(false); | 560 Close(false); |
553 delete this; | 561 delete this; |
554 } | 562 } |
555 | 563 |
556 } // namespace net | 564 } // namespace net |
OLD | NEW |