Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/spdy/spdy_stream.h" | 5 #include "net/spdy/spdy_stream.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 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 |