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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
71 } | 71 } |
72 DCHECK_GT(stream_->stream_id(), 0u); | 72 DCHECK_GT(stream_->stream_id(), 0u); |
73 return scoped_ptr<SpdyBuffer>( | 73 return scoped_ptr<SpdyBuffer>( |
74 new SpdyBuffer(stream_->ProduceSynStreamFrame())); | 74 new SpdyBuffer(stream_->ProduceSynStreamFrame())); |
75 } | 75 } |
76 | 76 |
77 private: | 77 private: |
78 const base::WeakPtr<SpdyStream> stream_; | 78 const base::WeakPtr<SpdyStream> stream_; |
79 }; | 79 }; |
80 | 80 |
81 SpdyStream::SpdyStream(SpdySession* session, | 81 SpdyStream::SpdyStream(SpdyStreamType type, |
82 SpdySession* session, | |
82 const std::string& path, | 83 const std::string& path, |
83 RequestPriority priority, | 84 RequestPriority priority, |
84 int32 initial_send_window_size, | 85 int32 initial_send_window_size, |
85 int32 initial_recv_window_size, | 86 int32 initial_recv_window_size, |
86 bool pushed, | |
87 const BoundNetLog& net_log) | 87 const BoundNetLog& net_log) |
88 : weak_ptr_factory_(this), | 88 : type_(type), |
89 weak_ptr_factory_(this), | |
89 in_do_loop_(false), | 90 in_do_loop_(false), |
90 continue_buffering_data_(true), | 91 continue_buffering_data_(true), |
91 stream_id_(0), | 92 stream_id_(0), |
92 path_(path), | 93 path_(path), |
93 priority_(priority), | 94 priority_(priority), |
94 slot_(0), | 95 slot_(0), |
95 send_stalled_by_flow_control_(false), | 96 send_stalled_by_flow_control_(false), |
96 send_window_size_(initial_send_window_size), | 97 send_window_size_(initial_send_window_size), |
97 recv_window_size_(initial_recv_window_size), | 98 recv_window_size_(initial_recv_window_size), |
98 unacked_recv_window_bytes_(0), | 99 unacked_recv_window_bytes_(0), |
99 pushed_(pushed), | |
100 response_received_(false), | 100 response_received_(false), |
101 session_(session), | 101 session_(session), |
102 delegate_(NULL), | 102 delegate_(NULL), |
103 send_status_(MORE_DATA_TO_SEND), | 103 send_status_( |
104 (type_ == SPDY_PUSH_STREAM) ? | |
105 NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND), | |
104 request_time_(base::Time::Now()), | 106 request_time_(base::Time::Now()), |
105 response_(new SpdyHeaderBlock), | 107 response_(new SpdyHeaderBlock), |
106 io_state_(STATE_NONE), | 108 io_state_(STATE_NONE), |
107 response_status_(OK), | 109 response_status_(OK), |
108 net_log_(net_log), | 110 net_log_(net_log), |
109 send_bytes_(0), | 111 send_bytes_(0), |
110 recv_bytes_(0), | 112 recv_bytes_(0), |
111 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE), | 113 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE), |
112 just_completed_frame_type_(DATA), | 114 just_completed_frame_type_(DATA), |
113 just_completed_frame_size_(0) { | 115 just_completed_frame_size_(0) { |
114 } | 116 } |
115 | 117 |
116 SpdyStream::~SpdyStream() { | 118 SpdyStream::~SpdyStream() { |
117 CHECK(!in_do_loop_); | 119 CHECK(!in_do_loop_); |
118 UpdateHistograms(); | 120 UpdateHistograms(); |
119 } | 121 } |
120 | 122 |
121 void SpdyStream::SetDelegate(Delegate* delegate) { | 123 void SpdyStream::SetDelegate(Delegate* delegate) { |
122 CHECK(delegate); | 124 CHECK(delegate); |
123 delegate_ = delegate; | 125 delegate_ = delegate; |
124 | 126 |
125 if (pushed_) { | 127 if (type_ == SPDY_PUSH_STREAM) { |
126 CHECK(response_received()); | 128 CHECK(response_received()); |
127 base::MessageLoop::current()->PostTask( | 129 base::MessageLoop::current()->PostTask( |
128 FROM_HERE, | 130 FROM_HERE, |
129 base::Bind(&SpdyStream::PushedStreamReplayData, GetWeakPtr())); | 131 base::Bind(&SpdyStream::PushedStreamReplayData, GetWeakPtr())); |
130 } else { | 132 } else { |
131 continue_buffering_data_ = false; | 133 continue_buffering_data_ = false; |
132 } | 134 } |
133 } | 135 } |
134 | 136 |
135 void SpdyStream::PushedStreamReplayData() { | 137 void SpdyStream::PushedStreamReplayData() { |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
372 metrics_.StartStream(); | 374 metrics_.StartStream(); |
373 | 375 |
374 DCHECK(response_->empty()); | 376 DCHECK(response_->empty()); |
375 *response_ = response; // TODO(ukai): avoid copy. | 377 *response_ = response; // TODO(ukai): avoid copy. |
376 | 378 |
377 recv_first_byte_time_ = base::TimeTicks::Now(); | 379 recv_first_byte_time_ = base::TimeTicks::Now(); |
378 response_time_ = base::Time::Now(); | 380 response_time_ = base::Time::Now(); |
379 | 381 |
380 // If we receive a response before we are in STATE_WAITING_FOR_RESPONSE, then | 382 // If we receive a response before we are in STATE_WAITING_FOR_RESPONSE, then |
381 // the server has sent the SYN_REPLY too early. | 383 // the server has sent the SYN_REPLY too early. |
382 if (!pushed_ && io_state_ != STATE_WAITING_FOR_RESPONSE) | 384 if (type_ != SPDY_PUSH_STREAM && io_state_ != STATE_WAITING_FOR_RESPONSE) |
383 return ERR_SPDY_PROTOCOL_ERROR; | 385 return ERR_SPDY_PROTOCOL_ERROR; |
384 if (pushed_) | 386 if (type_ == SPDY_PUSH_STREAM) |
385 CHECK_EQ(io_state_, STATE_NONE); | 387 CHECK_EQ(io_state_, STATE_NONE); |
386 io_state_ = STATE_OPEN; | 388 io_state_ = STATE_OPEN; |
387 | 389 |
388 // Append all the headers into the response header block. | 390 // Append all the headers into the response header block. |
389 for (SpdyHeaderBlock::const_iterator it = response.begin(); | 391 for (SpdyHeaderBlock::const_iterator it = response.begin(); |
390 it != response.end(); ++it) { | 392 it != response.end(); ++it) { |
391 // Disallow uppercase headers. | 393 // Disallow uppercase headers. |
392 if (ContainsUpperAscii(it->first)) { | 394 if (ContainsUpperAscii(it->first)) { |
393 session_->ResetStream(stream_id_, priority_, RST_STREAM_PROTOCOL_ERROR, | 395 session_->ResetStream(stream_id_, priority_, RST_STREAM_PROTOCOL_ERROR, |
394 "Upper case characters in header: " + it->first); | 396 "Upper case characters in header: " + it->first); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
556 CHECK(!in_do_loop_); | 558 CHECK(!in_do_loop_); |
557 if (stream_id_ != 0) { | 559 if (stream_id_ != 0) { |
558 session_->CloseActiveStream(stream_id_, OK); | 560 session_->CloseActiveStream(stream_id_, OK); |
559 } else { | 561 } else { |
560 session_->CloseCreatedStream(GetWeakPtr(), OK); | 562 session_->CloseCreatedStream(GetWeakPtr(), OK); |
561 } | 563 } |
562 } | 564 } |
563 | 565 |
564 int SpdyStream::SendRequestHeaders(scoped_ptr<SpdyHeaderBlock> headers, | 566 int SpdyStream::SendRequestHeaders(scoped_ptr<SpdyHeaderBlock> headers, |
565 SpdySendStatus send_status) { | 567 SpdySendStatus send_status) { |
568 CHECK_NE(type_, SPDY_PUSH_STREAM); | |
Ryan Hamilton
2013/05/26 15:33:49
I don't think this is right, is it? When a reques
| |
566 CHECK_EQ(send_status_, MORE_DATA_TO_SEND); | 569 CHECK_EQ(send_status_, MORE_DATA_TO_SEND); |
567 CHECK(!request_); | 570 CHECK(!request_); |
571 CHECK(!pending_send_data_); | |
572 CHECK_EQ(io_state_, STATE_NONE); | |
568 request_ = headers.Pass(); | 573 request_ = headers.Pass(); |
569 // Pushed streams do not send any data, and should always be | |
570 // idle. However, we still want to return IO_PENDING to mimic | |
571 // non-push behavior. | |
572 send_status_ = send_status; | 574 send_status_ = send_status; |
573 if (pushed_) { | |
574 DCHECK(is_idle()); | |
575 DCHECK_EQ(send_status_, NO_MORE_DATA_TO_SEND); | |
576 DCHECK(response_received()); | |
577 send_time_ = base::TimeTicks::Now(); | |
578 return ERR_IO_PENDING; | |
579 } | |
580 CHECK_EQ(STATE_NONE, io_state_); | |
581 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; | 575 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; |
582 return DoLoop(OK); | 576 return DoLoop(OK); |
583 } | 577 } |
584 | 578 |
585 void SpdyStream::SendStreamData(IOBuffer* data, | 579 void SpdyStream::SendStreamData(IOBuffer* data, |
586 int length, | 580 int length, |
587 SpdySendStatus send_status) { | 581 SpdySendStatus send_status) { |
582 CHECK_NE(type_, SPDY_PUSH_STREAM); | |
588 CHECK_EQ(send_status_, MORE_DATA_TO_SEND); | 583 CHECK_EQ(send_status_, MORE_DATA_TO_SEND); |
584 CHECK_GE(io_state_, STATE_SEND_BODY); | |
589 CHECK(!pending_send_data_); | 585 CHECK(!pending_send_data_); |
590 pending_send_data_ = new DrainableIOBuffer(data, length); | 586 pending_send_data_ = new DrainableIOBuffer(data, length); |
591 send_status_ = send_status; | 587 send_status_ = send_status; |
592 QueueNextDataFrame(); | 588 QueueNextDataFrame(); |
593 } | 589 } |
594 | 590 |
595 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, | 591 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, |
596 bool* was_npn_negotiated, | 592 bool* was_npn_negotiated, |
597 NextProto* protocol_negotiated) { | 593 NextProto* protocol_negotiated) { |
598 return session_->GetSSLInfo( | 594 return session_->GetSSLInfo( |
(...skipping 15 matching lines...) Expand all Loading... | |
614 send_stalled_by_flow_control_ = false; | 610 send_stalled_by_flow_control_ = false; |
615 QueueNextDataFrame(); | 611 QueueNextDataFrame(); |
616 } | 612 } |
617 } | 613 } |
618 | 614 |
619 base::WeakPtr<SpdyStream> SpdyStream::GetWeakPtr() { | 615 base::WeakPtr<SpdyStream> SpdyStream::GetWeakPtr() { |
620 return weak_ptr_factory_.GetWeakPtr(); | 616 return weak_ptr_factory_.GetWeakPtr(); |
621 } | 617 } |
622 | 618 |
623 bool SpdyStream::HasUrl() const { | 619 bool SpdyStream::HasUrl() const { |
624 if (pushed_) | 620 if (type_ == SPDY_PUSH_STREAM) |
625 return response_received(); | 621 return response_received(); |
626 return request_.get() != NULL; | 622 return request_.get() != NULL; |
627 } | 623 } |
628 | 624 |
629 GURL SpdyStream::GetUrl() const { | 625 GURL SpdyStream::GetUrl() const { |
630 DCHECK(HasUrl()); | 626 DCHECK(HasUrl()); |
631 | 627 |
632 const SpdyHeaderBlock& headers = (pushed_) ? *response_ : *request_; | 628 const SpdyHeaderBlock& headers = |
633 return GetUrlFromHeaderBlock(headers, GetProtocolVersion(), pushed_); | 629 (type_ == SPDY_PUSH_STREAM) ? *response_ : *request_; |
630 return GetUrlFromHeaderBlock(headers, GetProtocolVersion(), | |
631 type_ == SPDY_PUSH_STREAM); | |
634 } | 632 } |
635 | 633 |
636 void SpdyStream::OnGetDomainBoundCertComplete(int result) { | 634 void SpdyStream::OnGetDomainBoundCertComplete(int result) { |
637 DCHECK_EQ(STATE_GET_DOMAIN_BOUND_CERT_COMPLETE, io_state_); | 635 DCHECK_EQ(io_state_, STATE_GET_DOMAIN_BOUND_CERT_COMPLETE); |
638 DoLoop(result); | 636 DoLoop(result); |
639 } | 637 } |
640 | 638 |
641 int SpdyStream::DoLoop(int result) { | 639 int SpdyStream::DoLoop(int result) { |
642 CHECK(!in_do_loop_); | 640 CHECK(!in_do_loop_); |
643 in_do_loop_ = true; | 641 in_do_loop_ = true; |
644 | 642 |
645 do { | 643 do { |
646 State state = io_state_; | 644 State state = io_state_; |
647 io_state_ = STATE_NONE; | 645 io_state_ = STATE_NONE; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
712 io_state_ != STATE_OPEN); | 710 io_state_ != STATE_OPEN); |
713 | 711 |
714 CHECK(in_do_loop_); | 712 CHECK(in_do_loop_); |
715 in_do_loop_ = false; | 713 in_do_loop_ = false; |
716 | 714 |
717 return result; | 715 return result; |
718 } | 716 } |
719 | 717 |
720 int SpdyStream::DoGetDomainBoundCert() { | 718 int SpdyStream::DoGetDomainBoundCert() { |
721 CHECK(request_.get()); | 719 CHECK(request_.get()); |
720 DCHECK_NE(type_, SPDY_PUSH_STREAM); | |
722 GURL url = GetUrl(); | 721 GURL url = GetUrl(); |
723 if (!session_->NeedsCredentials() || pushed_ || !url.SchemeIs("https")) { | 722 if (!session_->NeedsCredentials() || !url.SchemeIs("https")) { |
724 // Proceed directly to sending the request headers | 723 // Proceed directly to sending the request headers |
725 io_state_ = STATE_SEND_REQUEST_HEADERS; | 724 io_state_ = STATE_SEND_REQUEST_HEADERS; |
726 return OK; | 725 return OK; |
727 } | 726 } |
728 | 727 |
729 slot_ = session_->credential_state()->FindCredentialSlot(GetUrl()); | 728 slot_ = session_->credential_state()->FindCredentialSlot(GetUrl()); |
730 if (slot_ != SpdyCredentialState::kNoEntry) { | 729 if (slot_ != SpdyCredentialState::kNoEntry) { |
731 // Proceed directly to sending the request headers | 730 // Proceed directly to sending the request headers |
732 io_state_ = STATE_SEND_REQUEST_HEADERS; | 731 io_state_ = STATE_SEND_REQUEST_HEADERS; |
733 return OK; | 732 return OK; |
734 } | 733 } |
735 | 734 |
736 io_state_ = STATE_GET_DOMAIN_BOUND_CERT_COMPLETE; | 735 io_state_ = STATE_GET_DOMAIN_BOUND_CERT_COMPLETE; |
737 ServerBoundCertService* sbc_service = session_->GetServerBoundCertService(); | 736 ServerBoundCertService* sbc_service = session_->GetServerBoundCertService(); |
738 DCHECK(sbc_service != NULL); | 737 DCHECK(sbc_service != NULL); |
739 std::vector<uint8> requested_cert_types; | 738 std::vector<uint8> requested_cert_types; |
740 requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN); | 739 requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN); |
741 int rv = sbc_service->GetDomainBoundCert( | 740 int rv = sbc_service->GetDomainBoundCert( |
742 url.GetOrigin().host(), requested_cert_types, | 741 url.GetOrigin().host(), requested_cert_types, |
743 &domain_bound_cert_type_, &domain_bound_private_key_, &domain_bound_cert_, | 742 &domain_bound_cert_type_, &domain_bound_private_key_, &domain_bound_cert_, |
744 base::Bind(&SpdyStream::OnGetDomainBoundCertComplete, GetWeakPtr()), | 743 base::Bind(&SpdyStream::OnGetDomainBoundCertComplete, GetWeakPtr()), |
745 &domain_bound_cert_request_handle_); | 744 &domain_bound_cert_request_handle_); |
746 return rv; | 745 return rv; |
747 } | 746 } |
748 | 747 |
749 int SpdyStream::DoGetDomainBoundCertComplete(int result) { | 748 int SpdyStream::DoGetDomainBoundCertComplete(int result) { |
749 DCHECK_NE(type_, SPDY_PUSH_STREAM); | |
750 if (result != OK) | 750 if (result != OK) |
751 return result; | 751 return result; |
752 | 752 |
753 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; | 753 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; |
754 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); | 754 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); |
755 return OK; | 755 return OK; |
756 } | 756 } |
757 | 757 |
758 int SpdyStream::DoSendDomainBoundCert() { | 758 int SpdyStream::DoSendDomainBoundCert() { |
759 CHECK(request_.get()); | |
760 DCHECK_NE(type_, SPDY_PUSH_STREAM); | |
759 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; | 761 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; |
760 CHECK(request_.get()); | |
761 | 762 |
762 std::string origin = GetUrl().GetOrigin().spec(); | 763 std::string origin = GetUrl().GetOrigin().spec(); |
763 DCHECK(origin[origin.length() - 1] == '/'); | 764 DCHECK(origin[origin.length() - 1] == '/'); |
764 origin.erase(origin.length() - 1); // Trim trailing slash. | 765 origin.erase(origin.length() - 1); // Trim trailing slash. |
765 scoped_ptr<SpdyFrame> frame; | 766 scoped_ptr<SpdyFrame> frame; |
766 int rv = session_->CreateCredentialFrame( | 767 int rv = session_->CreateCredentialFrame( |
767 origin, domain_bound_cert_type_, domain_bound_private_key_, | 768 origin, domain_bound_cert_type_, domain_bound_private_key_, |
768 domain_bound_cert_, priority_, &frame); | 769 domain_bound_cert_, priority_, &frame); |
769 if (rv != OK) { | 770 if (rv != OK) { |
770 DCHECK_NE(rv, ERR_IO_PENDING); | 771 DCHECK_NE(rv, ERR_IO_PENDING); |
(...skipping 10 matching lines...) Expand all Loading... | |
781 // the state machine appropriately. | 782 // the state machine appropriately. |
782 session_->EnqueueStreamWrite( | 783 session_->EnqueueStreamWrite( |
783 GetWeakPtr(), CREDENTIAL, | 784 GetWeakPtr(), CREDENTIAL, |
784 scoped_ptr<SpdyBufferProducer>( | 785 scoped_ptr<SpdyBufferProducer>( |
785 new SimpleBufferProducer( | 786 new SimpleBufferProducer( |
786 scoped_ptr<SpdyBuffer>(new SpdyBuffer(frame.Pass()))))); | 787 scoped_ptr<SpdyBuffer>(new SpdyBuffer(frame.Pass()))))); |
787 return ERR_IO_PENDING; | 788 return ERR_IO_PENDING; |
788 } | 789 } |
789 | 790 |
790 int SpdyStream::DoSendDomainBoundCertComplete(int result) { | 791 int SpdyStream::DoSendDomainBoundCertComplete(int result) { |
792 DCHECK_NE(type_, SPDY_PUSH_STREAM); | |
791 if (result != OK) | 793 if (result != OK) |
792 return result; | 794 return result; |
793 | 795 |
794 DCHECK_EQ(just_completed_frame_type_, CREDENTIAL); | 796 DCHECK_EQ(just_completed_frame_type_, CREDENTIAL); |
795 io_state_ = STATE_SEND_REQUEST_HEADERS; | 797 io_state_ = STATE_SEND_REQUEST_HEADERS; |
796 return OK; | 798 return OK; |
797 } | 799 } |
798 | 800 |
799 int SpdyStream::DoSendRequestHeaders() { | 801 int SpdyStream::DoSendRequestHeaders() { |
802 DCHECK_NE(type_, SPDY_PUSH_STREAM); | |
800 io_state_ = STATE_SEND_REQUEST_HEADERS_COMPLETE; | 803 io_state_ = STATE_SEND_REQUEST_HEADERS_COMPLETE; |
801 | 804 |
802 session_->EnqueueStreamWrite( | 805 session_->EnqueueStreamWrite( |
803 GetWeakPtr(), SYN_STREAM, | 806 GetWeakPtr(), SYN_STREAM, |
804 scoped_ptr<SpdyBufferProducer>( | 807 scoped_ptr<SpdyBufferProducer>( |
805 new SynStreamBufferProducer(GetWeakPtr()))); | 808 new SynStreamBufferProducer(GetWeakPtr()))); |
806 return ERR_IO_PENDING; | 809 return ERR_IO_PENDING; |
807 } | 810 } |
808 | 811 |
809 int SpdyStream::DoSendRequestHeadersComplete() { | 812 int SpdyStream::DoSendRequestHeadersComplete() { |
813 DCHECK_NE(type_, SPDY_PUSH_STREAM); | |
810 DCHECK_EQ(just_completed_frame_type_, SYN_STREAM); | 814 DCHECK_EQ(just_completed_frame_type_, SYN_STREAM); |
811 DCHECK_NE(stream_id_, 0u); | 815 DCHECK_NE(stream_id_, 0u); |
812 if (!delegate_) | 816 if (!delegate_) |
813 return ERR_UNEXPECTED; | 817 return ERR_UNEXPECTED; |
814 | 818 |
815 // We don't store the return value in |send_status_|; see comments | 819 delegate_->OnSendRequestHeadersComplete(); |
816 // in spdy_stream.h for OnSendRequestHeadersComplete(). | |
817 SpdySendStatus send_status = delegate_->OnSendRequestHeadersComplete(); | |
818 | 820 |
819 io_state_ = | 821 switch (type_) { |
820 (send_status == MORE_DATA_TO_SEND) ? | 822 case SPDY_BIDIRECTIONAL_STREAM: |
821 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; | 823 DCHECK_EQ(send_status_, MORE_DATA_TO_SEND); |
824 io_state_ = STATE_WAITING_FOR_RESPONSE; | |
825 break; | |
826 | |
827 case SPDY_REQUEST_RESPONSE_STREAM: | |
828 io_state_ = | |
829 (send_status_ == MORE_DATA_TO_SEND) ? | |
830 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; | |
831 break; | |
832 | |
833 case SPDY_PUSH_STREAM: | |
834 // Fall through. | |
835 default: | |
836 NOTREACHED(); | |
837 return ERR_UNEXPECTED; | |
838 } | |
822 | 839 |
823 return OK; | 840 return OK; |
824 } | 841 } |
825 | 842 |
826 // DoSendBody is called to send the optional body for the request. This call | 843 // DoSendBody is called to send the optional body for the request. This call |
827 // will also be called as each write of a chunk of the body completes. | 844 // will also be called as each write of a chunk of the body completes. |
828 int SpdyStream::DoSendBody() { | 845 int SpdyStream::DoSendBody() { |
846 DCHECK_NE(type_, SPDY_PUSH_STREAM); | |
829 io_state_ = STATE_SEND_BODY_COMPLETE; | 847 io_state_ = STATE_SEND_BODY_COMPLETE; |
830 CHECK(delegate_); | 848 CHECK(delegate_); |
831 delegate_->OnSendBody(); | 849 delegate_->OnSendBody(); |
832 return ERR_IO_PENDING; | 850 return ERR_IO_PENDING; |
833 } | 851 } |
834 | 852 |
835 int SpdyStream::DoSendBodyComplete(int result) { | 853 int SpdyStream::DoSendBodyComplete(int result) { |
854 DCHECK_NE(type_, SPDY_PUSH_STREAM); | |
836 result = ProcessJustCompletedFrame(result, STATE_SEND_BODY_COMPLETE); | 855 result = ProcessJustCompletedFrame(result, STATE_SEND_BODY_COMPLETE); |
837 | 856 |
838 if (result != OK) | 857 if (result != OK) |
839 return result; | 858 return result; |
840 | 859 |
841 delegate_->OnSendBodyComplete(); | 860 delegate_->OnSendBodyComplete(); |
842 | 861 |
843 io_state_ = | 862 io_state_ = |
844 (send_status_ == MORE_DATA_TO_SEND) ? | 863 (send_status_ == MORE_DATA_TO_SEND) ? |
845 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; | 864 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
895 | 914 |
896 if (!delegate_) { | 915 if (!delegate_) { |
897 NOTREACHED(); | 916 NOTREACHED(); |
898 return ERR_UNEXPECTED; | 917 return ERR_UNEXPECTED; |
899 } | 918 } |
900 | 919 |
901 return OK; | 920 return OK; |
902 } | 921 } |
903 | 922 |
904 void SpdyStream::UpdateHistograms() { | 923 void SpdyStream::UpdateHistograms() { |
905 // We need all timers to be filled in, otherwise metrics can be bogus. | 924 // We need at least the receive timers to be filled in, as otherwise |
906 if (send_time_.is_null() || recv_first_byte_time_.is_null() || | 925 // metrics can be bogus. |
907 recv_last_byte_time_.is_null()) | 926 if (recv_first_byte_time_.is_null() || recv_last_byte_time_.is_null()) |
908 return; | 927 return; |
909 | 928 |
929 base::TimeTicks effective_send_time; | |
930 if (type_ == SPDY_PUSH_STREAM) { | |
931 // Push streams shouldn't have |send_time_| filled in. | |
932 DCHECK(send_time_.is_null()); | |
933 effective_send_time = recv_first_byte_time_; | |
934 } else { | |
935 // For non-push streams, we also need |send_time_| to be filled | |
936 // in. | |
937 if (send_time_.is_null()) | |
938 return; | |
939 effective_send_time = send_time_; | |
940 } | |
941 | |
910 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTimeToFirstByte", | 942 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTimeToFirstByte", |
911 recv_first_byte_time_ - send_time_); | 943 recv_first_byte_time_ - effective_send_time); |
912 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", | 944 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", |
913 recv_last_byte_time_ - recv_first_byte_time_); | 945 recv_last_byte_time_ - recv_first_byte_time_); |
914 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", | 946 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", |
915 recv_last_byte_time_ - send_time_); | 947 recv_last_byte_time_ - effective_send_time); |
916 | 948 |
917 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); | 949 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); |
918 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); | 950 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); |
919 } | 951 } |
920 | 952 |
921 void SpdyStream::QueueNextDataFrame() { | 953 void SpdyStream::QueueNextDataFrame() { |
922 // Until the request has been completely sent, we cannot be sure | 954 // Until the request has been completely sent, we cannot be sure |
923 // that our stream_id is correct. | 955 // that our stream_id is correct. |
924 DCHECK_GT(io_state_, STATE_SEND_REQUEST_HEADERS_COMPLETE); | 956 DCHECK_GT(io_state_, STATE_SEND_REQUEST_HEADERS_COMPLETE); |
925 CHECK_GT(stream_id_, 0u); | 957 CHECK_GT(stream_id_, 0u); |
(...skipping 26 matching lines...) Expand all Loading... | |
952 GetWeakPtr(), payload_size)); | 984 GetWeakPtr(), payload_size)); |
953 } | 985 } |
954 | 986 |
955 session_->EnqueueStreamWrite( | 987 session_->EnqueueStreamWrite( |
956 GetWeakPtr(), DATA, | 988 GetWeakPtr(), DATA, |
957 scoped_ptr<SpdyBufferProducer>( | 989 scoped_ptr<SpdyBufferProducer>( |
958 new SimpleBufferProducer(data_buffer.Pass()))); | 990 new SimpleBufferProducer(data_buffer.Pass()))); |
959 } | 991 } |
960 | 992 |
961 } // namespace net | 993 } // namespace net |
OLD | NEW |