Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(827)

Side by Side Diff: net/spdy/bidirectional_stream_spdy_impl.cc

Issue 2462463002: Make net::BidirectionalStream handle RST_STREAM_NO_ERROR (Closed)
Patch Set: Address Andrei's comments Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/bidirectional_stream_spdy_impl.h" 5 #include "net/spdy/bidirectional_stream_spdy_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
(...skipping 16 matching lines...) Expand all
27 } // namespace 27 } // namespace
28 28
29 BidirectionalStreamSpdyImpl::BidirectionalStreamSpdyImpl( 29 BidirectionalStreamSpdyImpl::BidirectionalStreamSpdyImpl(
30 const base::WeakPtr<SpdySession>& spdy_session) 30 const base::WeakPtr<SpdySession>& spdy_session)
31 : spdy_session_(spdy_session), 31 : spdy_session_(spdy_session),
32 request_info_(nullptr), 32 request_info_(nullptr),
33 delegate_(nullptr), 33 delegate_(nullptr),
34 negotiated_protocol_(kProtoUnknown), 34 negotiated_protocol_(kProtoUnknown),
35 more_read_data_pending_(false), 35 more_read_data_pending_(false),
36 read_buffer_len_(0), 36 read_buffer_len_(0),
37 written_end_of_stream_(false),
38 write_pending_(false),
37 stream_closed_(false), 39 stream_closed_(false),
38 closed_stream_status_(ERR_FAILED), 40 closed_stream_status_(ERR_FAILED),
39 closed_stream_received_bytes_(0), 41 closed_stream_received_bytes_(0),
40 closed_stream_sent_bytes_(0), 42 closed_stream_sent_bytes_(0),
41 closed_has_load_timing_info_(false), 43 closed_has_load_timing_info_(false),
42 weak_factory_(this) {} 44 weak_factory_(this) {}
43 45
44 BidirectionalStreamSpdyImpl::~BidirectionalStreamSpdyImpl() { 46 BidirectionalStreamSpdyImpl::~BidirectionalStreamSpdyImpl() {
45 // Sends a RST to the remote if the stream is destroyed before it completes. 47 // Sends a RST to the remote if the stream is destroyed before it completes.
46 ResetStream(); 48 ResetStream();
49 DCHECK(!write_pending_);
47 } 50 }
48 51
49 void BidirectionalStreamSpdyImpl::Start( 52 void BidirectionalStreamSpdyImpl::Start(
50 const BidirectionalStreamRequestInfo* request_info, 53 const BidirectionalStreamRequestInfo* request_info,
51 const NetLogWithSource& net_log, 54 const NetLogWithSource& net_log,
52 bool /*send_request_headers_automatically*/, 55 bool /*send_request_headers_automatically*/,
53 BidirectionalStreamImpl::Delegate* delegate, 56 BidirectionalStreamImpl::Delegate* delegate,
54 std::unique_ptr<base::Timer> timer) { 57 std::unique_ptr<base::Timer> timer) {
55 DCHECK(!stream_); 58 DCHECK(!stream_);
56 DCHECK(timer); 59 DCHECK(timer);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 // called upon completion. 103 // called upon completion.
101 read_buffer_ = buf; 104 read_buffer_ = buf;
102 read_buffer_len_ = buf_len; 105 read_buffer_len_ = buf_len;
103 return ERR_IO_PENDING; 106 return ERR_IO_PENDING;
104 } 107 }
105 108
106 void BidirectionalStreamSpdyImpl::SendData(const scoped_refptr<IOBuffer>& data, 109 void BidirectionalStreamSpdyImpl::SendData(const scoped_refptr<IOBuffer>& data,
107 int length, 110 int length,
108 bool end_stream) { 111 bool end_stream) {
109 DCHECK(length > 0 || (length == 0 && end_stream)); 112 DCHECK(length > 0 || (length == 0 && end_stream));
113 DCHECK(!write_pending_);
110 114
111 if (!stream_) { 115 if (!written_end_of_stream_) {
112 LOG(ERROR) << "Trying to send data after stream has been destroyed."; 116 LOG(ERROR) << "Writing after end of stream is written.";
113 base::ThreadTaskRunnerHandle::Get()->PostTask( 117 base::ThreadTaskRunnerHandle::Get()->PostTask(
114 FROM_HERE, base::Bind(&BidirectionalStreamSpdyImpl::NotifyError, 118 FROM_HERE, base::Bind(&BidirectionalStreamSpdyImpl::NotifyError,
115 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); 119 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED));
116 return; 120 return;
117 } 121 }
118 122
123 write_pending_ = true;
124 written_end_of_stream_ = end_stream;
125 if (MaybeHandleStreamClosedInSendData())
126 return;
127
119 DCHECK(!stream_closed_); 128 DCHECK(!stream_closed_);
120 stream_->SendData(data.get(), length, 129 stream_->SendData(data.get(), length,
121 end_stream ? NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND); 130 end_stream ? NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND);
122 } 131 }
123 132
124 void BidirectionalStreamSpdyImpl::SendvData( 133 void BidirectionalStreamSpdyImpl::SendvData(
125 const std::vector<scoped_refptr<IOBuffer>>& buffers, 134 const std::vector<scoped_refptr<IOBuffer>>& buffers,
126 const std::vector<int>& lengths, 135 const std::vector<int>& lengths,
127 bool end_stream) { 136 bool end_stream) {
128 DCHECK_EQ(buffers.size(), lengths.size()); 137 DCHECK_EQ(buffers.size(), lengths.size());
138 DCHECK(!write_pending_);
129 139
130 if (!stream_) { 140 if (!written_end_of_stream_) {
131 LOG(ERROR) << "Trying to send data after stream has been destroyed."; 141 LOG(ERROR) << "Writing after end of stream is written.";
132 base::ThreadTaskRunnerHandle::Get()->PostTask( 142 base::ThreadTaskRunnerHandle::Get()->PostTask(
133 FROM_HERE, base::Bind(&BidirectionalStreamSpdyImpl::NotifyError, 143 FROM_HERE, base::Bind(&BidirectionalStreamSpdyImpl::NotifyError,
134 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); 144 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED));
135 return; 145 return;
136 } 146 }
137 147
148 write_pending_ = true;
149 written_end_of_stream_ = end_stream;
150 if (MaybeHandleStreamClosedInSendData())
151 return;
152
138 DCHECK(!stream_closed_); 153 DCHECK(!stream_closed_);
139 int total_len = 0; 154 int total_len = 0;
140 for (int len : lengths) { 155 for (int len : lengths) {
141 total_len += len; 156 total_len += len;
142 } 157 }
143 158
144 pending_combined_buffer_ = new net::IOBuffer(total_len); 159 pending_combined_buffer_ = new net::IOBuffer(total_len);
145 int len = 0; 160 int len = 0;
146 // TODO(xunjieli): Get rid of extra copy. Coalesce headers and data frames. 161 // TODO(xunjieli): Get rid of extra copy. Coalesce headers and data frames.
147 for (size_t i = 0; i < buffers.size(); ++i) { 162 for (size_t i = 0; i < buffers.size(); ++i) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 276
262 if (status != OK) { 277 if (status != OK) {
263 NotifyError(status); 278 NotifyError(status);
264 return; 279 return;
265 } 280 }
266 ResetStream(); 281 ResetStream();
267 // Complete any remaining read, as all data has been buffered. 282 // Complete any remaining read, as all data has been buffered.
268 // If user has not called ReadData (i.e |read_buffer_| is nullptr), this will 283 // If user has not called ReadData (i.e |read_buffer_| is nullptr), this will
269 // do nothing. 284 // do nothing.
270 timer_->Stop(); 285 timer_->Stop();
286
287 // |this| might get destroyed after calling into |delegate_| in
288 // DoBufferedRead().
289 auto weak_this = weak_factory_.GetWeakPtr();
271 DoBufferedRead(); 290 DoBufferedRead();
291 if (weak_this.get() && write_pending_)
292 NotifyDataSent();
272 } 293 }
273 294
274 int BidirectionalStreamSpdyImpl::SendRequestHeadersHelper() { 295 int BidirectionalStreamSpdyImpl::SendRequestHeadersHelper() {
275 SpdyHeaderBlock headers; 296 SpdyHeaderBlock headers;
276 HttpRequestInfo http_request_info; 297 HttpRequestInfo http_request_info;
277 http_request_info.url = request_info_->url; 298 http_request_info.url = request_info_->url;
278 http_request_info.method = request_info_->method; 299 http_request_info.method = request_info_->method;
279 http_request_info.extra_headers = request_info_->extra_headers; 300 http_request_info.extra_headers = request_info_->extra_headers;
280 301
281 CreateSpdyHeadersFromHttpRequest( 302 CreateSpdyHeadersFromHttpRequest(
282 http_request_info, http_request_info.extra_headers, true, &headers); 303 http_request_info, http_request_info.extra_headers, true, &headers);
304 written_end_of_stream_ = request_info_->end_stream_on_headers;
283 return stream_->SendRequestHeaders(std::move(headers), 305 return stream_->SendRequestHeaders(std::move(headers),
284 request_info_->end_stream_on_headers 306 request_info_->end_stream_on_headers
285 ? NO_MORE_DATA_TO_SEND 307 ? NO_MORE_DATA_TO_SEND
286 : MORE_DATA_TO_SEND); 308 : MORE_DATA_TO_SEND);
287 } 309 }
288 310
289 void BidirectionalStreamSpdyImpl::OnStreamInitialized(int rv) { 311 void BidirectionalStreamSpdyImpl::OnStreamInitialized(int rv) {
290 DCHECK_NE(ERR_IO_PENDING, rv); 312 DCHECK_NE(ERR_IO_PENDING, rv);
291 if (rv == OK) { 313 if (rv == OK) {
292 stream_ = stream_request_.ReleaseStream(); 314 stream_ = stream_request_.ReleaseStream();
293 stream_->SetDelegate(this); 315 stream_->SetDelegate(this);
294 rv = SendRequestHeadersHelper(); 316 rv = SendRequestHeadersHelper();
295 if (rv == OK) { 317 if (rv == OK) {
296 OnRequestHeadersSent(); 318 OnRequestHeadersSent();
297 return; 319 return;
298 } else if (rv == ERR_IO_PENDING) { 320 } else if (rv == ERR_IO_PENDING) {
299 return; 321 return;
300 } 322 }
301 } 323 }
302 NotifyError(rv); 324 NotifyError(rv);
303 } 325 }
304 326
305 void BidirectionalStreamSpdyImpl::NotifyError(int rv) { 327 void BidirectionalStreamSpdyImpl::NotifyError(int rv) {
306 ResetStream(); 328 ResetStream();
329 write_pending_ = false;
307 if (delegate_) { 330 if (delegate_) {
308 BidirectionalStreamImpl::Delegate* delegate = delegate_; 331 BidirectionalStreamImpl::Delegate* delegate = delegate_;
309 delegate_ = nullptr; 332 delegate_ = nullptr;
310 // Cancel any pending callback. 333 // Cancel any pending callback.
311 weak_factory_.InvalidateWeakPtrs(); 334 weak_factory_.InvalidateWeakPtrs();
312 delegate->OnFailed(rv); 335 delegate->OnFailed(rv);
313 // |this| can be null when returned from delegate. 336 // |this| can be null when returned from delegate.
314 } 337 }
315 } 338 }
316 339
340 void BidirectionalStreamSpdyImpl::NotifyDataSent() {
341 DCHECK(write_pending_);
342
343 write_pending_ = false;
344 if (delegate_)
345 delegate_->OnDataSent();
346 }
347
317 void BidirectionalStreamSpdyImpl::ResetStream() { 348 void BidirectionalStreamSpdyImpl::ResetStream() {
318 if (!stream_) 349 if (!stream_)
319 return; 350 return;
320 if (!stream_->IsClosed()) { 351 if (!stream_->IsClosed()) {
321 // This sends a RST to the remote. 352 // This sends a RST to the remote.
322 stream_->DetachDelegate(); 353 stream_->DetachDelegate();
323 DCHECK(!stream_); 354 DCHECK(!stream_);
324 } else { 355 } else {
325 // Stream is already closed, so it is not legal to call DetachDelegate. 356 // Stream is already closed, so it is not legal to call DetachDelegate.
326 stream_.reset(); 357 stream_.reset();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 } 397 }
367 398
368 bool BidirectionalStreamSpdyImpl::ShouldWaitForMoreBufferedData() const { 399 bool BidirectionalStreamSpdyImpl::ShouldWaitForMoreBufferedData() const {
369 if (stream_closed_) 400 if (stream_closed_)
370 return false; 401 return false;
371 DCHECK_GT(read_buffer_len_, 0); 402 DCHECK_GT(read_buffer_len_, 0);
372 return read_data_queue_.GetTotalSize() < 403 return read_data_queue_.GetTotalSize() <
373 static_cast<size_t>(read_buffer_len_); 404 static_cast<size_t>(read_buffer_len_);
374 } 405 }
375 406
407 bool BidirectionalStreamSpdyImpl::MaybeHandleStreamClosedInSendData() {
408 if (stream_)
409 return false;
410 // If |stream_| is closed without an error before client half closes,
411 // blackhole any pending write data. crbug.com/650438.
412 if (stream_closed_ && closed_stream_status_ == OK) {
413 base::ThreadTaskRunnerHandle::Get()->PostTask(
414 FROM_HERE, base::Bind(&BidirectionalStreamSpdyImpl::NotifyDataSent,
415 weak_factory_.GetWeakPtr()));
416 return true;
417 }
418 LOG(ERROR) << "Trying to send data after stream has been destroyed.";
419 base::ThreadTaskRunnerHandle::Get()->PostTask(
420 FROM_HERE, base::Bind(&BidirectionalStreamSpdyImpl::NotifyError,
421 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED));
422 return true;
423 }
424
376 } // namespace net 425 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698