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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 if (*i >= 'A' && *i <= 'Z') { | 65 if (*i >= 'A' && *i <= 'Z') { |
66 return true; | 66 return true; |
67 } | 67 } |
68 } | 68 } |
69 return false; | 69 return false; |
70 } | 70 } |
71 | 71 |
72 } // namespace | 72 } // namespace |
73 | 73 |
74 SpdyStream::SpdyStream(SpdySession* session, | 74 SpdyStream::SpdyStream(SpdySession* session, |
75 SpdyStreamId stream_id, | |
76 bool pushed, | 75 bool pushed, |
77 const BoundNetLog& net_log) | 76 const BoundNetLog& net_log) |
78 : continue_buffering_data_(true), | 77 : continue_buffering_data_(true), |
79 stream_id_(stream_id), | 78 stream_id_(0), |
80 priority_(HIGHEST), | 79 priority_(HIGHEST), |
81 slot_(0), | 80 slot_(0), |
82 stalled_by_flow_control_(false), | 81 stalled_by_flow_control_(false), |
83 send_window_size_(kSpdyStreamInitialWindowSize), | 82 send_window_size_(kSpdyStreamInitialWindowSize), |
84 recv_window_size_(kSpdyStreamInitialWindowSize), | 83 recv_window_size_(kSpdyStreamInitialWindowSize), |
85 unacked_recv_window_bytes_(0), | 84 unacked_recv_window_bytes_(0), |
86 pushed_(pushed), | 85 pushed_(pushed), |
87 response_received_(false), | 86 response_received_(false), |
88 session_(session), | 87 session_(session), |
89 delegate_(NULL), | 88 delegate_(NULL), |
90 request_time_(base::Time::Now()), | 89 request_time_(base::Time::Now()), |
91 response_(new SpdyHeaderBlock), | 90 response_(new SpdyHeaderBlock), |
92 io_state_(STATE_NONE), | 91 io_state_(STATE_NONE), |
93 response_status_(OK), | 92 response_status_(OK), |
94 cancelled_(false), | 93 cancelled_(false), |
95 has_upload_data_(false), | 94 has_upload_data_(false), |
96 net_log_(net_log), | 95 net_log_(net_log), |
97 send_bytes_(0), | 96 send_bytes_(0), |
98 recv_bytes_(0), | 97 recv_bytes_(0), |
99 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { | 98 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { |
100 } | 99 } |
101 | 100 |
| 101 class SpdyStream::SpdyStreamFrameProducer |
| 102 : public SpdySession::SpdyFrameProducer { |
| 103 public: |
| 104 SpdyStreamFrameProducer(SpdyStream* stream) : stream_(stream) {} |
| 105 |
| 106 // SpdyFrameProducer |
| 107 virtual RequestPriority GetPriority() const OVERRIDE { |
| 108 return stream_->priority(); |
| 109 } |
| 110 virtual SpdyFrame* ProduceNextFrame(SpdySession* spdy_session) OVERRIDE { |
| 111 if (stream_->stream_id() == 0) |
| 112 ActivateStream(spdy_session, stream_); |
| 113 return stream_->ProduceNextFrame(); |
| 114 } |
| 115 virtual SpdyStream* GetSpdyStream() OVERRIDE { |
| 116 return stream_.get(); |
| 117 } |
| 118 |
| 119 private: |
| 120 scoped_refptr<SpdyStream> stream_; |
| 121 |
| 122 }; |
| 123 |
| 124 SpdySession::SpdyFrameProducer* SpdyStream::CreateProducer() { |
| 125 return new SpdyStreamFrameProducer(this); |
| 126 } |
| 127 |
| 128 SpdyFrame* SpdyStream::ProduceNextFrame() { |
| 129 if (io_state_ == STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE) { |
| 130 CHECK(request_.get()); |
| 131 CHECK_GT(stream_id_, 0u); |
| 132 |
| 133 std::string origin = GetUrl().GetOrigin().spec(); |
| 134 origin.erase(origin.length() - 1); // trim trailing slash |
| 135 SpdyCredentialControlFrame* frame = session_->CreateCredentialFrame( |
| 136 origin, domain_bound_cert_type_, domain_bound_private_key_, |
| 137 domain_bound_cert_, priority_); |
| 138 return frame; |
| 139 } else if (io_state_ == STATE_SEND_HEADERS_COMPLETE) { |
| 140 CHECK(request_.get()); |
| 141 CHECK_GT(stream_id_, 0u); |
| 142 |
| 143 SpdyControlFlags flags = |
| 144 has_upload_data_ ? CONTROL_FLAG_NONE : CONTROL_FLAG_FIN; |
| 145 SpdySynStreamControlFrame* frame = session_->CreateSynStream( |
| 146 stream_id_, priority_, slot_, flags, request_); |
| 147 set_stream_id(frame->stream_id()); |
| 148 send_time_ = base::TimeTicks::Now(); |
| 149 return frame; |
| 150 } else { |
| 151 CHECK(!cancelled()); |
| 152 // We must need to write stream data. |
| 153 // Until the headers have been completely sent, we can not be sure |
| 154 // that our stream_id is correct. |
| 155 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); |
| 156 DCHECK_GT(stream_id_, 0u); |
| 157 DCHECK(!pending_data_frames_.empty()); |
| 158 SpdyFrame* frame = pending_data_frames_.front(); |
| 159 pending_data_frames_.pop_front(); |
| 160 return frame; |
| 161 } |
| 162 } |
| 163 |
102 SpdyStream::~SpdyStream() { | 164 SpdyStream::~SpdyStream() { |
103 UpdateHistograms(); | 165 UpdateHistograms(); |
| 166 while (!pending_data_frames_.empty()) { |
| 167 SpdyFrame* frame = pending_data_frames_.back(); |
| 168 pending_data_frames_.pop_back(); |
| 169 delete frame; |
| 170 } |
104 } | 171 } |
105 | 172 |
106 void SpdyStream::SetDelegate(Delegate* delegate) { | 173 void SpdyStream::SetDelegate(Delegate* delegate) { |
107 CHECK(delegate); | 174 CHECK(delegate); |
108 delegate_ = delegate; | 175 delegate_ = delegate; |
109 | 176 |
110 if (pushed_) { | 177 if (pushed_) { |
111 CHECK(response_received()); | 178 CHECK(response_received()); |
112 MessageLoop::current()->PostTask( | 179 MessageLoop::current()->PostTask( |
113 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this)); | 180 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this)); |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 void SpdyStream::Cancel() { | 555 void SpdyStream::Cancel() { |
489 if (cancelled()) | 556 if (cancelled()) |
490 return; | 557 return; |
491 | 558 |
492 cancelled_ = true; | 559 cancelled_ = true; |
493 if (session_->IsStreamActive(stream_id_)) | 560 if (session_->IsStreamActive(stream_id_)) |
494 session_->ResetStream(stream_id_, CANCEL, ""); | 561 session_->ResetStream(stream_id_, CANCEL, ""); |
495 } | 562 } |
496 | 563 |
497 void SpdyStream::Close() { | 564 void SpdyStream::Close() { |
498 session_->CloseStream(stream_id_, net::OK); | 565 if (stream_id_ != 0) |
| 566 session_->CloseStream(stream_id_, net::OK); |
| 567 else |
| 568 session_->CloseCreatedStream(this, OK); |
499 } | 569 } |
500 | 570 |
501 int SpdyStream::SendRequest(bool has_upload_data) { | 571 int SpdyStream::SendRequest(bool has_upload_data) { |
502 if (delegate_) | 572 if (delegate_) |
503 delegate_->set_chunk_callback(this); | 573 delegate_->set_chunk_callback(this); |
504 | 574 |
505 // Pushed streams do not send any data, and should always be in STATE_OPEN or | 575 // Pushed streams do not send any data, and should always be in STATE_OPEN or |
506 // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push | 576 // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push |
507 // behavior. | 577 // behavior. |
508 has_upload_data_ = has_upload_data; | 578 has_upload_data_ = has_upload_data; |
509 if (pushed_) { | 579 if (pushed_) { |
510 send_time_ = base::TimeTicks::Now(); | 580 send_time_ = base::TimeTicks::Now(); |
511 DCHECK(!has_upload_data_); | 581 DCHECK(!has_upload_data_); |
512 DCHECK(response_received()); | 582 DCHECK(response_received()); |
513 return ERR_IO_PENDING; | 583 return ERR_IO_PENDING; |
514 } | 584 } |
515 CHECK_EQ(STATE_NONE, io_state_); | 585 CHECK_EQ(STATE_NONE, io_state_); |
516 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; | 586 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; |
517 return DoLoop(OK); | 587 return DoLoop(OK); |
518 } | 588 } |
519 | 589 |
520 int SpdyStream::WriteStreamData(IOBuffer* data, int length, | 590 int SpdyStream::WriteStreamData(IOBuffer* data, int length, |
521 SpdyDataFlags flags) { | 591 SpdyDataFlags flags) { |
522 // Until the headers have been completely sent, we can not be sure | 592 // Until the headers have been completely sent, we can not be sure |
523 // that our stream_id is correct. | 593 // that our stream_id is correct. |
524 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); | 594 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); |
525 return session_->WriteStreamData(stream_id_, data, length, flags); | 595 CHECK_GT(stream_id_, 0u); |
| 596 |
| 597 pending_data_frames_.push_back( |
| 598 session_->CreateDataFrame(stream_id_, data, length, flags)); |
| 599 |
| 600 session_->SetStreamHasWriteAvailable(this); |
| 601 return ERR_IO_PENDING; |
526 } | 602 } |
527 | 603 |
528 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, | 604 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, |
529 bool* was_npn_negotiated, | 605 bool* was_npn_negotiated, |
530 NextProto* protocol_negotiated) { | 606 NextProto* protocol_negotiated) { |
531 return session_->GetSSLInfo( | 607 return session_->GetSSLInfo( |
532 ssl_info, was_npn_negotiated, protocol_negotiated); | 608 ssl_info, was_npn_negotiated, protocol_negotiated); |
533 } | 609 } |
534 | 610 |
535 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { | 611 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 return result; | 735 return result; |
660 | 736 |
661 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; | 737 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; |
662 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); | 738 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); |
663 return OK; | 739 return OK; |
664 } | 740 } |
665 | 741 |
666 int SpdyStream::DoSendDomainBoundCert() { | 742 int SpdyStream::DoSendDomainBoundCert() { |
667 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; | 743 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; |
668 CHECK(request_.get()); | 744 CHECK(request_.get()); |
669 std::string origin = GetUrl().GetOrigin().spec(); | 745 session_->SetStreamHasWriteAvailable(this); |
670 origin.erase(origin.length() - 1); // trim trailing slash | 746 return ERR_IO_PENDING; |
671 int rv = session_->WriteCredentialFrame( | |
672 origin, domain_bound_cert_type_, domain_bound_private_key_, | |
673 domain_bound_cert_, priority_); | |
674 if (rv != ERR_IO_PENDING) | |
675 return rv; | |
676 return OK; | |
677 } | 747 } |
678 | 748 |
679 int SpdyStream::DoSendDomainBoundCertComplete(int result) { | 749 int SpdyStream::DoSendDomainBoundCertComplete(int result) { |
680 if (result < 0) | 750 if (result < 0) |
681 return result; | 751 return result; |
682 | 752 |
683 io_state_ = STATE_SEND_HEADERS; | 753 io_state_ = STATE_SEND_HEADERS; |
684 return OK; | 754 return OK; |
685 } | 755 } |
686 | 756 |
687 int SpdyStream::DoSendHeaders() { | 757 int SpdyStream::DoSendHeaders() { |
688 CHECK(!cancelled_); | 758 CHECK(!cancelled_); |
689 | 759 |
690 SpdyControlFlags flags = CONTROL_FLAG_NONE; | 760 session_->SetStreamHasWriteAvailable(this); |
691 if (!has_upload_data_) | |
692 flags = CONTROL_FLAG_FIN; | |
693 | |
694 CHECK(request_.get()); | |
695 int result = session_->WriteSynStream( | |
696 stream_id_, priority_, slot_, flags, | |
697 request_); | |
698 if (result != ERR_IO_PENDING) | |
699 return result; | |
700 | |
701 send_time_ = base::TimeTicks::Now(); | |
702 io_state_ = STATE_SEND_HEADERS_COMPLETE; | 761 io_state_ = STATE_SEND_HEADERS_COMPLETE; |
703 return ERR_IO_PENDING; | 762 return ERR_IO_PENDING; |
704 } | 763 } |
705 | 764 |
706 int SpdyStream::DoSendHeadersComplete(int result) { | 765 int SpdyStream::DoSendHeadersComplete(int result) { |
707 if (result < 0) | 766 if (result < 0) |
708 return result; | 767 return result; |
709 | 768 |
710 CHECK_GT(result, 0); | 769 CHECK_GT(result, 0); |
711 | 770 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", | 830 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", |
772 recv_last_byte_time_ - recv_first_byte_time_); | 831 recv_last_byte_time_ - recv_first_byte_time_); |
773 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", | 832 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", |
774 recv_last_byte_time_ - send_time_); | 833 recv_last_byte_time_ - send_time_); |
775 | 834 |
776 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); | 835 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); |
777 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); | 836 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); |
778 } | 837 } |
779 | 838 |
780 } // namespace net | 839 } // namespace net |
OLD | NEW |