Chromium Code Reviews| 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_stream.h" | 5 #include "net/spdy/spdy_stream.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 // headers once we've finished sending the request headers. | 396 // headers once we've finished sending the request headers. |
| 397 if (io_state_ == STATE_IDLE) { | 397 if (io_state_ == STATE_IDLE) { |
| 398 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, | 398 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, |
| 399 "Response received before request sent"); | 399 "Response received before request sent"); |
| 400 return ERR_SPDY_PROTOCOL_ERROR; | 400 return ERR_SPDY_PROTOCOL_ERROR; |
| 401 } | 401 } |
| 402 break; | 402 break; |
| 403 | 403 |
| 404 case SPDY_REQUEST_RESPONSE_STREAM: | 404 case SPDY_REQUEST_RESPONSE_STREAM: |
| 405 // For a request/response stream, we're ready for the response | 405 // For a request/response stream, we're ready for the response |
| 406 // headers once we've finished sending the request headers and | 406 // headers once we've finished sending the request headers. |
| 407 // the request body (if we have one). | 407 if (io_state_ == STATE_IDLE) { |
| 408 if (io_state_ != STATE_HALF_CLOSED_LOCAL) { | |
| 409 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, | 408 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, |
| 410 "Response received before request sent"); | 409 "Response received before request sent"); |
| 411 return ERR_SPDY_PROTOCOL_ERROR; | 410 return ERR_SPDY_PROTOCOL_ERROR; |
| 412 } | 411 } |
| 413 break; | 412 break; |
| 414 | 413 |
| 415 case SPDY_PUSH_STREAM: | 414 case SPDY_PUSH_STREAM: |
| 416 // Push streams transition to a locally half-closed state upon headers. | 415 // Push streams transition to a locally half-closed state upon headers. |
| 417 // We must continue to buffer data while waiting for a call to | 416 // We must continue to buffer data while waiting for a call to |
| 418 // SetDelegate() (which may not ever happen). | 417 // SetDelegate() (which may not ever happen). |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, | 477 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, |
| 479 "Data received with incomplete headers."); | 478 "Data received with incomplete headers."); |
| 480 session_->CloseActiveStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR); | 479 session_->CloseActiveStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR); |
| 481 return; | 480 return; |
| 482 } | 481 } |
| 483 | 482 |
| 484 CHECK(!IsClosed()); | 483 CHECK(!IsClosed()); |
| 485 | 484 |
| 486 if (!buffer) { | 485 if (!buffer) { |
| 487 metrics_.StopStream(); | 486 metrics_.StopStream(); |
| 488 // TODO(jgraettinger): Closing from OPEN preserves current SpdyStream | 487 if (io_state_ == STATE_OPEN) { |
| 489 // behavior, but is incorrect HTTP/2 behavior. |io_state_| should be | 488 io_state_ = STATE_HALF_CLOSED_REMOTE; |
| 490 // HALF_CLOSED_REMOTE. To be changed in a subsequent CL. | 489 } else if (io_state_ == STATE_HALF_CLOSED_LOCAL) { |
| 491 if (io_state_ == STATE_OPEN || io_state_ == STATE_HALF_CLOSED_LOCAL) { | |
| 492 io_state_ = STATE_CLOSED; | 490 io_state_ = STATE_CLOSED; |
| 493 // Deletes |this|. | 491 // Deletes |this|. |
| 494 session_->CloseActiveStream(stream_id_, OK); | 492 session_->CloseActiveStream(stream_id_, OK); |
| 495 return; | 493 } else { |
| 494 NOTREACHED() << io_state_; | |
| 496 } | 495 } |
| 497 NOTREACHED() << io_state_; | |
| 498 return; | 496 return; |
| 499 } | 497 } |
| 500 | 498 |
| 501 size_t length = buffer->GetRemainingSize(); | 499 size_t length = buffer->GetRemainingSize(); |
| 502 DCHECK_LE(length, session_->GetDataFrameMaximumPayload()); | 500 DCHECK_LE(length, session_->GetDataFrameMaximumPayload()); |
| 503 if (session_->flow_control_state() >= SpdySession::FLOW_CONTROL_STREAM) { | 501 if (session_->flow_control_state() >= SpdySession::FLOW_CONTROL_STREAM) { |
| 504 DecreaseRecvWindowSize(static_cast<int32>(length)); | 502 DecreaseRecvWindowSize(static_cast<int32>(length)); |
| 505 buffer->AddConsumeCallback( | 503 buffer->AddConsumeCallback( |
| 506 base::Bind(&SpdyStream::OnReadBufferConsumed, GetWeakPtr())); | 504 base::Bind(&SpdyStream::OnReadBufferConsumed, GetWeakPtr())); |
| 507 } | 505 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 528 frame_type == DATA) << frame_type; | 526 frame_type == DATA) << frame_type; |
| 529 | 527 |
| 530 int result = (frame_type == SYN_STREAM) ? | 528 int result = (frame_type == SYN_STREAM) ? |
| 531 OnRequestHeadersSent() : OnDataSent(frame_size); | 529 OnRequestHeadersSent() : OnDataSent(frame_size); |
| 532 if (result == ERR_IO_PENDING) { | 530 if (result == ERR_IO_PENDING) { |
| 533 // The write operation hasn't completed yet. | 531 // The write operation hasn't completed yet. |
| 534 return; | 532 return; |
| 535 } | 533 } |
| 536 | 534 |
| 537 if (pending_send_status_ == NO_MORE_DATA_TO_SEND) { | 535 if (pending_send_status_ == NO_MORE_DATA_TO_SEND) { |
| 538 // TODO(jgraettinger): Once HALF_CLOSED_REMOTE is added, | 536 if(io_state_ == STATE_OPEN) { |
| 539 // we'll need to handle transitions to fully closed here. | 537 io_state_ = STATE_HALF_CLOSED_LOCAL; |
| 540 CHECK_EQ(io_state_, STATE_OPEN); | 538 } else if(io_state_ == STATE_HALF_CLOSED_REMOTE) { |
| 541 io_state_ = STATE_HALF_CLOSED_LOCAL; | 539 io_state_ = STATE_CLOSED; |
| 540 } else { | |
| 541 NOTREACHED() << io_state_; | |
| 542 } | |
| 542 } | 543 } |
| 543 | 544 |
| 544 // Notify delegate of write completion. May destroy |this|. | 545 // Notify delegate of write completion. Must not destroy |this|. |
|
Johnny
2014/02/14 00:07:08
This looks scary on the surface, but I mixed up th
Ryan Hamilton
2014/02/14 01:47:22
Makes sense. I wonder if we could have a member v
Johnny
2014/02/14 16:27:30
Sure. I've added a |weak_this| guard instead. Same
| |
| 545 CHECK(delegate_); | 546 CHECK(delegate_); |
| 546 if (frame_type == SYN_STREAM) { | 547 if (frame_type == SYN_STREAM) { |
| 547 delegate_->OnRequestHeadersSent(); | 548 delegate_->OnRequestHeadersSent(); |
| 548 } else { | 549 } else { |
| 549 delegate_->OnDataSent(); | 550 delegate_->OnDataSent(); |
| 550 } | 551 } |
| 552 | |
| 553 if (io_state_ == STATE_CLOSED) { | |
| 554 // Deletes |this|. | |
| 555 session_->CloseActiveStream(stream_id_, OK); | |
| 556 } | |
| 551 } | 557 } |
| 552 | 558 |
| 553 int SpdyStream::OnRequestHeadersSent() { | 559 int SpdyStream::OnRequestHeadersSent() { |
| 554 CHECK_EQ(io_state_, STATE_IDLE); | 560 CHECK_EQ(io_state_, STATE_IDLE); |
| 555 CHECK_NE(stream_id_, 0u); | 561 CHECK_NE(stream_id_, 0u); |
| 556 | 562 |
| 557 io_state_ = STATE_OPEN; | 563 io_state_ = STATE_OPEN; |
| 558 return OK; | 564 return OK; |
| 559 } | 565 } |
| 560 | 566 |
| 561 int SpdyStream::OnDataSent(size_t frame_size) { | 567 int SpdyStream::OnDataSent(size_t frame_size) { |
| 562 CHECK_EQ(io_state_, STATE_OPEN); | 568 CHECK(io_state_ == STATE_OPEN || |
| 569 io_state_ == STATE_HALF_CLOSED_REMOTE) << io_state_; | |
| 563 | 570 |
| 564 size_t frame_payload_size = frame_size - session_->GetDataFrameMinimumSize(); | 571 size_t frame_payload_size = frame_size - session_->GetDataFrameMinimumSize(); |
| 565 | 572 |
| 566 CHECK_GE(frame_size, session_->GetDataFrameMinimumSize()); | 573 CHECK_GE(frame_size, session_->GetDataFrameMinimumSize()); |
| 567 CHECK_LE(frame_payload_size, session_->GetDataFrameMaximumPayload()); | 574 CHECK_LE(frame_payload_size, session_->GetDataFrameMaximumPayload()); |
| 568 | 575 |
| 569 send_bytes_ += frame_payload_size; | 576 send_bytes_ += frame_payload_size; |
| 570 | 577 |
| 571 // If more data is available to send, dispatch it and | 578 // If more data is available to send, dispatch it and |
| 572 // return that the write operation is still ongoing. | 579 // return that the write operation is still ongoing. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 647 scoped_ptr<SpdyBufferProducer>( | 654 scoped_ptr<SpdyBufferProducer>( |
| 648 new SynStreamBufferProducer(GetWeakPtr()))); | 655 new SynStreamBufferProducer(GetWeakPtr()))); |
| 649 return ERR_IO_PENDING; | 656 return ERR_IO_PENDING; |
| 650 } | 657 } |
| 651 | 658 |
| 652 void SpdyStream::SendData(IOBuffer* data, | 659 void SpdyStream::SendData(IOBuffer* data, |
| 653 int length, | 660 int length, |
| 654 SpdySendStatus send_status) { | 661 SpdySendStatus send_status) { |
| 655 CHECK_NE(type_, SPDY_PUSH_STREAM); | 662 CHECK_NE(type_, SPDY_PUSH_STREAM); |
| 656 CHECK_EQ(pending_send_status_, MORE_DATA_TO_SEND); | 663 CHECK_EQ(pending_send_status_, MORE_DATA_TO_SEND); |
| 657 CHECK_EQ(io_state_, STATE_OPEN); | 664 CHECK(io_state_ == STATE_OPEN || |
| 665 io_state_ == STATE_HALF_CLOSED_REMOTE) << io_state_; | |
| 658 CHECK(!pending_send_data_.get()); | 666 CHECK(!pending_send_data_.get()); |
| 659 pending_send_data_ = new DrainableIOBuffer(data, length); | 667 pending_send_data_ = new DrainableIOBuffer(data, length); |
| 660 pending_send_status_ = send_status; | 668 pending_send_status_ = send_status; |
| 661 QueueNextDataFrame(); | 669 QueueNextDataFrame(); |
| 662 } | 670 } |
| 663 | 671 |
| 664 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, | 672 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, |
| 665 bool* was_npn_negotiated, | 673 bool* was_npn_negotiated, |
| 666 NextProto* protocol_negotiated) { | 674 NextProto* protocol_negotiated) { |
| 667 return session_->GetSSLInfo( | 675 return session_->GetSSLInfo( |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 689 bool SpdyStream::IsClosed() const { | 697 bool SpdyStream::IsClosed() const { |
| 690 return io_state_ == STATE_CLOSED; | 698 return io_state_ == STATE_CLOSED; |
| 691 } | 699 } |
| 692 | 700 |
| 693 bool SpdyStream::IsLocallyClosed() const { | 701 bool SpdyStream::IsLocallyClosed() const { |
| 694 return io_state_ == STATE_HALF_CLOSED_LOCAL_UNCLAIMED || | 702 return io_state_ == STATE_HALF_CLOSED_LOCAL_UNCLAIMED || |
| 695 io_state_ == STATE_HALF_CLOSED_LOCAL || | 703 io_state_ == STATE_HALF_CLOSED_LOCAL || |
| 696 io_state_ == STATE_CLOSED; | 704 io_state_ == STATE_CLOSED; |
| 697 } | 705 } |
| 698 | 706 |
| 699 bool SpdyStream::IsIdleTemporaryRename() const { | 707 bool SpdyStream::IsIdle() const { |
| 700 return io_state_ == STATE_IDLE; | 708 return io_state_ == STATE_IDLE; |
| 701 } | 709 } |
| 702 | 710 |
| 703 bool SpdyStream::IsOpen() const { | 711 bool SpdyStream::IsOpen() const { |
| 704 return io_state_ == STATE_OPEN; | 712 return io_state_ == STATE_OPEN; |
| 705 } | 713 } |
| 706 | 714 |
| 707 NextProto SpdyStream::GetProtocol() const { | 715 NextProto SpdyStream::GetProtocol() const { |
| 708 return session_->protocol(); | 716 return session_->protocol(); |
| 709 } | 717 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 755 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", | 763 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", |
| 756 recv_last_byte_time_ - effective_send_time); | 764 recv_last_byte_time_ - effective_send_time); |
| 757 | 765 |
| 758 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); | 766 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); |
| 759 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); | 767 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); |
| 760 } | 768 } |
| 761 | 769 |
| 762 void SpdyStream::QueueNextDataFrame() { | 770 void SpdyStream::QueueNextDataFrame() { |
| 763 // Until the request has been completely sent, we cannot be sure | 771 // Until the request has been completely sent, we cannot be sure |
| 764 // that our stream_id is correct. | 772 // that our stream_id is correct. |
| 765 CHECK_EQ(io_state_, STATE_OPEN); | 773 CHECK(io_state_ == STATE_OPEN || |
| 774 io_state_ == STATE_HALF_CLOSED_REMOTE) << io_state_; | |
| 766 CHECK_GT(stream_id_, 0u); | 775 CHECK_GT(stream_id_, 0u); |
| 767 CHECK(pending_send_data_.get()); | 776 CHECK(pending_send_data_.get()); |
| 768 CHECK_GT(pending_send_data_->BytesRemaining(), 0); | 777 CHECK_GT(pending_send_data_->BytesRemaining(), 0); |
| 769 | 778 |
| 770 SpdyDataFlags flags = | 779 SpdyDataFlags flags = |
| 771 (pending_send_status_ == NO_MORE_DATA_TO_SEND) ? | 780 (pending_send_status_ == NO_MORE_DATA_TO_SEND) ? |
| 772 DATA_FLAG_FIN : DATA_FLAG_NONE; | 781 DATA_FLAG_FIN : DATA_FLAG_NONE; |
| 773 scoped_ptr<SpdyBuffer> data_buffer( | 782 scoped_ptr<SpdyBuffer> data_buffer( |
| 774 session_->CreateDataBuffer(stream_id_, | 783 session_->CreateDataBuffer(stream_id_, |
| 775 pending_send_data_.get(), | 784 pending_send_data_.get(), |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 874 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, | 883 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, |
| 875 state); | 884 state); |
| 876 break; | 885 break; |
| 877 } | 886 } |
| 878 return description; | 887 return description; |
| 879 } | 888 } |
| 880 | 889 |
| 881 #undef STATE_CASE | 890 #undef STATE_CASE |
| 882 | 891 |
| 883 } // namespace net | 892 } // namespace net |
| OLD | NEW |