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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 if (*i >= 'A' && *i <= 'Z') { | 43 if (*i >= 'A' && *i <= 'Z') { |
44 return true; | 44 return true; |
45 } | 45 } |
46 } | 46 } |
47 return false; | 47 return false; |
48 } | 48 } |
49 | 49 |
50 } // namespace | 50 } // namespace |
51 | 51 |
52 SpdyStream::SpdyStream(SpdySession* session, | 52 SpdyStream::SpdyStream(SpdySession* session, |
53 SpdyStreamId stream_id, | |
54 bool pushed, | 53 bool pushed, |
55 const BoundNetLog& net_log) | 54 const BoundNetLog& net_log) |
56 : continue_buffering_data_(true), | 55 : continue_buffering_data_(true), |
57 stream_id_(stream_id), | 56 stream_id_(0), |
58 priority_(HIGHEST), | 57 priority_(HIGHEST), |
59 slot_(0), | 58 slot_(0), |
60 stalled_by_flow_control_(false), | 59 stalled_by_flow_control_(false), |
61 send_window_size_(kSpdyStreamInitialWindowSize), | 60 send_window_size_(kSpdyStreamInitialWindowSize), |
62 recv_window_size_(kSpdyStreamInitialWindowSize), | 61 recv_window_size_(kSpdyStreamInitialWindowSize), |
63 unacked_recv_window_bytes_(0), | 62 unacked_recv_window_bytes_(0), |
64 pushed_(pushed), | 63 pushed_(pushed), |
65 response_received_(false), | 64 response_received_(false), |
66 session_(session), | 65 session_(session), |
67 delegate_(NULL), | 66 delegate_(NULL), |
68 request_time_(base::Time::Now()), | 67 request_time_(base::Time::Now()), |
69 response_(new SpdyHeaderBlock), | 68 response_(new SpdyHeaderBlock), |
70 io_state_(STATE_NONE), | 69 io_state_(STATE_NONE), |
71 response_status_(OK), | 70 response_status_(OK), |
72 cancelled_(false), | 71 cancelled_(false), |
73 has_upload_data_(false), | 72 has_upload_data_(false), |
74 net_log_(net_log), | 73 net_log_(net_log), |
75 send_bytes_(0), | 74 send_bytes_(0), |
76 recv_bytes_(0), | 75 recv_bytes_(0), |
77 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { | 76 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { |
78 } | 77 } |
79 | 78 |
| 79 class SpdyStream::SpdyStreamIOBufferProducer |
| 80 : public SpdySession::SpdyIOBufferProducer { |
| 81 public: |
| 82 SpdyStreamIOBufferProducer(SpdyStream* stream) : stream_(stream) {} |
| 83 |
| 84 // SpdyFrameProducer |
| 85 virtual RequestPriority GetPriority() const OVERRIDE { |
| 86 return stream_->priority(); |
| 87 } |
| 88 |
| 89 virtual SpdyIOBuffer* ProduceNextBuffer(SpdySession* session) OVERRIDE { |
| 90 if (stream_->stream_id() == 0) |
| 91 SpdySession::SpdyIOBufferProducer::ActivateStream(session, stream_); |
| 92 frame_.reset(stream_->ProduceNextFrame()); |
| 93 return frame_ == NULL ? NULL : |
| 94 SpdySession::SpdyIOBufferProducer::CreateIOBuffer( |
| 95 frame_.get(), GetPriority(), stream_); |
| 96 } |
| 97 |
| 98 private: |
| 99 scoped_refptr<SpdyStream> stream_; |
| 100 scoped_ptr<SpdyFrame> frame_; |
| 101 }; |
| 102 |
| 103 void SpdyStream::SetHasWriteAvailable() { |
| 104 session_->SetStreamHasWriteAvailable(this, |
| 105 new SpdyStreamIOBufferProducer(this)); |
| 106 } |
| 107 |
| 108 SpdyFrame* SpdyStream::ProduceNextFrame() { |
| 109 if (io_state_ == STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE) { |
| 110 CHECK(request_.get()); |
| 111 CHECK_GT(stream_id_, 0u); |
| 112 |
| 113 std::string origin = GetUrl().GetOrigin().spec(); |
| 114 DCHECK(origin[origin.length() - 1] == '/'); |
| 115 origin.erase(origin.length() - 1); // Trim trailing slash. |
| 116 SpdyCredentialControlFrame* frame = session_->CreateCredentialFrame( |
| 117 origin, domain_bound_cert_type_, domain_bound_private_key_, |
| 118 domain_bound_cert_, priority_); |
| 119 return frame; |
| 120 } else if (io_state_ == STATE_SEND_HEADERS_COMPLETE) { |
| 121 CHECK(request_.get()); |
| 122 CHECK_GT(stream_id_, 0u); |
| 123 |
| 124 SpdyControlFlags flags = |
| 125 has_upload_data_ ? CONTROL_FLAG_NONE : CONTROL_FLAG_FIN; |
| 126 SpdySynStreamControlFrame* frame = session_->CreateSynStream( |
| 127 stream_id_, priority_, slot_, flags, *request_); |
| 128 send_time_ = base::TimeTicks::Now(); |
| 129 return frame; |
| 130 } else { |
| 131 CHECK(!cancelled()); |
| 132 // We must need to write stream data. |
| 133 // Until the headers have been completely sent, we can not be sure |
| 134 // that our stream_id is correct. |
| 135 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); |
| 136 DCHECK_GT(stream_id_, 0u); |
| 137 DCHECK(!pending_data_frames_.empty()); |
| 138 SpdyFrame* frame = pending_data_frames_.front(); |
| 139 pending_data_frames_.pop_front(); |
| 140 return frame; |
| 141 } |
| 142 } |
| 143 |
80 SpdyStream::~SpdyStream() { | 144 SpdyStream::~SpdyStream() { |
81 UpdateHistograms(); | 145 UpdateHistograms(); |
| 146 while (!pending_data_frames_.empty()) { |
| 147 SpdyFrame* frame = pending_data_frames_.back(); |
| 148 pending_data_frames_.pop_back(); |
| 149 delete frame; |
| 150 } |
82 } | 151 } |
83 | 152 |
84 void SpdyStream::SetDelegate(Delegate* delegate) { | 153 void SpdyStream::SetDelegate(Delegate* delegate) { |
85 CHECK(delegate); | 154 CHECK(delegate); |
86 delegate_ = delegate; | 155 delegate_ = delegate; |
87 | 156 |
88 if (pushed_) { | 157 if (pushed_) { |
89 CHECK(response_received()); | 158 CHECK(response_received()); |
90 MessageLoop::current()->PostTask( | 159 MessageLoop::current()->PostTask( |
91 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this)); | 160 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this)); |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 void SpdyStream::Cancel() { | 522 void SpdyStream::Cancel() { |
454 if (cancelled()) | 523 if (cancelled()) |
455 return; | 524 return; |
456 | 525 |
457 cancelled_ = true; | 526 cancelled_ = true; |
458 if (session_->IsStreamActive(stream_id_)) | 527 if (session_->IsStreamActive(stream_id_)) |
459 session_->ResetStream(stream_id_, CANCEL, ""); | 528 session_->ResetStream(stream_id_, CANCEL, ""); |
460 } | 529 } |
461 | 530 |
462 void SpdyStream::Close() { | 531 void SpdyStream::Close() { |
463 session_->CloseStream(stream_id_, net::OK); | 532 if (stream_id_ != 0) |
| 533 session_->CloseStream(stream_id_, net::OK); |
| 534 else |
| 535 session_->CloseCreatedStream(this, OK); |
464 } | 536 } |
465 | 537 |
466 int SpdyStream::SendRequest(bool has_upload_data) { | 538 int SpdyStream::SendRequest(bool has_upload_data) { |
467 // Pushed streams do not send any data, and should always be in STATE_OPEN or | 539 // Pushed streams do not send any data, and should always be in STATE_OPEN or |
468 // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push | 540 // STATE_DONE. However, we still want to return IO_PENDING to mimic non-push |
469 // behavior. | 541 // behavior. |
470 has_upload_data_ = has_upload_data; | 542 has_upload_data_ = has_upload_data; |
471 if (pushed_) { | 543 if (pushed_) { |
472 send_time_ = base::TimeTicks::Now(); | 544 send_time_ = base::TimeTicks::Now(); |
473 DCHECK(!has_upload_data_); | 545 DCHECK(!has_upload_data_); |
474 DCHECK(response_received()); | 546 DCHECK(response_received()); |
475 return ERR_IO_PENDING; | 547 return ERR_IO_PENDING; |
476 } | 548 } |
477 CHECK_EQ(STATE_NONE, io_state_); | 549 CHECK_EQ(STATE_NONE, io_state_); |
478 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; | 550 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; |
479 return DoLoop(OK); | 551 return DoLoop(OK); |
480 } | 552 } |
481 | 553 |
482 int SpdyStream::WriteStreamData(IOBuffer* data, int length, | 554 int SpdyStream::WriteStreamData(IOBuffer* data, int length, |
483 SpdyDataFlags flags) { | 555 SpdyDataFlags flags) { |
484 // Until the headers have been completely sent, we can not be sure | 556 // Until the headers have been completely sent, we can not be sure |
485 // that our stream_id is correct. | 557 // that our stream_id is correct. |
486 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); | 558 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); |
487 return session_->WriteStreamData(stream_id_, data, length, flags); | 559 CHECK_GT(stream_id_, 0u); |
| 560 |
| 561 pending_data_frames_.push_back( |
| 562 session_->CreateDataFrame(stream_id_, data, length, flags)); |
| 563 |
| 564 SetHasWriteAvailable(); |
| 565 return ERR_IO_PENDING; |
488 } | 566 } |
489 | 567 |
490 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, | 568 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, |
491 bool* was_npn_negotiated, | 569 bool* was_npn_negotiated, |
492 NextProto* protocol_negotiated) { | 570 NextProto* protocol_negotiated) { |
493 return session_->GetSSLInfo( | 571 return session_->GetSSLInfo( |
494 ssl_info, was_npn_negotiated, protocol_negotiated); | 572 ssl_info, was_npn_negotiated, protocol_negotiated); |
495 } | 573 } |
496 | 574 |
497 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { | 575 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 return result; | 699 return result; |
622 | 700 |
623 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; | 701 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; |
624 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); | 702 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); |
625 return OK; | 703 return OK; |
626 } | 704 } |
627 | 705 |
628 int SpdyStream::DoSendDomainBoundCert() { | 706 int SpdyStream::DoSendDomainBoundCert() { |
629 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; | 707 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; |
630 CHECK(request_.get()); | 708 CHECK(request_.get()); |
631 std::string origin = GetUrl().GetOrigin().spec(); | 709 SetHasWriteAvailable(); |
632 origin.erase(origin.length() - 1); // trim trailing slash | 710 return ERR_IO_PENDING; |
633 int rv = session_->WriteCredentialFrame( | |
634 origin, domain_bound_cert_type_, domain_bound_private_key_, | |
635 domain_bound_cert_, priority_); | |
636 if (rv != ERR_IO_PENDING) | |
637 return rv; | |
638 return OK; | |
639 } | 711 } |
640 | 712 |
641 int SpdyStream::DoSendDomainBoundCertComplete(int result) { | 713 int SpdyStream::DoSendDomainBoundCertComplete(int result) { |
642 if (result < 0) | 714 if (result < 0) |
643 return result; | 715 return result; |
644 | 716 |
645 io_state_ = STATE_SEND_HEADERS; | 717 io_state_ = STATE_SEND_HEADERS; |
646 return OK; | 718 return OK; |
647 } | 719 } |
648 | 720 |
649 int SpdyStream::DoSendHeaders() { | 721 int SpdyStream::DoSendHeaders() { |
650 CHECK(!cancelled_); | 722 CHECK(!cancelled_); |
651 | 723 |
652 SpdyControlFlags flags = CONTROL_FLAG_NONE; | 724 SetHasWriteAvailable(); |
653 if (!has_upload_data_) | |
654 flags = CONTROL_FLAG_FIN; | |
655 | |
656 CHECK(request_.get()); | |
657 int result = session_->WriteSynStream( | |
658 stream_id_, priority_, slot_, flags, | |
659 *request_); | |
660 if (result != ERR_IO_PENDING) | |
661 return result; | |
662 | |
663 send_time_ = base::TimeTicks::Now(); | |
664 io_state_ = STATE_SEND_HEADERS_COMPLETE; | 725 io_state_ = STATE_SEND_HEADERS_COMPLETE; |
665 return ERR_IO_PENDING; | 726 return ERR_IO_PENDING; |
666 } | 727 } |
667 | 728 |
668 int SpdyStream::DoSendHeadersComplete(int result) { | 729 int SpdyStream::DoSendHeadersComplete(int result) { |
669 if (result < 0) | 730 if (result < 0) |
670 return result; | 731 return result; |
671 | 732 |
672 CHECK_GT(result, 0); | 733 CHECK_GT(result, 0); |
673 | 734 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
733 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", | 794 UMA_HISTOGRAM_TIMES("Net.SpdyStreamDownloadTime", |
734 recv_last_byte_time_ - recv_first_byte_time_); | 795 recv_last_byte_time_ - recv_first_byte_time_); |
735 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", | 796 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTime", |
736 recv_last_byte_time_ - send_time_); | 797 recv_last_byte_time_ - send_time_); |
737 | 798 |
738 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); | 799 UMA_HISTOGRAM_COUNTS("Net.SpdySendBytes", send_bytes_); |
739 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); | 800 UMA_HISTOGRAM_COUNTS("Net.SpdyRecvBytes", recv_bytes_); |
740 } | 801 } |
741 | 802 |
742 } // namespace net | 803 } // namespace net |
OLD | NEW |