| 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 CHECK(type_ == SPDY_BIDIRECTIONAL_STREAM || |
| 117 type_ == SPDY_REQUEST_RESPONSE_STREAM || |
| 118 type_ == SPDY_PUSH_STREAM); |
| 116 } | 119 } |
| 117 | 120 |
| 118 SpdyStream::~SpdyStream() { | 121 SpdyStream::~SpdyStream() { |
| 119 CHECK(!in_do_loop_); | 122 CHECK(!in_do_loop_); |
| 120 UpdateHistograms(); | 123 UpdateHistograms(); |
| 121 } | 124 } |
| 122 | 125 |
| 123 void SpdyStream::SetDelegate(Delegate* delegate) { | 126 void SpdyStream::SetDelegate(Delegate* delegate) { |
| 124 CHECK(delegate); | 127 CHECK(delegate); |
| 125 delegate_ = delegate; | 128 delegate_ = delegate; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 delegate_->OnDataReceived(scoped_ptr<SpdyBuffer>()); | 173 delegate_->OnDataReceived(scoped_ptr<SpdyBuffer>()); |
| 171 session_->CloseActiveStream(stream_id_, OK); | 174 session_->CloseActiveStream(stream_id_, OK); |
| 172 // Note: |this| may be deleted after calling CloseActiveStream. | 175 // Note: |this| may be deleted after calling CloseActiveStream. |
| 173 DCHECK_EQ(buffers.size() - 1, i); | 176 DCHECK_EQ(buffers.size() - 1, i); |
| 174 } | 177 } |
| 175 } | 178 } |
| 176 } | 179 } |
| 177 | 180 |
| 178 scoped_ptr<SpdyFrame> SpdyStream::ProduceSynStreamFrame() { | 181 scoped_ptr<SpdyFrame> SpdyStream::ProduceSynStreamFrame() { |
| 179 CHECK_EQ(io_state_, STATE_SEND_REQUEST_HEADERS_COMPLETE); | 182 CHECK_EQ(io_state_, STATE_SEND_REQUEST_HEADERS_COMPLETE); |
| 180 CHECK(request_.get()); | 183 CHECK(request_); |
| 181 CHECK_GT(stream_id_, 0u); | 184 CHECK_GT(stream_id_, 0u); |
| 182 | 185 |
| 183 SpdyControlFlags flags = | 186 SpdyControlFlags flags = |
| 184 (send_status_ == NO_MORE_DATA_TO_SEND) ? | 187 (send_status_ == NO_MORE_DATA_TO_SEND) ? |
| 185 CONTROL_FLAG_FIN : CONTROL_FLAG_NONE; | 188 CONTROL_FLAG_FIN : CONTROL_FLAG_NONE; |
| 186 scoped_ptr<SpdyFrame> frame(session_->CreateSynStream( | 189 scoped_ptr<SpdyFrame> frame(session_->CreateSynStream( |
| 187 stream_id_, priority_, slot_, flags, *request_)); | 190 stream_id_, priority_, slot_, flags, *request_)); |
| 188 send_time_ = base::TimeTicks::Now(); | 191 send_time_ = base::TimeTicks::Now(); |
| 189 return frame.Pass(); | 192 return frame.Pass(); |
| 190 } | 193 } |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 | 369 |
| 367 void SpdyStream::SetRequestTime(base::Time t) { | 370 void SpdyStream::SetRequestTime(base::Time t) { |
| 368 request_time_ = t; | 371 request_time_ = t; |
| 369 } | 372 } |
| 370 | 373 |
| 371 int SpdyStream::OnResponseHeadersReceived(const SpdyHeaderBlock& response) { | 374 int SpdyStream::OnResponseHeadersReceived(const SpdyHeaderBlock& response) { |
| 372 int rv = OK; | 375 int rv = OK; |
| 373 | 376 |
| 374 metrics_.StartStream(); | 377 metrics_.StartStream(); |
| 375 | 378 |
| 379 // TODO(akalin): This should be handled as a protocol error. |
| 376 DCHECK(response_->empty()); | 380 DCHECK(response_->empty()); |
| 377 *response_ = response; // TODO(ukai): avoid copy. | 381 *response_ = response; // TODO(ukai): avoid copy. |
| 378 | 382 |
| 379 recv_first_byte_time_ = base::TimeTicks::Now(); | 383 recv_first_byte_time_ = base::TimeTicks::Now(); |
| 380 response_time_ = base::Time::Now(); | 384 response_time_ = base::Time::Now(); |
| 381 | 385 |
| 382 // If we receive a response before we are in STATE_WAITING_FOR_RESPONSE, then | 386 // Check to make sure that we don't receive the response headers |
| 383 // the server has sent the SYN_REPLY too early. | 387 // before we're ready for it. |
| 384 if (type_ != SPDY_PUSH_STREAM && io_state_ != STATE_WAITING_FOR_RESPONSE) | 388 switch (type_) { |
| 385 return ERR_SPDY_PROTOCOL_ERROR; | 389 case SPDY_BIDIRECTIONAL_STREAM: |
| 386 if (type_ == SPDY_PUSH_STREAM) | 390 // For a bidirectional stream, we're ready for the response |
| 387 CHECK_EQ(io_state_, STATE_NONE); | 391 // headers once we've finished sending the request headers. |
| 388 io_state_ = STATE_OPEN; | 392 if (io_state_ < STATE_OPEN) |
| 393 return ERR_SPDY_PROTOCOL_ERROR; |
| 394 break; |
| 395 |
| 396 case SPDY_REQUEST_RESPONSE_STREAM: |
| 397 // For a request/response stream, we're ready for the response |
| 398 // headers once we've finished sending the request headers and |
| 399 // the request body (if we have one). |
| 400 if ((io_state_ < STATE_OPEN) || |
| 401 (send_status_ == MORE_DATA_TO_SEND) || |
| 402 pending_send_data_) |
| 403 return ERR_SPDY_PROTOCOL_ERROR; |
| 404 break; |
| 405 |
| 406 case SPDY_PUSH_STREAM: |
| 407 // For a push stream, we're ready immediately. |
| 408 DCHECK_EQ(send_status_, NO_MORE_DATA_TO_SEND); |
| 409 DCHECK_EQ(io_state_, STATE_OPEN); |
| 410 break; |
| 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 |
| 848 CHECK(false); |
| 849 return ERR_UNEXPECTED; |
| 850 } |
| 851 |
| 852 } // namespace |
| 853 |
| 816 int SpdyStream::DoSendRequestHeadersComplete() { | 854 int SpdyStream::DoSendRequestHeadersComplete() { |
| 817 DCHECK_NE(type_, SPDY_PUSH_STREAM); | 855 DCHECK_NE(type_, SPDY_PUSH_STREAM); |
| 818 DCHECK_EQ(just_completed_frame_type_, SYN_STREAM); | 856 DCHECK_EQ(just_completed_frame_type_, SYN_STREAM); |
| 819 DCHECK_NE(stream_id_, 0u); | 857 DCHECK_NE(stream_id_, 0u); |
| 820 if (!delegate_) | |
| 821 return ERR_UNEXPECTED; | |
| 822 | 858 |
| 823 switch (type_) { | 859 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 | 860 |
| 829 case SPDY_REQUEST_RESPONSE_STREAM: | 861 // Do this before calling into the |delegate_| as that call may |
| 830 io_state_ = | 862 // delete us. |
| 831 (send_status_ == MORE_DATA_TO_SEND) ? | 863 int result = GetOpenStateResult(type_, send_status_); |
| 832 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; | |
| 833 break; | |
| 834 | 864 |
| 835 case SPDY_PUSH_STREAM: | 865 CHECK(delegate_); |
| 836 // Fall through. | |
| 837 default: | |
| 838 NOTREACHED(); | |
| 839 return ERR_UNEXPECTED; | |
| 840 } | |
| 841 | |
| 842 delegate_->OnRequestHeadersSent(); | 866 delegate_->OnRequestHeadersSent(); |
| 843 | 867 |
| 844 return OK; | 868 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 } | 869 } |
| 870 | 870 |
| 871 int SpdyStream::DoOpen() { | 871 int SpdyStream::DoOpen() { |
| 872 int result = ProcessJustCompletedFrame(OK, STATE_OPEN); | 872 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 | 873 |
| 889 if (just_completed_frame_type_ != DATA) { | 874 if (just_completed_frame_type_ != DATA) { |
| 890 NOTREACHED(); | 875 NOTREACHED(); |
| 891 return ERR_UNEXPECTED; | 876 return ERR_UNEXPECTED; |
| 892 } | 877 } |
| 893 | 878 |
| 894 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) { | 879 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) { |
| 895 NOTREACHED(); | 880 NOTREACHED(); |
| 896 return ERR_UNEXPECTED; | 881 return ERR_UNEXPECTED; |
| 897 } | 882 } |
| 898 | 883 |
| 899 size_t frame_payload_size = | 884 size_t frame_payload_size = |
| 900 just_completed_frame_size_ - session_->GetDataFrameMinimumSize(); | 885 just_completed_frame_size_ - session_->GetDataFrameMinimumSize(); |
| 901 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) { | 886 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) { |
| 902 NOTREACHED(); | 887 NOTREACHED(); |
| 903 return ERR_UNEXPECTED; | 888 return ERR_UNEXPECTED; |
| 904 } | 889 } |
| 905 | 890 |
| 891 // Set |io_state_| first as |delegate_| may check it. |
| 892 io_state_ = STATE_OPEN; |
| 893 |
| 906 send_bytes_ += frame_payload_size; | 894 send_bytes_ += frame_payload_size; |
| 907 | 895 |
| 908 pending_send_data_->DidConsume(frame_payload_size); | 896 pending_send_data_->DidConsume(frame_payload_size); |
| 909 if (pending_send_data_->BytesRemaining() > 0) { | 897 if (pending_send_data_->BytesRemaining() > 0) { |
| 910 io_state_ = io_pending_state; | |
| 911 QueueNextDataFrame(); | 898 QueueNextDataFrame(); |
| 912 return ERR_IO_PENDING; | 899 return ERR_IO_PENDING; |
| 913 } | 900 } |
| 914 | 901 |
| 915 pending_send_data_ = NULL; | 902 pending_send_data_ = NULL; |
| 916 | 903 |
| 917 if (!delegate_) { | 904 // Do this before calling into the |delegate_| as that call may |
| 918 NOTREACHED(); | 905 // delete us. |
| 919 return ERR_UNEXPECTED; | 906 int result = GetOpenStateResult(type_, send_status_); |
| 920 } | |
| 921 | 907 |
| 922 return OK; | 908 CHECK(delegate_); |
| 909 delegate_->OnDataSent(); |
| 910 |
| 911 return result; |
| 923 } | 912 } |
| 924 | 913 |
| 925 void SpdyStream::UpdateHistograms() { | 914 void SpdyStream::UpdateHistograms() { |
| 926 // We need at least the receive timers to be filled in, as otherwise | 915 // We need at least the receive timers to be filled in, as otherwise |
| 927 // metrics can be bogus. | 916 // metrics can be bogus. |
| 928 if (recv_first_byte_time_.is_null() || recv_last_byte_time_.is_null()) | 917 if (recv_first_byte_time_.is_null() || recv_last_byte_time_.is_null()) |
| 929 return; | 918 return; |
| 930 | 919 |
| 931 base::TimeTicks effective_send_time; | 920 base::TimeTicks effective_send_time; |
| 932 if (type_ == SPDY_PUSH_STREAM) { | 921 if (type_ == SPDY_PUSH_STREAM) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 986 GetWeakPtr(), payload_size)); | 975 GetWeakPtr(), payload_size)); |
| 987 } | 976 } |
| 988 | 977 |
| 989 session_->EnqueueStreamWrite( | 978 session_->EnqueueStreamWrite( |
| 990 GetWeakPtr(), DATA, | 979 GetWeakPtr(), DATA, |
| 991 scoped_ptr<SpdyBufferProducer>( | 980 scoped_ptr<SpdyBufferProducer>( |
| 992 new SimpleBufferProducer(data_buffer.Pass()))); | 981 new SimpleBufferProducer(data_buffer.Pass()))); |
| 993 } | 982 } |
| 994 | 983 |
| 995 } // namespace net | 984 } // namespace net |
| OLD | NEW |