Chromium Code Reviews| Index: net/spdy/spdy_stream.cc |
| diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc |
| index 9d0f552efbca70d5917a69e5754df024e7c9dae8..47311681c45ffbe5b02b890d8182749e3d81ea78 100644 |
| --- a/net/spdy/spdy_stream.cc |
| +++ b/net/spdy/spdy_stream.cc |
| @@ -50,11 +50,10 @@ bool ContainsUpperAscii(const std::string& str) { |
| } // namespace |
| SpdyStream::SpdyStream(SpdySession* session, |
| - SpdyStreamId stream_id, |
| bool pushed, |
| const BoundNetLog& net_log) |
| : continue_buffering_data_(true), |
| - stream_id_(stream_id), |
| + stream_id_(0), |
| priority_(HIGHEST), |
| slot_(0), |
| stalled_by_flow_control_(false), |
| @@ -77,8 +76,77 @@ SpdyStream::SpdyStream(SpdySession* session, |
| domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { |
| } |
| +class SpdyStream::SpdyStreamIOBufferProducer |
| + : public SpdySession::SpdyIOBufferProducer { |
| + public: |
| + SpdyStreamIOBufferProducer(SpdyStream* stream) : stream_(stream) {} |
| + |
| + // SpdyFrameProducer |
| + virtual RequestPriority GetPriority() const OVERRIDE { |
| + return stream_->priority(); |
| + } |
| + |
| + virtual SpdyIOBuffer* ProduceNextBuffer(SpdySession* session) OVERRIDE { |
| + if (stream_->stream_id() == 0) |
| + SpdySession::SpdyIOBufferProducer::ActivateStream(session, stream_); |
| + SpdyFrame* frame = stream_->ProduceNextFrame(); |
| + return frame == NULL ? NULL : |
| + SpdySession::SpdyIOBufferProducer::CreateIOBuffer( |
| + frame, GetPriority(), stream_); |
| + } |
| + |
| + private: |
| + scoped_refptr<SpdyStream> stream_; |
| + |
| +}; |
| + |
| +SpdySession::SpdyIOBufferProducer* SpdyStream::CreateProducer() { |
|
willchan no longer on Chromium
2012/06/26 17:07:27
I don't feel strongly. I don't really know why I f
Ryan Hamilton
2012/06/26 17:55:24
Done. Heh, fair enough. Both approaches work for
|
| + return new SpdyStreamIOBufferProducer(this); |
| +} |
| + |
| +SpdyFrame* SpdyStream::ProduceNextFrame() { |
| + if (io_state_ == STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE) { |
| + CHECK(request_.get()); |
| + CHECK_GT(stream_id_, 0u); |
| + |
| + std::string origin = GetUrl().GetOrigin().spec(); |
| + origin.erase(origin.length() - 1); // trim trailing slash |
| + SpdyCredentialControlFrame* frame = session_->CreateCredentialFrame( |
| + origin, domain_bound_cert_type_, domain_bound_private_key_, |
| + domain_bound_cert_, priority_); |
| + return frame; |
| + } else if (io_state_ == STATE_SEND_HEADERS_COMPLETE) { |
| + CHECK(request_.get()); |
| + CHECK_GT(stream_id_, 0u); |
| + |
| + SpdyControlFlags flags = |
| + has_upload_data_ ? CONTROL_FLAG_NONE : CONTROL_FLAG_FIN; |
| + SpdySynStreamControlFrame* frame = session_->CreateSynStream( |
| + stream_id_, priority_, slot_, flags, request_); |
| + set_stream_id(frame->stream_id()); |
| + send_time_ = base::TimeTicks::Now(); |
| + return frame; |
| + } else { |
| + CHECK(!cancelled()); |
| + // We must need to write stream data. |
| + // Until the headers have been completely sent, we can not be sure |
| + // that our stream_id is correct. |
| + DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); |
| + DCHECK_GT(stream_id_, 0u); |
| + DCHECK(!pending_data_frames_.empty()); |
| + SpdyFrame* frame = pending_data_frames_.front(); |
| + pending_data_frames_.pop_front(); |
| + return frame; |
| + } |
| +} |
| + |
| SpdyStream::~SpdyStream() { |
| UpdateHistograms(); |
| + while (!pending_data_frames_.empty()) { |
| + SpdyFrame* frame = pending_data_frames_.back(); |
| + pending_data_frames_.pop_back(); |
| + delete frame; |
| + } |
| } |
| void SpdyStream::SetDelegate(Delegate* delegate) { |
| @@ -472,7 +540,10 @@ void SpdyStream::Cancel() { |
| } |
| void SpdyStream::Close() { |
| - session_->CloseStream(stream_id_, net::OK); |
| + if (stream_id_ != 0) |
| + session_->CloseStream(stream_id_, net::OK); |
| + else |
| + session_->CloseCreatedStream(this, OK); |
| } |
| int SpdyStream::SendRequest(bool has_upload_data) { |
| @@ -499,7 +570,13 @@ int SpdyStream::WriteStreamData(IOBuffer* data, int length, |
| // Until the headers have been completely sent, we can not be sure |
| // that our stream_id is correct. |
| DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); |
| - return session_->WriteStreamData(stream_id_, data, length, flags); |
| + CHECK_GT(stream_id_, 0u); |
| + |
| + pending_data_frames_.push_back( |
| + session_->CreateDataFrame(stream_id_, data, length, flags)); |
| + |
| + session_->SetStreamHasWriteAvailable(this); |
| + return ERR_IO_PENDING; |
| } |
| bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, |
| @@ -643,14 +720,8 @@ int SpdyStream::DoGetDomainBoundCertComplete(int result) { |
| int SpdyStream::DoSendDomainBoundCert() { |
| io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; |
| CHECK(request_.get()); |
| - std::string origin = GetUrl().GetOrigin().spec(); |
| - origin.erase(origin.length() - 1); // trim trailing slash |
| - int rv = session_->WriteCredentialFrame( |
| - origin, domain_bound_cert_type_, domain_bound_private_key_, |
| - domain_bound_cert_, priority_); |
| - if (rv != ERR_IO_PENDING) |
| - return rv; |
| - return OK; |
| + session_->SetStreamHasWriteAvailable(this); |
| + return ERR_IO_PENDING; |
| } |
| int SpdyStream::DoSendDomainBoundCertComplete(int result) { |
| @@ -664,18 +735,7 @@ int SpdyStream::DoSendDomainBoundCertComplete(int result) { |
| int SpdyStream::DoSendHeaders() { |
| CHECK(!cancelled_); |
| - SpdyControlFlags flags = CONTROL_FLAG_NONE; |
| - if (!has_upload_data_) |
| - flags = CONTROL_FLAG_FIN; |
| - |
| - CHECK(request_.get()); |
| - int result = session_->WriteSynStream( |
| - stream_id_, priority_, slot_, flags, |
| - request_); |
| - if (result != ERR_IO_PENDING) |
| - return result; |
| - |
| - send_time_ = base::TimeTicks::Now(); |
| + session_->SetStreamHasWriteAvailable(this); |
| io_state_ = STATE_SEND_HEADERS_COMPLETE; |
| return ERR_IO_PENDING; |
| } |