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 15 matching lines...) Expand all Loading... |
26 namespace net { | 26 namespace net { |
27 | 27 |
28 SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, bool direct) | 28 SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, bool direct) |
29 : weak_factory_(this), | 29 : weak_factory_(this), |
30 spdy_session_(spdy_session), | 30 spdy_session_(spdy_session), |
31 stream_closed_(false), | 31 stream_closed_(false), |
32 closed_stream_status_(ERR_FAILED), | 32 closed_stream_status_(ERR_FAILED), |
33 closed_stream_id_(0), | 33 closed_stream_id_(0), |
34 request_info_(NULL), | 34 request_info_(NULL), |
35 response_info_(NULL), | 35 response_info_(NULL), |
36 response_headers_received_(false), | 36 response_headers_status_(RESPONSE_HEADERS_ARE_INCOMPLETE), |
37 user_buffer_len_(0), | 37 user_buffer_len_(0), |
38 request_body_buf_size_(0), | 38 request_body_buf_size_(0), |
39 buffered_read_callback_pending_(false), | 39 buffered_read_callback_pending_(false), |
40 more_read_data_pending_(false), | 40 more_read_data_pending_(false), |
41 direct_(direct) { | 41 direct_(direct) { |
42 DCHECK(spdy_session_); | 42 DCHECK(spdy_session_); |
43 } | 43 } |
44 | 44 |
45 SpdyHttpStream::~SpdyHttpStream() { | 45 SpdyHttpStream::~SpdyHttpStream() { |
46 if (stream_.get()) { | 46 if (stream_.get()) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 } | 99 } |
100 | 100 |
101 int SpdyHttpStream::ReadResponseHeaders(const CompletionCallback& callback) { | 101 int SpdyHttpStream::ReadResponseHeaders(const CompletionCallback& callback) { |
102 CHECK(!callback.is_null()); | 102 CHECK(!callback.is_null()); |
103 if (stream_closed_) | 103 if (stream_closed_) |
104 return closed_stream_status_; | 104 return closed_stream_status_; |
105 | 105 |
106 CHECK(stream_.get()); | 106 CHECK(stream_.get()); |
107 | 107 |
108 // Check if we already have the response headers. If so, return synchronously. | 108 // Check if we already have the response headers. If so, return synchronously. |
109 if(stream_->response_received()) { | 109 if (response_headers_status_ == RESPONSE_HEADERS_ARE_COMPLETE) { |
110 CHECK(stream_->is_idle()); | 110 CHECK(stream_->is_idle()); |
111 return OK; | 111 return OK; |
112 } | 112 } |
113 | 113 |
114 // Still waiting for the response, return IO_PENDING. | 114 // Still waiting for the response, return IO_PENDING. |
115 CHECK(callback_.is_null()); | 115 CHECK(callback_.is_null()); |
116 callback_ = callback; | 116 callback_ = callback; |
117 return ERR_IO_PENDING; | 117 return ERR_IO_PENDING; |
118 } | 118 } |
119 | 119 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 void SpdyHttpStream::OnRequestHeadersSent() { | 285 void SpdyHttpStream::OnRequestHeadersSent() { |
286 if (!callback_.is_null()) | 286 if (!callback_.is_null()) |
287 DoCallback(OK); | 287 DoCallback(OK); |
288 | 288 |
289 // TODO(akalin): Do this immediately after sending the request | 289 // TODO(akalin): Do this immediately after sending the request |
290 // headers. | 290 // headers. |
291 if (HasUploadData()) | 291 if (HasUploadData()) |
292 ReadAndSendRequestBodyData(); | 292 ReadAndSendRequestBodyData(); |
293 } | 293 } |
294 | 294 |
295 int SpdyHttpStream::OnResponseHeadersReceived(const SpdyHeaderBlock& response, | 295 SpdyResponseHeadersStatus SpdyHttpStream::OnResponseHeadersUpdated( |
296 base::Time response_time, | 296 const SpdyHeaderBlock& response_headers) { |
297 int status) { | 297 CHECK_EQ(response_headers_status_, RESPONSE_HEADERS_ARE_INCOMPLETE); |
| 298 |
298 if (!response_info_) { | 299 if (!response_info_) { |
299 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); | 300 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); |
300 push_response_info_.reset(new HttpResponseInfo); | 301 push_response_info_.reset(new HttpResponseInfo); |
301 response_info_ = push_response_info_.get(); | 302 response_info_ = push_response_info_.get(); |
302 } | 303 } |
303 | 304 |
304 // If the response is already received, these headers are too late. | 305 if (!SpdyHeadersToHttpResponse( |
305 if (response_headers_received_) { | 306 response_headers, stream_->GetProtocolVersion(), response_info_)) { |
306 LOG(WARNING) << "SpdyHttpStream headers received after response started."; | 307 // We do not have complete headers yet. |
307 return OK; | 308 return RESPONSE_HEADERS_ARE_INCOMPLETE; |
308 } | 309 } |
309 | 310 |
310 // TODO(mbelshe): This is the time of all headers received, not just time | 311 response_info_->response_time = stream_->response_time(); |
311 // to first byte. | 312 response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE; |
312 response_info_->response_time = base::Time::Now(); | |
313 | |
314 if (!SpdyHeadersToHttpResponse(response, stream_->GetProtocolVersion(), | |
315 response_info_)) { | |
316 // We might not have complete headers yet. | |
317 return ERR_INCOMPLETE_SPDY_HEADERS; | |
318 } | |
319 | |
320 response_headers_received_ = true; | |
321 // Don't store the SSLInfo in the response here, HttpNetworkTransaction | 313 // Don't store the SSLInfo in the response here, HttpNetworkTransaction |
322 // will take care of that part. | 314 // will take care of that part. |
323 SSLInfo ssl_info; | 315 SSLInfo ssl_info; |
324 NextProto protocol_negotiated = kProtoUnknown; | 316 NextProto protocol_negotiated = kProtoUnknown; |
325 stream_->GetSSLInfo(&ssl_info, | 317 stream_->GetSSLInfo(&ssl_info, |
326 &response_info_->was_npn_negotiated, | 318 &response_info_->was_npn_negotiated, |
327 &protocol_negotiated); | 319 &protocol_negotiated); |
328 response_info_->npn_negotiated_protocol = | 320 response_info_->npn_negotiated_protocol = |
329 SSLClientSocket::NextProtoToString(protocol_negotiated); | 321 SSLClientSocket::NextProtoToString(protocol_negotiated); |
330 response_info_->request_time = stream_->GetRequestTime(); | 322 response_info_->request_time = stream_->GetRequestTime(); |
331 switch (spdy_session_->GetProtocolVersion()) { | 323 switch (spdy_session_->GetProtocolVersion()) { |
332 case SPDY2: | 324 case SPDY2: |
333 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY2; | 325 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY2; |
334 break; | 326 break; |
335 case SPDY3: | 327 case SPDY3: |
336 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY3; | 328 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY3; |
337 break; | 329 break; |
338 case SPDY4: | 330 case SPDY4: |
339 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY4; | 331 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY4; |
340 break; | 332 break; |
341 default: | 333 default: |
342 NOTREACHED(); | 334 NOTREACHED(); |
343 } | 335 } |
344 response_info_->vary_data | 336 response_info_->vary_data |
345 .Init(*request_info_, *response_info_->headers.get()); | 337 .Init(*request_info_, *response_info_->headers.get()); |
346 // TODO(ahendrickson): This is recorded after the entire SYN_STREAM control | |
347 // frame has been received and processed. Move to framer? | |
348 response_info_->response_time = response_time; | |
349 | 338 |
350 if (!callback_.is_null()) | 339 if (!callback_.is_null()) |
351 DoCallback(status); | 340 DoCallback(OK); |
352 | 341 |
353 return status; | 342 return RESPONSE_HEADERS_ARE_COMPLETE; |
354 } | 343 } |
355 | 344 |
356 int SpdyHttpStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { | 345 void SpdyHttpStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { |
357 // SpdyStream won't call us with data if the header block didn't contain a | 346 CHECK_EQ(response_headers_status_, RESPONSE_HEADERS_ARE_COMPLETE); |
358 // valid set of headers. So we don't expect to not have headers received | |
359 // here. | |
360 if (!response_headers_received_) | |
361 return ERR_INCOMPLETE_SPDY_HEADERS; | |
362 | 347 |
363 // Note that data may be received for a SpdyStream prior to the user calling | 348 // Note that data may be received for a SpdyStream prior to the user calling |
364 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often | 349 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often |
365 // happen for server initiated streams. | 350 // happen for server initiated streams. |
366 DCHECK(stream_.get()); | 351 DCHECK(stream_.get()); |
367 DCHECK(!stream_->closed() || stream_->type() == SPDY_PUSH_STREAM); | 352 DCHECK(!stream_->closed() || stream_->type() == SPDY_PUSH_STREAM); |
368 if (buffer) { | 353 if (buffer) { |
369 response_body_queue_.Enqueue(buffer.Pass()); | 354 response_body_queue_.Enqueue(buffer.Pass()); |
370 | 355 |
371 if (user_buffer_.get()) { | 356 if (user_buffer_.get()) { |
372 // Handing small chunks of data to the caller creates measurable overhead. | 357 // Handing small chunks of data to the caller creates measurable overhead. |
373 // We buffer data in short time-spans and send a single read notification. | 358 // We buffer data in short time-spans and send a single read notification. |
374 ScheduleBufferedReadCallback(); | 359 ScheduleBufferedReadCallback(); |
375 } | 360 } |
376 } | 361 } |
377 return OK; | |
378 } | 362 } |
379 | 363 |
380 void SpdyHttpStream::OnDataSent() { | 364 void SpdyHttpStream::OnDataSent() { |
381 request_body_buf_size_ = 0; | 365 request_body_buf_size_ = 0; |
382 ReadAndSendRequestBodyData(); | 366 ReadAndSendRequestBodyData(); |
383 } | 367 } |
384 | 368 |
385 void SpdyHttpStream::OnClose(int status) { | 369 void SpdyHttpStream::OnClose(int status) { |
386 if (stream_.get()) { | 370 if (stream_.get()) { |
387 stream_closed_ = true; | 371 stream_closed_ = true; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 bool SpdyHttpStream::IsSpdyHttpStream() const { | 524 bool SpdyHttpStream::IsSpdyHttpStream() const { |
541 return true; | 525 return true; |
542 } | 526 } |
543 | 527 |
544 void SpdyHttpStream::Drain(HttpNetworkSession* session) { | 528 void SpdyHttpStream::Drain(HttpNetworkSession* session) { |
545 Close(false); | 529 Close(false); |
546 delete this; | 530 delete this; |
547 } | 531 } |
548 | 532 |
549 } // namespace net | 533 } // namespace net |
OLD | NEW |