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 } |
| 543 } |
| 544 // Notify delegate of write completion. Must not destroy |this|. |
| 545 CHECK(delegate_); |
| 546 { |
| 547 base::WeakPtr<SpdyStream> weak_this = GetWeakPtr(); |
| 548 if (frame_type == SYN_STREAM) { |
| 549 delegate_->OnRequestHeadersSent(); |
| 550 } else { |
| 551 delegate_->OnDataSent(); |
| 552 } |
| 553 CHECK(weak_this); |
542 } | 554 } |
543 | 555 |
544 // Notify delegate of write completion. May destroy |this|. | 556 if (io_state_ == STATE_CLOSED) { |
545 CHECK(delegate_); | 557 // Deletes |this|. |
546 if (frame_type == SYN_STREAM) { | 558 session_->CloseActiveStream(stream_id_, OK); |
547 delegate_->OnRequestHeadersSent(); | |
548 } else { | |
549 delegate_->OnDataSent(); | |
550 } | 559 } |
551 } | 560 } |
552 | 561 |
553 int SpdyStream::OnRequestHeadersSent() { | 562 int SpdyStream::OnRequestHeadersSent() { |
554 CHECK_EQ(io_state_, STATE_IDLE); | 563 CHECK_EQ(io_state_, STATE_IDLE); |
555 CHECK_NE(stream_id_, 0u); | 564 CHECK_NE(stream_id_, 0u); |
556 | 565 |
557 io_state_ = STATE_OPEN; | 566 io_state_ = STATE_OPEN; |
558 return OK; | 567 return OK; |
559 } | 568 } |
560 | 569 |
561 int SpdyStream::OnDataSent(size_t frame_size) { | 570 int SpdyStream::OnDataSent(size_t frame_size) { |
562 CHECK_EQ(io_state_, STATE_OPEN); | 571 CHECK(io_state_ == STATE_OPEN || |
| 572 io_state_ == STATE_HALF_CLOSED_REMOTE) << io_state_; |
563 | 573 |
564 size_t frame_payload_size = frame_size - session_->GetDataFrameMinimumSize(); | 574 size_t frame_payload_size = frame_size - session_->GetDataFrameMinimumSize(); |
565 | 575 |
566 CHECK_GE(frame_size, session_->GetDataFrameMinimumSize()); | 576 CHECK_GE(frame_size, session_->GetDataFrameMinimumSize()); |
567 CHECK_LE(frame_payload_size, session_->GetDataFrameMaximumPayload()); | 577 CHECK_LE(frame_payload_size, session_->GetDataFrameMaximumPayload()); |
568 | 578 |
569 send_bytes_ += frame_payload_size; | 579 send_bytes_ += frame_payload_size; |
570 | 580 |
571 // If more data is available to send, dispatch it and | 581 // If more data is available to send, dispatch it and |
572 // return that the write operation is still ongoing. | 582 // 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>( | 657 scoped_ptr<SpdyBufferProducer>( |
648 new SynStreamBufferProducer(GetWeakPtr()))); | 658 new SynStreamBufferProducer(GetWeakPtr()))); |
649 return ERR_IO_PENDING; | 659 return ERR_IO_PENDING; |
650 } | 660 } |
651 | 661 |
652 void SpdyStream::SendData(IOBuffer* data, | 662 void SpdyStream::SendData(IOBuffer* data, |
653 int length, | 663 int length, |
654 SpdySendStatus send_status) { | 664 SpdySendStatus send_status) { |
655 CHECK_NE(type_, SPDY_PUSH_STREAM); | 665 CHECK_NE(type_, SPDY_PUSH_STREAM); |
656 CHECK_EQ(pending_send_status_, MORE_DATA_TO_SEND); | 666 CHECK_EQ(pending_send_status_, MORE_DATA_TO_SEND); |
657 CHECK_EQ(io_state_, STATE_OPEN); | 667 CHECK(io_state_ == STATE_OPEN || |
| 668 io_state_ == STATE_HALF_CLOSED_REMOTE) << io_state_; |
658 CHECK(!pending_send_data_.get()); | 669 CHECK(!pending_send_data_.get()); |
659 pending_send_data_ = new DrainableIOBuffer(data, length); | 670 pending_send_data_ = new DrainableIOBuffer(data, length); |
660 pending_send_status_ = send_status; | 671 pending_send_status_ = send_status; |
661 QueueNextDataFrame(); | 672 QueueNextDataFrame(); |
662 } | 673 } |
663 | 674 |
664 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, | 675 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, |
665 bool* was_npn_negotiated, | 676 bool* was_npn_negotiated, |
666 NextProto* protocol_negotiated) { | 677 NextProto* protocol_negotiated) { |
667 return session_->GetSSLInfo( | 678 return session_->GetSSLInfo( |
(...skipping 21 matching lines...) Expand all Loading... |
689 bool SpdyStream::IsClosed() const { | 700 bool SpdyStream::IsClosed() const { |
690 return io_state_ == STATE_CLOSED; | 701 return io_state_ == STATE_CLOSED; |
691 } | 702 } |
692 | 703 |
693 bool SpdyStream::IsLocallyClosed() const { | 704 bool SpdyStream::IsLocallyClosed() const { |
694 return io_state_ == STATE_HALF_CLOSED_LOCAL_UNCLAIMED || | 705 return io_state_ == STATE_HALF_CLOSED_LOCAL_UNCLAIMED || |
695 io_state_ == STATE_HALF_CLOSED_LOCAL || | 706 io_state_ == STATE_HALF_CLOSED_LOCAL || |
696 io_state_ == STATE_CLOSED; | 707 io_state_ == STATE_CLOSED; |
697 } | 708 } |
698 | 709 |
699 bool SpdyStream::IsIdleTemporaryRename() const { | 710 bool SpdyStream::IsIdle() const { |
700 return io_state_ == STATE_IDLE; | 711 return io_state_ == STATE_IDLE; |
701 } | 712 } |
702 | 713 |
703 bool SpdyStream::IsOpen() const { | 714 bool SpdyStream::IsOpen() const { |
704 return io_state_ == STATE_OPEN; | 715 return io_state_ == STATE_OPEN; |
705 } | 716 } |
706 | 717 |
707 NextProto SpdyStream::GetProtocol() const { | 718 NextProto SpdyStream::GetProtocol() const { |
708 return session_->protocol(); | 719 return session_->protocol(); |
709 } | 720 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", | 766 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", |
756 recv_last_byte_time_ - effective_send_time); | 767 recv_last_byte_time_ - effective_send_time); |
757 | 768 |
758 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); | 769 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); |
759 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); | 770 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); |
760 } | 771 } |
761 | 772 |
762 void SpdyStream::QueueNextDataFrame() { | 773 void SpdyStream::QueueNextDataFrame() { |
763 // Until the request has been completely sent, we cannot be sure | 774 // Until the request has been completely sent, we cannot be sure |
764 // that our stream_id is correct. | 775 // that our stream_id is correct. |
765 CHECK_EQ(io_state_, STATE_OPEN); | 776 CHECK(io_state_ == STATE_OPEN || |
| 777 io_state_ == STATE_HALF_CLOSED_REMOTE) << io_state_; |
766 CHECK_GT(stream_id_, 0u); | 778 CHECK_GT(stream_id_, 0u); |
767 CHECK(pending_send_data_.get()); | 779 CHECK(pending_send_data_.get()); |
768 CHECK_GT(pending_send_data_->BytesRemaining(), 0); | 780 CHECK_GT(pending_send_data_->BytesRemaining(), 0); |
769 | 781 |
770 SpdyDataFlags flags = | 782 SpdyDataFlags flags = |
771 (pending_send_status_ == NO_MORE_DATA_TO_SEND) ? | 783 (pending_send_status_ == NO_MORE_DATA_TO_SEND) ? |
772 DATA_FLAG_FIN : DATA_FLAG_NONE; | 784 DATA_FLAG_FIN : DATA_FLAG_NONE; |
773 scoped_ptr<SpdyBuffer> data_buffer( | 785 scoped_ptr<SpdyBuffer> data_buffer( |
774 session_->CreateDataBuffer(stream_id_, | 786 session_->CreateDataBuffer(stream_id_, |
775 pending_send_data_.get(), | 787 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, | 886 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, |
875 state); | 887 state); |
876 break; | 888 break; |
877 } | 889 } |
878 return description; | 890 return description; |
879 } | 891 } |
880 | 892 |
881 #undef STATE_CASE | 893 #undef STATE_CASE |
882 | 894 |
883 } // namespace net | 895 } // namespace net |
OLD | NEW |