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 <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
122 priority_(priority), | 122 priority_(priority), |
123 slot_(0), | 123 slot_(0), |
124 send_stalled_by_flow_control_(false), | 124 send_stalled_by_flow_control_(false), |
125 send_window_size_(initial_send_window_size), | 125 send_window_size_(initial_send_window_size), |
126 recv_window_size_(initial_recv_window_size), | 126 recv_window_size_(initial_recv_window_size), |
127 unacked_recv_window_bytes_(0), | 127 unacked_recv_window_bytes_(0), |
128 pushed_(pushed), | 128 pushed_(pushed), |
129 response_received_(false), | 129 response_received_(false), |
130 session_(session), | 130 session_(session), |
131 delegate_(NULL), | 131 delegate_(NULL), |
132 pending_send_flags_(DATA_FLAG_NONE), | |
132 request_time_(base::Time::Now()), | 133 request_time_(base::Time::Now()), |
133 response_(new SpdyHeaderBlock), | 134 response_(new SpdyHeaderBlock), |
134 io_state_(STATE_NONE), | 135 io_state_(STATE_NONE), |
135 response_status_(OK), | 136 response_status_(OK), |
136 has_upload_data_(false), | 137 has_upload_data_(false), |
137 net_log_(net_log), | 138 net_log_(net_log), |
138 send_bytes_(0), | 139 send_bytes_(0), |
139 recv_bytes_(0), | 140 recv_bytes_(0), |
140 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE), | 141 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE), |
141 just_completed_frame_type_(DATA), | 142 just_completed_frame_type_(DATA), |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
618 DCHECK(!has_upload_data_); | 619 DCHECK(!has_upload_data_); |
619 DCHECK(response_received()); | 620 DCHECK(response_received()); |
620 send_time_ = base::TimeTicks::Now(); | 621 send_time_ = base::TimeTicks::Now(); |
621 return ERR_IO_PENDING; | 622 return ERR_IO_PENDING; |
622 } | 623 } |
623 CHECK_EQ(STATE_NONE, io_state_); | 624 CHECK_EQ(STATE_NONE, io_state_); |
624 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; | 625 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; |
625 return DoLoop(OK); | 626 return DoLoop(OK); |
626 } | 627 } |
627 | 628 |
628 void SpdyStream::QueueHeaders(scoped_ptr<SpdyHeaderBlock> headers) { | 629 void SpdyStream::SendHeaders(scoped_ptr<SpdyHeaderBlock> headers) { |
629 // Until the first headers by SYN_STREAM have been completely sent, we can | 630 // Until the first headers by SYN_STREAM have been completely sent, we can |
630 // not be sure that our stream_id is correct. | 631 // not be sure that our stream_id is correct. |
631 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); | 632 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); |
632 CHECK_GT(stream_id_, 0u); | 633 CHECK_GT(stream_id_, 0u); |
633 | 634 |
634 session_->EnqueueStreamWrite( | 635 session_->EnqueueStreamWrite( |
635 GetWeakPtr(), HEADERS, | 636 GetWeakPtr(), HEADERS, |
636 scoped_ptr<SpdyBufferProducer>( | 637 scoped_ptr<SpdyBufferProducer>( |
637 new HeaderBufferProducer(GetWeakPtr(), headers.Pass()))); | 638 new HeaderBufferProducer(GetWeakPtr(), headers.Pass()))); |
638 } | 639 } |
639 | 640 |
640 void SpdyStream::QueueStreamData(IOBuffer* data, | 641 void SpdyStream::SendStreamData(IOBuffer* data, |
641 int length, | 642 int length, |
642 SpdyDataFlags flags) { | 643 SpdyDataFlags flags) { |
643 // Until the headers have been completely sent, we can not be sure | 644 CHECK(!pending_send_data_); |
644 // that our stream_id is correct. | 645 pending_send_data_ = new DrainableIOBuffer(data, length); |
645 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); | 646 pending_send_flags_ = flags; |
646 CHECK_GT(stream_id_, 0u); | 647 QueueNextDataFrame(); |
647 | |
648 scoped_ptr<SpdyBuffer> data_buffer(session_->CreateDataBuffer( | |
649 stream_id_, data, length, flags)); | |
650 // We'll get called again by PossiblyResumeIfSendStalled(). | |
651 if (!data_buffer) | |
652 return; | |
653 | |
654 if (session_->flow_control_state() >= SpdySession::FLOW_CONTROL_STREAM) { | |
655 DCHECK_GE(data_buffer->GetRemainingSize(), | |
656 session_->GetDataFrameMinimumSize()); | |
657 size_t payload_size = | |
658 data_buffer->GetRemainingSize() - session_->GetDataFrameMinimumSize(); | |
659 DCHECK_LE(payload_size, session_->GetDataFrameMaximumPayload()); | |
660 DecreaseSendWindowSize(static_cast<int32>(payload_size)); | |
661 // This currently isn't strictly needed, since write frames are | |
662 // discarded only if the stream is about to be closed. But have it | |
663 // here anyway just in case this changes. | |
664 data_buffer->AddConsumeCallback( | |
665 base::Bind(&SpdyStream::OnWriteBufferConsumed, | |
666 GetWeakPtr(), payload_size)); | |
667 } | |
668 | |
669 session_->EnqueueStreamWrite( | |
670 GetWeakPtr(), DATA, | |
671 scoped_ptr<SpdyBufferProducer>( | |
672 new SimpleBufferProducer(data_buffer.Pass()))); | |
673 } | 648 } |
674 | 649 |
675 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, | 650 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, |
676 bool* was_npn_negotiated, | 651 bool* was_npn_negotiated, |
677 NextProto* protocol_negotiated) { | 652 NextProto* protocol_negotiated) { |
678 return session_->GetSSLInfo( | 653 return session_->GetSSLInfo( |
679 ssl_info, was_npn_negotiated, protocol_negotiated); | 654 ssl_info, was_npn_negotiated, protocol_negotiated); |
680 } | 655 } |
681 | 656 |
682 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { | 657 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { |
683 return session_->GetSSLCertRequestInfo(cert_request_info); | 658 return session_->GetSSLCertRequestInfo(cert_request_info); |
684 } | 659 } |
685 | 660 |
686 void SpdyStream::PossiblyResumeIfSendStalled() { | 661 void SpdyStream::PossiblyResumeIfSendStalled() { |
687 DCHECK(!closed()); | 662 DCHECK(!closed()); |
688 | 663 |
689 if (send_stalled_by_flow_control_ && !session_->IsSendStalled() && | 664 if (send_stalled_by_flow_control_ && !session_->IsSendStalled() && |
690 send_window_size_ > 0) { | 665 send_window_size_ > 0) { |
691 net_log_.AddEvent( | 666 net_log_.AddEvent( |
692 NetLog::TYPE_SPDY_STREAM_FLOW_CONTROL_UNSTALLED, | 667 NetLog::TYPE_SPDY_STREAM_FLOW_CONTROL_UNSTALLED, |
693 NetLog::IntegerCallback("stream_id", stream_id_)); | 668 NetLog::IntegerCallback("stream_id", stream_id_)); |
694 send_stalled_by_flow_control_ = false; | 669 send_stalled_by_flow_control_ = false; |
695 io_state_ = STATE_SEND_BODY; | 670 QueueNextDataFrame(); |
696 DoLoop(OK); | |
697 } | 671 } |
698 } | 672 } |
699 | 673 |
700 base::WeakPtr<SpdyStream> SpdyStream::GetWeakPtr() { | 674 base::WeakPtr<SpdyStream> SpdyStream::GetWeakPtr() { |
701 return weak_ptr_factory_.GetWeakPtr(); | 675 return weak_ptr_factory_.GetWeakPtr(); |
702 } | 676 } |
703 | 677 |
704 bool SpdyStream::HasUrl() const { | 678 bool SpdyStream::HasUrl() const { |
705 if (pushed_) | 679 if (pushed_) |
706 return response_received(); | 680 return response_received(); |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
896 io_state_ = | 870 io_state_ = |
897 (delegate_->OnSendHeadersComplete() == MORE_DATA_TO_SEND) ? | 871 (delegate_->OnSendHeadersComplete() == MORE_DATA_TO_SEND) ? |
898 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; | 872 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; |
899 | 873 |
900 return OK; | 874 return OK; |
901 } | 875 } |
902 | 876 |
903 // DoSendBody is called to send the optional body for the request. This call | 877 // DoSendBody is called to send the optional body for the request. This call |
904 // will also be called as each write of a chunk of the body completes. | 878 // will also be called as each write of a chunk of the body completes. |
905 int SpdyStream::DoSendBody() { | 879 int SpdyStream::DoSendBody() { |
906 // If we're already in the STATE_SEND_BODY state, then we've already | |
907 // sent a portion of the body. In that case, we need to first consume | |
908 // the bytes written in the body stream. Note that the bytes written is | |
909 // the number of bytes in the frame that were written, only consume the | |
910 // data portion, of course. | |
911 io_state_ = STATE_SEND_BODY_COMPLETE; | 880 io_state_ = STATE_SEND_BODY_COMPLETE; |
912 CHECK(delegate_); | 881 CHECK(delegate_); |
913 delegate_->OnSendBody(); | 882 delegate_->OnSendBody(); |
914 return ERR_IO_PENDING; | 883 return ERR_IO_PENDING; |
915 } | 884 } |
916 | 885 |
917 int SpdyStream::DoSendBodyComplete(int result) { | 886 int SpdyStream::DoSendBodyComplete(int result) { |
918 if (result != OK) | 887 if (result != OK) |
919 return result; | 888 return result; |
920 | 889 |
921 if (just_completed_frame_type_ != DATA) { | 890 if (just_completed_frame_type_ != DATA) { |
922 NOTREACHED(); | 891 NOTREACHED(); |
923 return ERR_UNEXPECTED; | 892 return ERR_UNEXPECTED; |
924 } | 893 } |
925 | 894 |
926 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) { | 895 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) { |
927 NOTREACHED(); | 896 NOTREACHED(); |
928 return ERR_UNEXPECTED; | 897 return ERR_UNEXPECTED; |
929 } | 898 } |
930 | 899 |
931 size_t frame_payload_size = | 900 size_t frame_payload_size = |
932 just_completed_frame_size_ - session_->GetDataFrameMinimumSize(); | 901 just_completed_frame_size_ - session_->GetDataFrameMinimumSize(); |
933 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) { | 902 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) { |
934 NOTREACHED(); | 903 NOTREACHED(); |
935 return ERR_UNEXPECTED; | 904 return ERR_UNEXPECTED; |
936 } | 905 } |
937 | 906 |
907 send_bytes_ += frame_payload_size; | |
908 | |
909 pending_send_data_->DidConsume(frame_payload_size); | |
910 if (pending_send_data_->BytesRemaining() > 0) { | |
911 io_state_ = STATE_SEND_BODY_COMPLETE; | |
912 QueueNextDataFrame(); | |
913 return ERR_IO_PENDING; | |
914 } | |
915 | |
916 pending_send_data_ = NULL; | |
917 pending_send_flags_ = DATA_FLAG_NONE; | |
918 | |
938 if (!delegate_) { | 919 if (!delegate_) { |
939 NOTREACHED(); | 920 NOTREACHED(); |
940 return ERR_UNEXPECTED; | 921 return ERR_UNEXPECTED; |
941 } | 922 } |
942 | 923 |
943 send_bytes_ += frame_payload_size; | |
944 | |
945 io_state_ = | 924 io_state_ = |
946 (delegate_->OnSendBodyComplete(frame_payload_size) == MORE_DATA_TO_SEND) ? | 925 (delegate_->OnSendBodyComplete() == MORE_DATA_TO_SEND) ? |
947 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; | 926 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; |
948 | 927 |
949 return OK; | 928 return OK; |
950 } | 929 } |
951 | 930 |
952 int SpdyStream::DoOpen() { | 931 int SpdyStream::DoOpen() { |
953 io_state_ = STATE_OPEN; | 932 io_state_ = STATE_OPEN; |
954 | 933 |
955 switch (just_completed_frame_type_) { | 934 switch (just_completed_frame_type_) { |
956 case DATA: { | 935 case DATA: { |
957 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) { | 936 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) { |
958 NOTREACHED(); | 937 NOTREACHED(); |
959 return ERR_UNEXPECTED; | 938 return ERR_UNEXPECTED; |
960 } | 939 } |
961 | 940 |
962 size_t frame_payload_size = | 941 size_t frame_payload_size = |
963 just_completed_frame_size_ - session_->GetDataFrameMinimumSize(); | 942 just_completed_frame_size_ - session_->GetDataFrameMinimumSize(); |
964 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) { | 943 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) { |
965 NOTREACHED(); | 944 NOTREACHED(); |
966 return ERR_UNEXPECTED; | 945 return ERR_UNEXPECTED; |
967 } | 946 } |
968 | 947 |
969 send_bytes_ += frame_payload_size; | 948 send_bytes_ += frame_payload_size; |
949 | |
950 pending_send_data_->DidConsume(frame_payload_size); | |
951 if (pending_send_data_->BytesRemaining() > 0) { | |
952 QueueNextDataFrame(); | |
953 return ERR_IO_PENDING; | |
954 } | |
955 | |
956 pending_send_data_ = NULL; | |
957 pending_send_flags_ = DATA_FLAG_NONE; | |
Ryan Hamilton
2013/05/23 04:12:00
It's a pity that lines 948-957 are almost complete
akalin
2013/05/23 05:29:38
I did think about this. The problem is, factoring
Ryan Hamilton
2013/05/23 16:26:30
Sounds great. I thought about a helper that retur
| |
958 | |
970 if (delegate_) | 959 if (delegate_) |
971 delegate_->OnDataSent(frame_payload_size); | 960 delegate_->OnDataSent(); |
961 | |
972 break; | 962 break; |
973 } | 963 } |
974 | 964 |
975 case HEADERS: | 965 case HEADERS: |
976 if (delegate_) | 966 if (delegate_) |
977 delegate_->OnHeadersSent(); | 967 delegate_->OnHeadersSent(); |
978 break; | 968 break; |
979 | 969 |
980 default: | 970 default: |
981 NOTREACHED(); | 971 NOTREACHED(); |
(...skipping 13 matching lines...) Expand all Loading... | |
995 recv_first_byte_time_ - send_time_); | 985 recv_first_byte_time_ - send_time_); |
996 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", | 986 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", |
997 recv_last_byte_time_ - recv_first_byte_time_); | 987 recv_last_byte_time_ - recv_first_byte_time_); |
998 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", | 988 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", |
999 recv_last_byte_time_ - send_time_); | 989 recv_last_byte_time_ - send_time_); |
1000 | 990 |
1001 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); | 991 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); |
1002 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); | 992 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); |
1003 } | 993 } |
1004 | 994 |
995 void SpdyStream::QueueNextDataFrame() { | |
996 // Until the headers have been completely sent, we can not be sure | |
997 // that our stream_id is correct. | |
998 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); | |
999 CHECK_GT(stream_id_, 0u); | |
1000 CHECK(pending_send_data_); | |
1001 CHECK_GT(pending_send_data_->BytesRemaining(), 0); | |
1002 | |
1003 scoped_ptr<SpdyBuffer> data_buffer(session_->CreateDataBuffer( | |
1004 stream_id_, | |
1005 pending_send_data_, pending_send_data_->BytesRemaining(), | |
1006 pending_send_flags_)); | |
1007 // We'll get called again by PossiblyResumeIfSendStalled(). | |
1008 if (!data_buffer) | |
1009 return; | |
1010 | |
1011 if (session_->flow_control_state() >= SpdySession::FLOW_CONTROL_STREAM) { | |
1012 DCHECK_GE(data_buffer->GetRemainingSize(), | |
1013 session_->GetDataFrameMinimumSize()); | |
1014 size_t payload_size = | |
1015 data_buffer->GetRemainingSize() - session_->GetDataFrameMinimumSize(); | |
1016 DCHECK_LE(payload_size, session_->GetDataFrameMaximumPayload()); | |
1017 DecreaseSendWindowSize(static_cast<int32>(payload_size)); | |
1018 // This currently isn't strictly needed, since write frames are | |
1019 // discarded only if the stream is about to be closed. But have it | |
1020 // here anyway just in case this changes. | |
1021 data_buffer->AddConsumeCallback( | |
1022 base::Bind(&SpdyStream::OnWriteBufferConsumed, | |
1023 GetWeakPtr(), payload_size)); | |
1024 } | |
1025 | |
1026 session_->EnqueueStreamWrite( | |
1027 GetWeakPtr(), DATA, | |
1028 scoped_ptr<SpdyBufferProducer>( | |
1029 new SimpleBufferProducer(data_buffer.Pass()))); | |
1030 } | |
1031 | |
1005 } // namespace net | 1032 } // namespace net |
OLD | NEW |