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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
98 recv_window_size_(initial_recv_window_size), | 98 recv_window_size_(initial_recv_window_size), |
99 unacked_recv_window_bytes_(0), | 99 unacked_recv_window_bytes_(0), |
100 response_received_(false), | 100 response_received_(false), |
101 session_(session), | 101 session_(session), |
102 delegate_(NULL), | 102 delegate_(NULL), |
103 send_status_( | 103 send_status_( |
104 (type_ == SPDY_PUSH_STREAM) ? | 104 (type_ == SPDY_PUSH_STREAM) ? |
105 NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND), | 105 NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND), |
106 request_time_(base::Time::Now()), | 106 request_time_(base::Time::Now()), |
107 response_(new SpdyHeaderBlock), | 107 response_(new SpdyHeaderBlock), |
108 io_state_(STATE_NONE), | 108 io_state_((type_ == SPDY_PUSH_STREAM) ? STATE_OPEN : STATE_NONE), |
109 response_status_(OK), | 109 response_status_(OK), |
110 net_log_(net_log), | 110 net_log_(net_log), |
111 send_bytes_(0), | 111 send_bytes_(0), |
112 recv_bytes_(0), | 112 recv_bytes_(0), |
113 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE), | 113 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE), |
114 just_completed_frame_type_(DATA), | 114 just_completed_frame_type_(DATA), |
115 just_completed_frame_size_(0) { | 115 just_completed_frame_size_(0) { |
116 } | 116 } |
117 | 117 |
118 SpdyStream::~SpdyStream() { | 118 SpdyStream::~SpdyStream() { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
170 delegate_->OnDataReceived(scoped_ptr<SpdyBuffer>()); | 170 delegate_->OnDataReceived(scoped_ptr<SpdyBuffer>()); |
171 session_->CloseActiveStream(stream_id_, OK); | 171 session_->CloseActiveStream(stream_id_, OK); |
172 // Note: |this| may be deleted after calling CloseActiveStream. | 172 // Note: |this| may be deleted after calling CloseActiveStream. |
173 DCHECK_EQ(buffers.size() - 1, i); | 173 DCHECK_EQ(buffers.size() - 1, i); |
174 } | 174 } |
175 } | 175 } |
176 } | 176 } |
177 | 177 |
178 scoped_ptr<SpdyFrame> SpdyStream::ProduceSynStreamFrame() { | 178 scoped_ptr<SpdyFrame> SpdyStream::ProduceSynStreamFrame() { |
179 CHECK_EQ(io_state_, STATE_SEND_REQUEST_HEADERS_COMPLETE); | 179 CHECK_EQ(io_state_, STATE_SEND_REQUEST_HEADERS_COMPLETE); |
180 CHECK(request_.get()); | 180 CHECK(request_); |
181 CHECK_GT(stream_id_, 0u); | 181 CHECK_GT(stream_id_, 0u); |
182 | 182 |
183 SpdyControlFlags flags = | 183 SpdyControlFlags flags = |
184 (send_status_ == NO_MORE_DATA_TO_SEND) ? | 184 (send_status_ == NO_MORE_DATA_TO_SEND) ? |
185 CONTROL_FLAG_FIN : CONTROL_FLAG_NONE; | 185 CONTROL_FLAG_FIN : CONTROL_FLAG_NONE; |
186 scoped_ptr<SpdyFrame> frame(session_->CreateSynStream( | 186 scoped_ptr<SpdyFrame> frame(session_->CreateSynStream( |
187 stream_id_, priority_, slot_, flags, *request_)); | 187 stream_id_, priority_, slot_, flags, *request_)); |
188 send_time_ = base::TimeTicks::Now(); | 188 send_time_ = base::TimeTicks::Now(); |
189 return frame.Pass(); | 189 return frame.Pass(); |
190 } | 190 } |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
366 | 366 |
367 void SpdyStream::SetRequestTime(base::Time t) { | 367 void SpdyStream::SetRequestTime(base::Time t) { |
368 request_time_ = t; | 368 request_time_ = t; |
369 } | 369 } |
370 | 370 |
371 int SpdyStream::OnResponseHeadersReceived(const SpdyHeaderBlock& response) { | 371 int SpdyStream::OnResponseHeadersReceived(const SpdyHeaderBlock& response) { |
372 int rv = OK; | 372 int rv = OK; |
373 | 373 |
374 metrics_.StartStream(); | 374 metrics_.StartStream(); |
375 | 375 |
376 // TODO(akalin): This should be handled as a protocol error. | |
376 DCHECK(response_->empty()); | 377 DCHECK(response_->empty()); |
377 *response_ = response; // TODO(ukai): avoid copy. | 378 *response_ = response; // TODO(ukai): avoid copy. |
378 | 379 |
379 recv_first_byte_time_ = base::TimeTicks::Now(); | 380 recv_first_byte_time_ = base::TimeTicks::Now(); |
380 response_time_ = base::Time::Now(); | 381 response_time_ = base::Time::Now(); |
381 | 382 |
382 // If we receive a response before we are in STATE_WAITING_FOR_RESPONSE, then | 383 // Check to make sure that we don't receive the response headers |
383 // the server has sent the SYN_REPLY too early. | 384 // before we're ready for it. |
384 if (type_ != SPDY_PUSH_STREAM && io_state_ != STATE_WAITING_FOR_RESPONSE) | 385 switch (type_) { |
385 return ERR_SPDY_PROTOCOL_ERROR; | 386 case SPDY_BIDIRECTIONAL_STREAM: |
386 if (type_ == SPDY_PUSH_STREAM) | 387 // For a bidirectional stream, we're ready for the response |
387 CHECK_EQ(io_state_, STATE_NONE); | 388 // headers once we've finished sending the request headers. |
388 io_state_ = STATE_OPEN; | 389 if (io_state_ < STATE_OPEN) |
390 return ERR_SPDY_PROTOCOL_ERROR; | |
391 break; | |
392 | |
393 case SPDY_REQUEST_RESPONSE_STREAM: | |
394 // For a request/response stream, we're ready for the response | |
395 // headers once we've finished sending the request headers and | |
396 // the request body (if we have one). | |
397 if ((io_state_ < STATE_OPEN) || | |
398 (send_status_ == MORE_DATA_TO_SEND) || | |
399 pending_send_data_) | |
400 return ERR_SPDY_PROTOCOL_ERROR; | |
401 break; | |
402 | |
403 case SPDY_PUSH_STREAM: | |
404 // For a push stream, we're ready immediately. | |
405 DCHECK_EQ(send_status_, NO_MORE_DATA_TO_SEND); | |
406 DCHECK_EQ(io_state_, STATE_OPEN); | |
407 break; | |
408 | |
409 default: | |
Ryan Hamilton
2013/05/29 03:05:33
If there is not another value for the enum, I thin
akalin
2013/05/29 03:12:45
Unfortunately, no. since the enum has to be at lea
| |
410 NOTREACHED(); | |
411 } | |
412 | |
413 DCHECK_EQ(io_state_, STATE_OPEN); | |
414 | |
415 // TODO(akalin): Merge the code below with the code in OnHeaders(). | |
389 | 416 |
390 // Append all the headers into the response header block. | 417 // Append all the headers into the response header block. |
391 for (SpdyHeaderBlock::const_iterator it = response.begin(); | 418 for (SpdyHeaderBlock::const_iterator it = response.begin(); |
392 it != response.end(); ++it) { | 419 it != response.end(); ++it) { |
393 // Disallow uppercase headers. | 420 // Disallow uppercase headers. |
394 if (ContainsUpperAscii(it->first)) { | 421 if (ContainsUpperAscii(it->first)) { |
395 session_->ResetStream(stream_id_, priority_, RST_STREAM_PROTOCOL_ERROR, | 422 session_->ResetStream(stream_id_, priority_, RST_STREAM_PROTOCOL_ERROR, |
396 "Upper case characters in header: " + it->first); | 423 "Upper case characters in header: " + it->first); |
397 return ERR_SPDY_PROTOCOL_ERROR; | 424 return ERR_SPDY_PROTOCOL_ERROR; |
398 } | 425 } |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
575 send_status_ = send_status; | 602 send_status_ = send_status; |
576 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; | 603 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; |
577 return DoLoop(OK); | 604 return DoLoop(OK); |
578 } | 605 } |
579 | 606 |
580 void SpdyStream::SendData(IOBuffer* data, | 607 void SpdyStream::SendData(IOBuffer* data, |
581 int length, | 608 int length, |
582 SpdySendStatus send_status) { | 609 SpdySendStatus send_status) { |
583 CHECK_NE(type_, SPDY_PUSH_STREAM); | 610 CHECK_NE(type_, SPDY_PUSH_STREAM); |
584 CHECK_EQ(send_status_, MORE_DATA_TO_SEND); | 611 CHECK_EQ(send_status_, MORE_DATA_TO_SEND); |
585 CHECK_GE(io_state_, STATE_SEND_BODY); | 612 CHECK_GE(io_state_, STATE_SEND_REQUEST_HEADERS_COMPLETE); |
586 CHECK(!pending_send_data_); | 613 CHECK(!pending_send_data_); |
587 pending_send_data_ = new DrainableIOBuffer(data, length); | 614 pending_send_data_ = new DrainableIOBuffer(data, length); |
588 send_status_ = send_status; | 615 send_status_ = send_status; |
589 QueueNextDataFrame(); | 616 QueueNextDataFrame(); |
590 } | 617 } |
591 | 618 |
592 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, | 619 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, |
593 bool* was_npn_negotiated, | 620 bool* was_npn_negotiated, |
594 NextProto* protocol_negotiated) { | 621 NextProto* protocol_negotiated) { |
595 return session_->GetSSLInfo( | 622 return session_->GetSSLInfo( |
(...skipping 17 matching lines...) Expand all Loading... | |
613 } | 640 } |
614 } | 641 } |
615 | 642 |
616 base::WeakPtr<SpdyStream> SpdyStream::GetWeakPtr() { | 643 base::WeakPtr<SpdyStream> SpdyStream::GetWeakPtr() { |
617 return weak_ptr_factory_.GetWeakPtr(); | 644 return weak_ptr_factory_.GetWeakPtr(); |
618 } | 645 } |
619 | 646 |
620 bool SpdyStream::HasUrl() const { | 647 bool SpdyStream::HasUrl() const { |
621 if (type_ == SPDY_PUSH_STREAM) | 648 if (type_ == SPDY_PUSH_STREAM) |
622 return response_received(); | 649 return response_received(); |
623 return request_.get() != NULL; | 650 return request_ != NULL; |
624 } | 651 } |
625 | 652 |
626 GURL SpdyStream::GetUrl() const { | 653 GURL SpdyStream::GetUrl() const { |
627 DCHECK(HasUrl()); | 654 DCHECK(HasUrl()); |
628 | 655 |
629 const SpdyHeaderBlock& headers = | 656 const SpdyHeaderBlock& headers = |
630 (type_ == SPDY_PUSH_STREAM) ? *response_ : *request_; | 657 (type_ == SPDY_PUSH_STREAM) ? *response_ : *request_; |
631 return GetUrlFromHeaderBlock(headers, GetProtocolVersion(), | 658 return GetUrlFromHeaderBlock(headers, GetProtocolVersion(), |
632 type_ == SPDY_PUSH_STREAM); | 659 type_ == SPDY_PUSH_STREAM); |
633 } | 660 } |
634 | 661 |
635 void SpdyStream::OnGetDomainBoundCertComplete(int result) { | 662 void SpdyStream::OnGetDomainBoundCertComplete(int result) { |
636 DCHECK_EQ(io_state_, STATE_GET_DOMAIN_BOUND_CERT_COMPLETE); | 663 DCHECK_EQ(io_state_, STATE_GET_DOMAIN_BOUND_CERT_COMPLETE); |
637 DoLoop(result); | 664 DoLoop(result); |
638 } | 665 } |
639 | 666 |
640 int SpdyStream::DoLoop(int result) { | 667 int SpdyStream::DoLoop(int result) { |
641 CHECK(!in_do_loop_); | 668 CHECK(!in_do_loop_); |
642 in_do_loop_ = true; | 669 in_do_loop_ = true; |
643 | 670 |
644 do { | 671 do { |
645 State state = io_state_; | 672 State state = io_state_; |
646 io_state_ = STATE_NONE; | 673 io_state_ = STATE_NONE; |
647 switch (state) { | 674 switch (state) { |
648 // State machine 1: Send headers and body. | |
649 case STATE_GET_DOMAIN_BOUND_CERT: | 675 case STATE_GET_DOMAIN_BOUND_CERT: |
650 CHECK_EQ(result, OK); | 676 CHECK_EQ(result, OK); |
651 result = DoGetDomainBoundCert(); | 677 result = DoGetDomainBoundCert(); |
652 break; | 678 break; |
653 case STATE_GET_DOMAIN_BOUND_CERT_COMPLETE: | 679 case STATE_GET_DOMAIN_BOUND_CERT_COMPLETE: |
654 result = DoGetDomainBoundCertComplete(result); | 680 result = DoGetDomainBoundCertComplete(result); |
655 break; | 681 break; |
656 case STATE_SEND_DOMAIN_BOUND_CERT: | 682 case STATE_SEND_DOMAIN_BOUND_CERT: |
657 CHECK_EQ(result, OK); | 683 CHECK_EQ(result, OK); |
658 result = DoSendDomainBoundCert(); | 684 result = DoSendDomainBoundCert(); |
659 break; | 685 break; |
660 case STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE: | 686 case STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE: |
661 result = DoSendDomainBoundCertComplete(result); | 687 result = DoSendDomainBoundCertComplete(result); |
662 break; | 688 break; |
663 case STATE_SEND_REQUEST_HEADERS: | 689 case STATE_SEND_REQUEST_HEADERS: |
664 CHECK_EQ(result, OK); | 690 CHECK_EQ(result, OK); |
665 result = DoSendRequestHeaders(); | 691 result = DoSendRequestHeaders(); |
666 break; | 692 break; |
667 case STATE_SEND_REQUEST_HEADERS_COMPLETE: | 693 case STATE_SEND_REQUEST_HEADERS_COMPLETE: |
668 CHECK_EQ(result, OK); | 694 CHECK_EQ(result, OK); |
669 result = DoSendRequestHeadersComplete(); | 695 result = DoSendRequestHeadersComplete(); |
670 break; | 696 break; |
671 // TODO(akalin): Remove the states STATE_SEND_BODY through | 697 |
672 // STATE_WAITING_FOR_RESPONSE; we can infer correct behavior | 698 // For request/response streams, no data is sent from the client |
673 // from |type_| and |send_status_|. | 699 // while in the OPEN state, so OnFrameWriteComplete is never |
674 case STATE_SEND_BODY: | 700 // called here. The HTTP body is handled in the OnDataReceived |
675 CHECK_EQ(result, OK); | 701 // callback, which does not call into DoLoop. |
676 result = DoSendBody(); | |
677 break; | |
678 case STATE_SEND_BODY_COMPLETE: | |
679 result = DoSendBodyComplete(result); | |
680 break; | |
681 // This is an intermediary waiting state. This state is reached when all | |
682 // data has been sent, but no data has been received. | |
683 case STATE_WAITING_FOR_RESPONSE: | |
684 io_state_ = STATE_WAITING_FOR_RESPONSE; | |
685 result = ERR_IO_PENDING; | |
686 break; | |
687 // State machine 2: connection is established. | |
688 // In STATE_OPEN, OnResponseHeadersReceived has already been called. | |
689 // OnDataReceived, OnClose and OnFrameWriteComplete can be called. | |
690 // Only OnFrameWriteComplete calls DoLoop(). | |
691 // | 702 // |
692 // For HTTP streams, no data is sent from the client while in the OPEN | 703 // For bidirectional streams, we'll send and receive data once |
693 // state, so OnFrameWriteComplete is never called here. The HTTP body is | 704 // the connection is established. Received data is handled in |
694 // handled in the OnDataReceived callback, which does not call into | 705 // OnDataReceived. Sent data is handled in |
695 // DoLoop. | |
696 // | |
697 // For WebSocket streams, which are bi-directional, we'll send and | |
698 // receive data once the connection is established. Received data is | |
699 // handled in OnDataReceived. Sent data is handled in | |
700 // OnFrameWriteComplete, which calls DoOpen(). | 706 // OnFrameWriteComplete, which calls DoOpen(). |
701 case STATE_OPEN: | 707 case STATE_OPEN: |
702 CHECK_EQ(result, OK); | 708 CHECK_EQ(result, OK); |
703 result = DoOpen(); | 709 result = DoOpen(); |
704 break; | 710 break; |
705 | 711 |
706 case STATE_DONE: | 712 case STATE_DONE: |
707 DCHECK(result != ERR_IO_PENDING); | 713 DCHECK(result != ERR_IO_PENDING); |
708 break; | 714 break; |
709 default: | 715 default: |
710 NOTREACHED() << io_state_; | 716 NOTREACHED() << io_state_; |
711 break; | 717 break; |
712 } | 718 } |
713 } while (result != ERR_IO_PENDING && io_state_ != STATE_NONE && | 719 } while (result != ERR_IO_PENDING && io_state_ != STATE_NONE && |
714 io_state_ != STATE_OPEN); | 720 io_state_ != STATE_OPEN); |
715 | 721 |
716 CHECK(in_do_loop_); | 722 CHECK(in_do_loop_); |
717 in_do_loop_ = false; | 723 in_do_loop_ = false; |
718 | 724 |
719 return result; | 725 return result; |
720 } | 726 } |
721 | 727 |
722 int SpdyStream::DoGetDomainBoundCert() { | 728 int SpdyStream::DoGetDomainBoundCert() { |
723 CHECK(request_.get()); | 729 CHECK(request_); |
724 DCHECK_NE(type_, SPDY_PUSH_STREAM); | 730 DCHECK_NE(type_, SPDY_PUSH_STREAM); |
725 GURL url = GetUrl(); | 731 GURL url = GetUrl(); |
726 if (!session_->NeedsCredentials() || !url.SchemeIs("https")) { | 732 if (!session_->NeedsCredentials() || !url.SchemeIs("https")) { |
727 // Proceed directly to sending the request headers | 733 // Proceed directly to sending the request headers |
728 io_state_ = STATE_SEND_REQUEST_HEADERS; | 734 io_state_ = STATE_SEND_REQUEST_HEADERS; |
729 return OK; | 735 return OK; |
730 } | 736 } |
731 | 737 |
732 slot_ = session_->credential_state()->FindCredentialSlot(GetUrl()); | 738 slot_ = session_->credential_state()->FindCredentialSlot(GetUrl()); |
733 if (slot_ != SpdyCredentialState::kNoEntry) { | 739 if (slot_ != SpdyCredentialState::kNoEntry) { |
(...skipping 19 matching lines...) Expand all Loading... | |
753 DCHECK_NE(type_, SPDY_PUSH_STREAM); | 759 DCHECK_NE(type_, SPDY_PUSH_STREAM); |
754 if (result != OK) | 760 if (result != OK) |
755 return result; | 761 return result; |
756 | 762 |
757 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; | 763 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; |
758 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); | 764 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); |
759 return OK; | 765 return OK; |
760 } | 766 } |
761 | 767 |
762 int SpdyStream::DoSendDomainBoundCert() { | 768 int SpdyStream::DoSendDomainBoundCert() { |
763 CHECK(request_.get()); | 769 CHECK(request_); |
764 DCHECK_NE(type_, SPDY_PUSH_STREAM); | 770 DCHECK_NE(type_, SPDY_PUSH_STREAM); |
765 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; | 771 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; |
766 | 772 |
767 std::string origin = GetUrl().GetOrigin().spec(); | 773 std::string origin = GetUrl().GetOrigin().spec(); |
768 DCHECK(origin[origin.length() - 1] == '/'); | 774 DCHECK(origin[origin.length() - 1] == '/'); |
769 origin.erase(origin.length() - 1); // Trim trailing slash. | 775 origin.erase(origin.length() - 1); // Trim trailing slash. |
770 scoped_ptr<SpdyFrame> frame; | 776 scoped_ptr<SpdyFrame> frame; |
771 int rv = session_->CreateCredentialFrame( | 777 int rv = session_->CreateCredentialFrame( |
772 origin, domain_bound_cert_type_, domain_bound_private_key_, | 778 origin, domain_bound_cert_type_, domain_bound_private_key_, |
773 domain_bound_cert_, priority_, &frame); | 779 domain_bound_cert_, priority_, &frame); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
806 DCHECK_NE(type_, SPDY_PUSH_STREAM); | 812 DCHECK_NE(type_, SPDY_PUSH_STREAM); |
807 io_state_ = STATE_SEND_REQUEST_HEADERS_COMPLETE; | 813 io_state_ = STATE_SEND_REQUEST_HEADERS_COMPLETE; |
808 | 814 |
809 session_->EnqueueStreamWrite( | 815 session_->EnqueueStreamWrite( |
810 GetWeakPtr(), SYN_STREAM, | 816 GetWeakPtr(), SYN_STREAM, |
811 scoped_ptr<SpdyBufferProducer>( | 817 scoped_ptr<SpdyBufferProducer>( |
812 new SynStreamBufferProducer(GetWeakPtr()))); | 818 new SynStreamBufferProducer(GetWeakPtr()))); |
813 return ERR_IO_PENDING; | 819 return ERR_IO_PENDING; |
814 } | 820 } |
815 | 821 |
822 namespace { | |
823 | |
824 // Assuming we're in STATE_OPEN, maps the given type (which must not | |
825 // be SPDY_PUSH_STREAM) and send status to a result to return from | |
826 // DoSendRequestHeadersComplete() or DoOpen(). | |
827 int GetOpenStateResult(SpdyStreamType type, SpdySendStatus send_status) { | |
828 switch (type) { | |
829 case SPDY_BIDIRECTIONAL_STREAM: | |
830 // For bidirectional streams, there's nothing else to do. | |
831 DCHECK_EQ(send_status, MORE_DATA_TO_SEND); | |
832 return OK; | |
833 | |
834 case SPDY_REQUEST_RESPONSE_STREAM: | |
835 // For request/response streams, wait for the delegate to send | |
836 // data if there's request data to send; we'll get called back | |
837 // when the send finishes. | |
838 if (send_status == MORE_DATA_TO_SEND) | |
839 return ERR_IO_PENDING; | |
840 | |
841 return OK; | |
842 | |
843 case SPDY_PUSH_STREAM: | |
844 // This should never be called for push streams. | |
845 break; | |
846 | |
847 default: | |
Ryan Hamilton
2013/05/29 03:05:33
ditto. I think you can drop this case, right?
akalin
2013/05/29 03:12:45
ditto.
| |
848 break; | |
849 } | |
850 | |
851 CHECK(false); | |
852 return ERR_UNEXPECTED; | |
853 } | |
854 | |
855 } // namespace | |
856 | |
816 int SpdyStream::DoSendRequestHeadersComplete() { | 857 int SpdyStream::DoSendRequestHeadersComplete() { |
817 DCHECK_NE(type_, SPDY_PUSH_STREAM); | 858 DCHECK_NE(type_, SPDY_PUSH_STREAM); |
818 DCHECK_EQ(just_completed_frame_type_, SYN_STREAM); | 859 DCHECK_EQ(just_completed_frame_type_, SYN_STREAM); |
819 DCHECK_NE(stream_id_, 0u); | 860 DCHECK_NE(stream_id_, 0u); |
820 if (!delegate_) | |
821 return ERR_UNEXPECTED; | |
822 | 861 |
823 switch (type_) { | 862 io_state_ = STATE_OPEN; |
824 case SPDY_BIDIRECTIONAL_STREAM: | |
825 DCHECK_EQ(send_status_, MORE_DATA_TO_SEND); | |
826 io_state_ = STATE_WAITING_FOR_RESPONSE; | |
827 break; | |
828 | 863 |
829 case SPDY_REQUEST_RESPONSE_STREAM: | 864 // Do this before calling into the |delegate_| as that call may |
830 io_state_ = | 865 // delete us. |
831 (send_status_ == MORE_DATA_TO_SEND) ? | 866 int result = GetOpenStateResult(type_, send_status_); |
832 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; | |
833 break; | |
834 | 867 |
835 case SPDY_PUSH_STREAM: | 868 CHECK(delegate_); |
836 // Fall through. | |
837 default: | |
838 NOTREACHED(); | |
839 return ERR_UNEXPECTED; | |
840 } | |
841 | |
842 delegate_->OnRequestHeadersSent(); | 869 delegate_->OnRequestHeadersSent(); |
843 | 870 |
844 return OK; | 871 return result; |
845 } | |
846 | |
847 // DoSendBody is called to send the optional body for the request. This call | |
848 // will also be called as each write of a chunk of the body completes. | |
849 int SpdyStream::DoSendBody() { | |
850 DCHECK_NE(type_, SPDY_PUSH_STREAM); | |
851 io_state_ = STATE_SEND_BODY_COMPLETE; | |
852 return ERR_IO_PENDING; | |
853 } | |
854 | |
855 int SpdyStream::DoSendBodyComplete(int result) { | |
856 DCHECK_NE(type_, SPDY_PUSH_STREAM); | |
857 result = ProcessJustCompletedFrame(result, STATE_SEND_BODY_COMPLETE); | |
858 | |
859 if (result != OK) | |
860 return result; | |
861 | |
862 io_state_ = | |
863 (send_status_ == MORE_DATA_TO_SEND) ? | |
864 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; | |
865 | |
866 delegate_->OnDataSent(); | |
867 | |
868 return OK; | |
869 } | 872 } |
870 | 873 |
871 int SpdyStream::DoOpen() { | 874 int SpdyStream::DoOpen() { |
872 int result = ProcessJustCompletedFrame(OK, STATE_OPEN); | 875 DCHECK_NE(type_, SPDY_PUSH_STREAM); |
873 | |
874 if (result != OK) | |
875 return result; | |
876 | |
877 // Set |io_state_| first as |delegate_| may check it. | |
878 io_state_ = STATE_OPEN; | |
879 | |
880 delegate_->OnDataSent(); | |
881 | |
882 return OK; | |
883 } | |
884 | |
885 int SpdyStream::ProcessJustCompletedFrame(int result, State io_pending_state) { | |
886 if (result != OK) | |
887 return result; | |
888 | 876 |
889 if (just_completed_frame_type_ != DATA) { | 877 if (just_completed_frame_type_ != DATA) { |
890 NOTREACHED(); | 878 NOTREACHED(); |
891 return ERR_UNEXPECTED; | 879 return ERR_UNEXPECTED; |
892 } | 880 } |
893 | 881 |
894 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) { | 882 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) { |
895 NOTREACHED(); | 883 NOTREACHED(); |
896 return ERR_UNEXPECTED; | 884 return ERR_UNEXPECTED; |
897 } | 885 } |
898 | 886 |
899 size_t frame_payload_size = | 887 size_t frame_payload_size = |
900 just_completed_frame_size_ - session_->GetDataFrameMinimumSize(); | 888 just_completed_frame_size_ - session_->GetDataFrameMinimumSize(); |
901 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) { | 889 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) { |
902 NOTREACHED(); | 890 NOTREACHED(); |
903 return ERR_UNEXPECTED; | 891 return ERR_UNEXPECTED; |
904 } | 892 } |
905 | 893 |
894 // Set |io_state_| first as |delegate_| may check it. | |
895 io_state_ = STATE_OPEN; | |
896 | |
906 send_bytes_ += frame_payload_size; | 897 send_bytes_ += frame_payload_size; |
907 | 898 |
908 pending_send_data_->DidConsume(frame_payload_size); | 899 pending_send_data_->DidConsume(frame_payload_size); |
909 if (pending_send_data_->BytesRemaining() > 0) { | 900 if (pending_send_data_->BytesRemaining() > 0) { |
910 io_state_ = io_pending_state; | |
911 QueueNextDataFrame(); | 901 QueueNextDataFrame(); |
912 return ERR_IO_PENDING; | 902 return ERR_IO_PENDING; |
913 } | 903 } |
914 | 904 |
915 pending_send_data_ = NULL; | 905 pending_send_data_ = NULL; |
916 | 906 |
917 if (!delegate_) { | 907 // Do this before calling into the |delegate_| as that call may |
918 NOTREACHED(); | 908 // delete us. |
919 return ERR_UNEXPECTED; | 909 int result = GetOpenStateResult(type_, send_status_); |
920 } | |
921 | 910 |
922 return OK; | 911 CHECK(delegate_); |
912 delegate_->OnDataSent(); | |
913 | |
914 return result; | |
923 } | 915 } |
924 | 916 |
925 void SpdyStream::UpdateHistograms() { | 917 void SpdyStream::UpdateHistograms() { |
926 // We need at least the receive timers to be filled in, as otherwise | 918 // We need at least the receive timers to be filled in, as otherwise |
927 // metrics can be bogus. | 919 // metrics can be bogus. |
928 if (recv_first_byte_time_.is_null() || recv_last_byte_time_.is_null()) | 920 if (recv_first_byte_time_.is_null() || recv_last_byte_time_.is_null()) |
929 return; | 921 return; |
930 | 922 |
931 base::TimeTicks effective_send_time; | 923 base::TimeTicks effective_send_time; |
932 if (type_ == SPDY_PUSH_STREAM) { | 924 if (type_ == SPDY_PUSH_STREAM) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
986 GetWeakPtr(), payload_size)); | 978 GetWeakPtr(), payload_size)); |
987 } | 979 } |
988 | 980 |
989 session_->EnqueueStreamWrite( | 981 session_->EnqueueStreamWrite( |
990 GetWeakPtr(), DATA, | 982 GetWeakPtr(), DATA, |
991 scoped_ptr<SpdyBufferProducer>( | 983 scoped_ptr<SpdyBufferProducer>( |
992 new SimpleBufferProducer(data_buffer.Pass()))); | 984 new SimpleBufferProducer(data_buffer.Pass()))); |
993 } | 985 } |
994 | 986 |
995 } // namespace net | 987 } // namespace net |
OLD | NEW |