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" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
14 #include "net/base/host_port_pair.h" | 14 #include "net/base/host_port_pair.h" |
15 #include "net/base/net_log.h" | 15 #include "net/base/net_log.h" |
16 #include "net/base/net_util.h" | 16 #include "net/base/net_util.h" |
17 #include "net/base/upload_data_stream.h" | 17 #include "net/base/upload_data_stream.h" |
18 #include "net/http/http_request_headers.h" | 18 #include "net/http/http_request_headers.h" |
19 #include "net/http/http_request_info.h" | 19 #include "net/http/http_request_info.h" |
20 #include "net/http/http_response_info.h" | 20 #include "net/http/http_response_info.h" |
21 #include "net/spdy/spdy_header_block.h" | 21 #include "net/spdy/spdy_header_block.h" |
22 #include "net/spdy/spdy_http_utils.h" | 22 #include "net/spdy/spdy_http_utils.h" |
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, bool direct) | 28 SpdyHttpStream::SpdyHttpStream(const base::WeakPtr<SpdySession>& spdy_session, |
| 29 bool direct) |
29 : weak_factory_(this), | 30 : weak_factory_(this), |
30 spdy_session_(spdy_session), | 31 spdy_session_(spdy_session), |
| 32 is_reused_(spdy_session_->IsReused()), |
31 stream_closed_(false), | 33 stream_closed_(false), |
32 closed_stream_status_(ERR_FAILED), | 34 closed_stream_status_(ERR_FAILED), |
33 closed_stream_id_(0), | 35 closed_stream_id_(0), |
34 request_info_(NULL), | 36 request_info_(NULL), |
35 response_info_(NULL), | 37 response_info_(NULL), |
36 response_headers_status_(RESPONSE_HEADERS_ARE_INCOMPLETE), | 38 response_headers_status_(RESPONSE_HEADERS_ARE_INCOMPLETE), |
37 user_buffer_len_(0), | 39 user_buffer_len_(0), |
38 request_body_buf_size_(0), | 40 request_body_buf_size_(0), |
39 buffered_read_callback_pending_(false), | 41 buffered_read_callback_pending_(false), |
40 more_read_data_pending_(false), | 42 more_read_data_pending_(false), |
41 direct_(direct) { | 43 direct_(direct) { |
42 DCHECK(spdy_session_.get()); | 44 DCHECK(spdy_session_.get()); |
43 } | 45 } |
44 | 46 |
45 SpdyHttpStream::~SpdyHttpStream() { | 47 SpdyHttpStream::~SpdyHttpStream() { |
46 if (stream_.get()) { | 48 if (stream_.get()) { |
47 stream_->DetachDelegate(); | 49 stream_->DetachDelegate(); |
48 DCHECK(!stream_.get()); | 50 DCHECK(!stream_.get()); |
49 } | 51 } |
50 } | 52 } |
51 | 53 |
52 int SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info, | 54 int SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info, |
53 RequestPriority priority, | 55 RequestPriority priority, |
54 const BoundNetLog& stream_net_log, | 56 const BoundNetLog& stream_net_log, |
55 const CompletionCallback& callback) { | 57 const CompletionCallback& callback) { |
56 DCHECK(!stream_.get()); | 58 DCHECK(!stream_); |
| 59 if (!spdy_session_) |
| 60 return ERR_CONNECTION_CLOSED; |
57 | 61 |
58 request_info_ = request_info; | 62 request_info_ = request_info; |
59 if (request_info_->method == "GET") { | 63 if (request_info_->method == "GET") { |
60 int error = spdy_session_->GetPushStream(request_info_->url, &stream_, | 64 int error = spdy_session_->GetPushStream(request_info_->url, &stream_, |
61 stream_net_log); | 65 stream_net_log); |
62 if (error != OK) | 66 if (error != OK) |
63 return error; | 67 return error; |
64 | 68 |
65 // |stream_| may be NULL even if OK was returned. | 69 // |stream_| may be NULL even if OK was returned. |
66 if (stream_.get()) { | 70 if (stream_.get()) { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 | 158 |
155 bool SpdyHttpStream::IsResponseBodyComplete() const { | 159 bool SpdyHttpStream::IsResponseBodyComplete() const { |
156 return stream_closed_; | 160 return stream_closed_; |
157 } | 161 } |
158 | 162 |
159 bool SpdyHttpStream::CanFindEndOfResponse() const { | 163 bool SpdyHttpStream::CanFindEndOfResponse() const { |
160 return true; | 164 return true; |
161 } | 165 } |
162 | 166 |
163 bool SpdyHttpStream::IsConnectionReused() const { | 167 bool SpdyHttpStream::IsConnectionReused() const { |
164 return spdy_session_->IsReused(); | 168 return is_reused_; |
165 } | 169 } |
166 | 170 |
167 void SpdyHttpStream::SetConnectionReused() { | 171 void SpdyHttpStream::SetConnectionReused() { |
168 // SPDY doesn't need an indicator here. | 172 // SPDY doesn't need an indicator here. |
169 } | 173 } |
170 | 174 |
171 bool SpdyHttpStream::IsConnectionReusable() const { | 175 bool SpdyHttpStream::IsConnectionReusable() const { |
172 // SPDY streams aren't considered reusable. | 176 // SPDY streams aren't considered reusable. |
173 return false; | 177 return false; |
174 } | 178 } |
175 | 179 |
176 bool SpdyHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { | 180 bool SpdyHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { |
| 181 if (stream_closed_) { |
| 182 if (!closed_stream_has_load_timing_info_) |
| 183 return false; |
| 184 *load_timing_info = closed_stream_load_timing_info_; |
| 185 return true; |
| 186 } |
| 187 |
177 // If |stream_| has yet to be created, or does not yet have an ID, fail. | 188 // If |stream_| has yet to be created, or does not yet have an ID, fail. |
178 // The reused flag can only be correctly set once a stream has an ID. Streams | 189 // The reused flag can only be correctly set once a stream has an ID. Streams |
179 // get their IDs once the request has been successfully sent, so this does not | 190 // get their IDs once the request has been successfully sent, so this does not |
180 // behave that differently from other stream types. | 191 // behave that differently from other stream types. |
181 if (!spdy_session_.get() || (!stream_.get() && !stream_closed_)) | 192 if (!stream_ || stream_->stream_id() == 0) |
182 return false; | 193 return false; |
183 | 194 |
184 SpdyStreamId stream_id = | 195 return stream_->GetLoadTimingInfo(load_timing_info); |
185 stream_closed_ ? closed_stream_id_ : stream_->stream_id(); | |
186 if (stream_id == 0) | |
187 return false; | |
188 | |
189 return spdy_session_->GetLoadTimingInfo(stream_id, load_timing_info); | |
190 } | 196 } |
191 | 197 |
192 int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, | 198 int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, |
193 HttpResponseInfo* response, | 199 HttpResponseInfo* response, |
194 const CompletionCallback& callback) { | 200 const CompletionCallback& callback) { |
195 if (stream_closed_) { | 201 if (stream_closed_) { |
196 if (stream_->type() == SPDY_PUSH_STREAM) | 202 if (stream_->type() == SPDY_PUSH_STREAM) |
197 return closed_stream_status_; | 203 return closed_stream_status_; |
198 | 204 |
199 return (closed_stream_status_ == OK) ? ERR_FAILED : closed_stream_status_; | 205 return (closed_stream_status_ == OK) ? ERR_FAILED : closed_stream_status_; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 // Don't store the SSLInfo in the response here, HttpNetworkTransaction | 316 // Don't store the SSLInfo in the response here, HttpNetworkTransaction |
311 // will take care of that part. | 317 // will take care of that part. |
312 SSLInfo ssl_info; | 318 SSLInfo ssl_info; |
313 NextProto protocol_negotiated = kProtoUnknown; | 319 NextProto protocol_negotiated = kProtoUnknown; |
314 stream_->GetSSLInfo(&ssl_info, | 320 stream_->GetSSLInfo(&ssl_info, |
315 &response_info_->was_npn_negotiated, | 321 &response_info_->was_npn_negotiated, |
316 &protocol_negotiated); | 322 &protocol_negotiated); |
317 response_info_->npn_negotiated_protocol = | 323 response_info_->npn_negotiated_protocol = |
318 SSLClientSocket::NextProtoToString(protocol_negotiated); | 324 SSLClientSocket::NextProtoToString(protocol_negotiated); |
319 response_info_->request_time = stream_->GetRequestTime(); | 325 response_info_->request_time = stream_->GetRequestTime(); |
320 switch (spdy_session_->GetProtocolVersion()) { | 326 switch (stream_->GetProtocolVersion()) { |
321 case SPDY2: | 327 case SPDY2: |
322 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY2; | 328 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY2; |
323 break; | 329 break; |
324 case SPDY3: | 330 case SPDY3: |
325 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY3; | 331 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY3; |
326 break; | 332 break; |
327 case SPDY4: | 333 case SPDY4: |
328 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY4; | 334 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY4; |
329 break; | 335 break; |
330 default: | 336 default: |
(...skipping 30 matching lines...) Expand all Loading... |
361 void SpdyHttpStream::OnDataSent() { | 367 void SpdyHttpStream::OnDataSent() { |
362 request_body_buf_size_ = 0; | 368 request_body_buf_size_ = 0; |
363 ReadAndSendRequestBodyData(); | 369 ReadAndSendRequestBodyData(); |
364 } | 370 } |
365 | 371 |
366 void SpdyHttpStream::OnClose(int status) { | 372 void SpdyHttpStream::OnClose(int status) { |
367 if (stream_.get()) { | 373 if (stream_.get()) { |
368 stream_closed_ = true; | 374 stream_closed_ = true; |
369 closed_stream_status_ = status; | 375 closed_stream_status_ = status; |
370 closed_stream_id_ = stream_->stream_id(); | 376 closed_stream_id_ = stream_->stream_id(); |
| 377 closed_stream_has_load_timing_info_ = |
| 378 stream_->GetLoadTimingInfo(&closed_stream_load_timing_info_); |
371 } | 379 } |
372 stream_.reset(); | 380 stream_.reset(); |
373 bool invoked_callback = false; | 381 bool invoked_callback = false; |
374 if (status == net::OK) { | 382 if (status == net::OK) { |
375 // We need to complete any pending buffered read now. | 383 // We need to complete any pending buffered read now. |
376 invoked_callback = DoBufferedReadCallback(); | 384 invoked_callback = DoBufferedReadCallback(); |
377 } | 385 } |
378 if (!invoked_callback && !callback_.is_null()) | 386 if (!invoked_callback && !callback_.is_null()) |
379 DoCallback(status); | 387 DoCallback(status); |
380 } | 388 } |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 bool SpdyHttpStream::IsSpdyHttpStream() const { | 529 bool SpdyHttpStream::IsSpdyHttpStream() const { |
522 return true; | 530 return true; |
523 } | 531 } |
524 | 532 |
525 void SpdyHttpStream::Drain(HttpNetworkSession* session) { | 533 void SpdyHttpStream::Drain(HttpNetworkSession* session) { |
526 Close(false); | 534 Close(false); |
527 delete this; | 535 delete this; |
528 } | 536 } |
529 | 537 |
530 } // namespace net | 538 } // namespace net |
OLD | NEW |