Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: net/spdy/spdy_stream.cc

Issue 15892015: [SPDY] Refactor SpdyStream state machine (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« net/spdy/spdy_stream.h ('K') | « net/spdy/spdy_stream.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« net/spdy/spdy_stream.h ('K') | « net/spdy/spdy_stream.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698