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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 int SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info, | 55 int SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info, |
56 RequestPriority priority, | 56 RequestPriority priority, |
57 const BoundNetLog& stream_net_log, | 57 const BoundNetLog& stream_net_log, |
58 const CompletionCallback& callback) { | 58 const CompletionCallback& callback) { |
59 DCHECK(!stream_); | 59 DCHECK(!stream_); |
60 if (!spdy_session_) | 60 if (!spdy_session_) |
61 return ERR_CONNECTION_CLOSED; | 61 return ERR_CONNECTION_CLOSED; |
62 | 62 |
63 request_info_ = request_info; | 63 request_info_ = request_info; |
64 if (request_info_->method == "GET") { | 64 if (request_info_->method == "GET") { |
65 int error = spdy_session_->GetPushStream(request_info_->url, &stream_, | 65 int error = spdy_session_->GetPushStream( |
66 stream_net_log); | 66 request_info_->url, &stream_, stream_net_log); |
67 if (error != OK) | 67 if (error != OK) |
68 return error; | 68 return error; |
69 | 69 |
70 // |stream_| may be NULL even if OK was returned. | 70 // |stream_| may be NULL even if OK was returned. |
71 if (stream_.get()) { | 71 if (stream_.get()) { |
72 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); | 72 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); |
73 stream_->SetDelegate(this); | 73 stream_->SetDelegate(this); |
74 return OK; | 74 return OK; |
75 } | 75 } |
76 } | 76 } |
77 | 77 |
78 int rv = stream_request_.StartRequest( | 78 int rv = |
79 SPDY_REQUEST_RESPONSE_STREAM, spdy_session_, request_info_->url, | 79 stream_request_.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, |
80 priority, stream_net_log, | 80 spdy_session_, |
81 base::Bind(&SpdyHttpStream::OnStreamCreated, | 81 request_info_->url, |
82 weak_factory_.GetWeakPtr(), callback)); | 82 priority, |
| 83 stream_net_log, |
| 84 base::Bind(&SpdyHttpStream::OnStreamCreated, |
| 85 weak_factory_.GetWeakPtr(), |
| 86 callback)); |
83 | 87 |
84 if (rv == OK) { | 88 if (rv == OK) { |
85 stream_ = stream_request_.ReleaseStream(); | 89 stream_ = stream_request_.ReleaseStream(); |
86 stream_->SetDelegate(this); | 90 stream_->SetDelegate(this); |
87 } | 91 } |
88 | 92 |
89 return rv; | 93 return rv; |
90 } | 94 } |
91 | 95 |
92 const HttpResponseInfo* SpdyHttpStream::GetResponseInfo() const { | 96 const HttpResponseInfo* SpdyHttpStream::GetResponseInfo() const { |
(...skipping 20 matching lines...) Expand all Loading... |
113 CHECK(!stream_->IsIdle()); | 117 CHECK(!stream_->IsIdle()); |
114 return OK; | 118 return OK; |
115 } | 119 } |
116 | 120 |
117 // Still waiting for the response, return IO_PENDING. | 121 // Still waiting for the response, return IO_PENDING. |
118 CHECK(callback_.is_null()); | 122 CHECK(callback_.is_null()); |
119 callback_ = callback; | 123 callback_ = callback; |
120 return ERR_IO_PENDING; | 124 return ERR_IO_PENDING; |
121 } | 125 } |
122 | 126 |
123 int SpdyHttpStream::ReadResponseBody( | 127 int SpdyHttpStream::ReadResponseBody(IOBuffer* buf, |
124 IOBuffer* buf, int buf_len, const CompletionCallback& callback) { | 128 int buf_len, |
| 129 const CompletionCallback& callback) { |
125 if (stream_.get()) | 130 if (stream_.get()) |
126 CHECK(!stream_->IsIdle()); | 131 CHECK(!stream_->IsIdle()); |
127 | 132 |
128 CHECK(buf); | 133 CHECK(buf); |
129 CHECK(buf_len); | 134 CHECK(buf_len); |
130 CHECK(!callback.is_null()); | 135 CHECK(!callback.is_null()); |
131 | 136 |
132 // If we have data buffered, complete the IO immediately. | 137 // If we have data buffered, complete the IO immediately. |
133 if (!response_body_queue_.IsEmpty()) { | 138 if (!response_body_queue_.IsEmpty()) { |
134 return response_body_queue_.Dequeue(buf->data(), buf_len); | 139 return response_body_queue_.Dequeue(buf->data(), buf_len); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 response_info_->socket_address = HostPortPair::FromIPEndPoint(address); | 263 response_info_->socket_address = HostPortPair::FromIPEndPoint(address); |
259 | 264 |
260 if (stream_->type() == SPDY_PUSH_STREAM) { | 265 if (stream_->type() == SPDY_PUSH_STREAM) { |
261 // Pushed streams do not send any data, and should always be | 266 // Pushed streams do not send any data, and should always be |
262 // idle. However, we still want to return ERR_IO_PENDING to mimic | 267 // idle. However, we still want to return ERR_IO_PENDING to mimic |
263 // non-push behavior. The callback will be called when the | 268 // non-push behavior. The callback will be called when the |
264 // response is received. | 269 // response is received. |
265 result = ERR_IO_PENDING; | 270 result = ERR_IO_PENDING; |
266 } else { | 271 } else { |
267 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); | 272 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); |
268 CreateSpdyHeadersFromHttpRequest( | 273 CreateSpdyHeadersFromHttpRequest(*request_info_, |
269 *request_info_, request_headers, | 274 request_headers, |
270 headers.get(), stream_->GetProtocolVersion(), | 275 headers.get(), |
271 direct_); | 276 stream_->GetProtocolVersion(), |
| 277 direct_); |
272 stream_->net_log().AddEvent( | 278 stream_->net_log().AddEvent( |
273 NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, | 279 NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, |
274 base::Bind(&SpdyHeaderBlockNetLogCallback, headers.get())); | 280 base::Bind(&SpdyHeaderBlockNetLogCallback, headers.get())); |
275 result = | 281 result = stream_->SendRequestHeaders( |
276 stream_->SendRequestHeaders( | 282 headers.Pass(), |
277 headers.Pass(), | 283 HasUploadData() ? MORE_DATA_TO_SEND : NO_MORE_DATA_TO_SEND); |
278 HasUploadData() ? MORE_DATA_TO_SEND : NO_MORE_DATA_TO_SEND); | |
279 } | 284 } |
280 | 285 |
281 if (result == ERR_IO_PENDING) { | 286 if (result == ERR_IO_PENDING) { |
282 CHECK(callback_.is_null()); | 287 CHECK(callback_.is_null()); |
283 callback_ = callback; | 288 callback_ = callback; |
284 } | 289 } |
285 return result; | 290 return result; |
286 } | 291 } |
287 | 292 |
288 void SpdyHttpStream::Cancel() { | 293 void SpdyHttpStream::Cancel() { |
(...skipping 29 matching lines...) Expand all Loading... |
318 // We do not have complete headers yet. | 323 // We do not have complete headers yet. |
319 return RESPONSE_HEADERS_ARE_INCOMPLETE; | 324 return RESPONSE_HEADERS_ARE_INCOMPLETE; |
320 } | 325 } |
321 | 326 |
322 response_info_->response_time = stream_->response_time(); | 327 response_info_->response_time = stream_->response_time(); |
323 response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE; | 328 response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE; |
324 // Don't store the SSLInfo in the response here, HttpNetworkTransaction | 329 // Don't store the SSLInfo in the response here, HttpNetworkTransaction |
325 // will take care of that part. | 330 // will take care of that part. |
326 SSLInfo ssl_info; | 331 SSLInfo ssl_info; |
327 NextProto protocol_negotiated = kProtoUnknown; | 332 NextProto protocol_negotiated = kProtoUnknown; |
328 stream_->GetSSLInfo(&ssl_info, | 333 stream_->GetSSLInfo( |
329 &response_info_->was_npn_negotiated, | 334 &ssl_info, &response_info_->was_npn_negotiated, &protocol_negotiated); |
330 &protocol_negotiated); | |
331 response_info_->npn_negotiated_protocol = | 335 response_info_->npn_negotiated_protocol = |
332 SSLClientSocket::NextProtoToString(protocol_negotiated); | 336 SSLClientSocket::NextProtoToString(protocol_negotiated); |
333 response_info_->request_time = stream_->GetRequestTime(); | 337 response_info_->request_time = stream_->GetRequestTime(); |
334 response_info_->connection_info = | 338 response_info_->connection_info = |
335 HttpResponseInfo::ConnectionInfoFromNextProto(stream_->GetProtocol()); | 339 HttpResponseInfo::ConnectionInfoFromNextProto(stream_->GetProtocol()); |
336 response_info_->vary_data | 340 response_info_->vary_data.Init(*request_info_, |
337 .Init(*request_info_, *response_info_->headers.get()); | 341 *response_info_->headers.get()); |
338 | 342 |
339 if (!callback_.is_null()) | 343 if (!callback_.is_null()) |
340 DoCallback(OK); | 344 DoCallback(OK); |
341 | 345 |
342 return RESPONSE_HEADERS_ARE_COMPLETE; | 346 return RESPONSE_HEADERS_ARE_COMPLETE; |
343 } | 347 } |
344 | 348 |
345 void SpdyHttpStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { | 349 void SpdyHttpStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { |
346 CHECK_EQ(response_headers_status_, RESPONSE_HEADERS_ARE_COMPLETE); | 350 CHECK_EQ(response_headers_status_, RESPONSE_HEADERS_ARE_COMPLETE); |
347 | 351 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 if (status == net::OK) { | 384 if (status == net::OK) { |
381 // We need to complete any pending buffered read now. | 385 // We need to complete any pending buffered read now. |
382 invoked_callback = DoBufferedReadCallback(); | 386 invoked_callback = DoBufferedReadCallback(); |
383 } | 387 } |
384 if (!invoked_callback && !callback_.is_null()) | 388 if (!invoked_callback && !callback_.is_null()) |
385 DoCallback(status); | 389 DoCallback(status); |
386 } | 390 } |
387 | 391 |
388 bool SpdyHttpStream::HasUploadData() const { | 392 bool SpdyHttpStream::HasUploadData() const { |
389 CHECK(request_info_); | 393 CHECK(request_info_); |
390 return | 394 return request_info_->upload_data_stream && |
391 request_info_->upload_data_stream && | 395 ((request_info_->upload_data_stream->size() > 0) || |
392 ((request_info_->upload_data_stream->size() > 0) || | 396 request_info_->upload_data_stream->is_chunked()); |
393 request_info_->upload_data_stream->is_chunked()); | |
394 } | 397 } |
395 | 398 |
396 void SpdyHttpStream::OnStreamCreated( | 399 void SpdyHttpStream::OnStreamCreated(const CompletionCallback& callback, |
397 const CompletionCallback& callback, | 400 int rv) { |
398 int rv) { | |
399 if (rv == OK) { | 401 if (rv == OK) { |
400 stream_ = stream_request_.ReleaseStream(); | 402 stream_ = stream_request_.ReleaseStream(); |
401 stream_->SetDelegate(this); | 403 stream_->SetDelegate(this); |
402 } | 404 } |
403 callback.Run(rv); | 405 callback.Run(rv); |
404 } | 406 } |
405 | 407 |
406 void SpdyHttpStream::ReadAndSendRequestBodyData() { | 408 void SpdyHttpStream::ReadAndSendRequestBodyData() { |
407 CHECK(HasUploadData()); | 409 CHECK(HasUploadData()); |
408 CHECK_EQ(request_body_buf_size_, 0); | 410 CHECK_EQ(request_body_buf_size_, 0); |
409 | 411 |
410 if (request_info_->upload_data_stream->IsEOF()) | 412 if (request_info_->upload_data_stream->IsEOF()) |
411 return; | 413 return; |
412 | 414 |
413 // Read the data from the request body stream. | 415 // Read the data from the request body stream. |
414 const int rv = request_info_->upload_data_stream | 416 const int rv = request_info_->upload_data_stream->Read( |
415 ->Read(request_body_buf_.get(), | 417 request_body_buf_.get(), |
416 request_body_buf_->size(), | 418 request_body_buf_->size(), |
417 base::Bind(&SpdyHttpStream::OnRequestBodyReadCompleted, | 419 base::Bind(&SpdyHttpStream::OnRequestBodyReadCompleted, |
418 weak_factory_.GetWeakPtr())); | 420 weak_factory_.GetWeakPtr())); |
419 | 421 |
420 if (rv != ERR_IO_PENDING) { | 422 if (rv != ERR_IO_PENDING) { |
421 // ERR_IO_PENDING is the only possible error. | 423 // ERR_IO_PENDING is the only possible error. |
422 CHECK_GE(rv, 0); | 424 CHECK_GE(rv, 0); |
423 OnRequestBodyReadCompleted(rv); | 425 OnRequestBodyReadCompleted(rv); |
424 } | 426 } |
425 } | 427 } |
426 | 428 |
427 void SpdyHttpStream::OnRequestBodyReadCompleted(int status) { | 429 void SpdyHttpStream::OnRequestBodyReadCompleted(int status) { |
428 CHECK_GE(status, 0); | 430 CHECK_GE(status, 0); |
(...skipping 29 matching lines...) Expand all Loading... |
458 | 460 |
459 // Checks to see if we should wait for more buffered data before notifying | 461 // Checks to see if we should wait for more buffered data before notifying |
460 // the caller. Returns true if we should wait, false otherwise. | 462 // the caller. Returns true if we should wait, false otherwise. |
461 bool SpdyHttpStream::ShouldWaitForMoreBufferedData() const { | 463 bool SpdyHttpStream::ShouldWaitForMoreBufferedData() const { |
462 // If the response is complete, there is no point in waiting. | 464 // If the response is complete, there is no point in waiting. |
463 if (stream_closed_) | 465 if (stream_closed_) |
464 return false; | 466 return false; |
465 | 467 |
466 DCHECK_GT(user_buffer_len_, 0); | 468 DCHECK_GT(user_buffer_len_, 0); |
467 return response_body_queue_.GetTotalSize() < | 469 return response_body_queue_.GetTotalSize() < |
468 static_cast<size_t>(user_buffer_len_); | 470 static_cast<size_t>(user_buffer_len_); |
469 } | 471 } |
470 | 472 |
471 bool SpdyHttpStream::DoBufferedReadCallback() { | 473 bool SpdyHttpStream::DoBufferedReadCallback() { |
472 buffered_read_callback_pending_ = false; | 474 buffered_read_callback_pending_ = false; |
473 | 475 |
474 // If the transaction is cancelled or errored out, we don't need to complete | 476 // If the transaction is cancelled or errored out, we don't need to complete |
475 // the read. | 477 // the read. |
476 if (!stream_.get() && !stream_closed_) | 478 if (!stream_.get() && !stream_closed_) |
477 return false; | 479 return false; |
478 | 480 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 Close(false); | 534 Close(false); |
533 delete this; | 535 delete this; |
534 } | 536 } |
535 | 537 |
536 void SpdyHttpStream::SetPriority(RequestPriority priority) { | 538 void SpdyHttpStream::SetPriority(RequestPriority priority) { |
537 // TODO(akalin): Plumb this through to |stream_request_| and | 539 // TODO(akalin): Plumb this through to |stream_request_| and |
538 // |stream_|. | 540 // |stream_|. |
539 } | 541 } |
540 | 542 |
541 } // namespace net | 543 } // namespace net |
OLD | NEW |