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 <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 |