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

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

Issue 10689034: SPDY - chunked upload - speech recognition doesn't work with SPDY/3 (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 5 months 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 | Annotate | Revision Log
OLDNEW
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_http_stream.h" 5 #include "net/spdy/spdy_http_stream.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <list> 8 #include <list>
9 #include <string> 9 #include <string>
10 10
(...skipping 18 matching lines...) Expand all
29 bool direct) 29 bool direct)
30 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 30 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
31 stream_(NULL), 31 stream_(NULL),
32 spdy_session_(spdy_session), 32 spdy_session_(spdy_session),
33 response_info_(NULL), 33 response_info_(NULL),
34 download_finished_(false), 34 download_finished_(false),
35 response_headers_received_(false), 35 response_headers_received_(false),
36 user_buffer_len_(0), 36 user_buffer_len_(0),
37 buffered_read_callback_pending_(false), 37 buffered_read_callback_pending_(false),
38 more_read_data_pending_(false), 38 more_read_data_pending_(false),
39 direct_(direct) { } 39 direct_(direct),
40 waiting_for_chunk_(false) { }
40 41
41 void SpdyHttpStream::InitializeWithExistingStream(SpdyStream* spdy_stream) { 42 void SpdyHttpStream::InitializeWithExistingStream(SpdyStream* spdy_stream) {
42 stream_ = spdy_stream; 43 stream_ = spdy_stream;
43 stream_->SetDelegate(this); 44 stream_->SetDelegate(this);
44 response_headers_received_ = true; 45 response_headers_received_ = true;
45 } 46 }
46 47
47 SpdyHttpStream::~SpdyHttpStream() { 48 SpdyHttpStream::~SpdyHttpStream() {
49 if (request_body_stream_ != NULL)
50 request_body_stream_->set_chunk_callback(NULL);
48 if (stream_) 51 if (stream_)
49 stream_->DetachDelegate(); 52 stream_->DetachDelegate();
50 } 53 }
51 54
52 int SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info, 55 int SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info,
53 const BoundNetLog& stream_net_log, 56 const BoundNetLog& stream_net_log,
54 const CompletionCallback& callback) { 57 const CompletionCallback& callback) {
55 DCHECK(!stream_.get()); 58 DCHECK(!stream_.get());
56 if (spdy_session_->IsClosed()) 59 if (spdy_session_->IsClosed())
57 return ERR_CONNECTION_CLOSED; 60 return ERR_CONNECTION_CLOSED;
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 178
176 void SpdyHttpStream::SetConnectionReused() { 179 void SpdyHttpStream::SetConnectionReused() {
177 // SPDY doesn't need an indicator here. 180 // SPDY doesn't need an indicator here.
178 } 181 }
179 182
180 bool SpdyHttpStream::IsConnectionReusable() const { 183 bool SpdyHttpStream::IsConnectionReusable() const {
181 // SPDY streams aren't considered reusable. 184 // SPDY streams aren't considered reusable.
182 return false; 185 return false;
183 } 186 }
184 187
185 void SpdyHttpStream::set_chunk_callback(ChunkCallback* callback) {
186 if (request_body_stream_ != NULL)
187 request_body_stream_->set_chunk_callback(callback);
188 }
189
190 int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, 188 int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
191 scoped_ptr<UploadDataStream> request_body, 189 scoped_ptr<UploadDataStream> request_body,
192 HttpResponseInfo* response, 190 HttpResponseInfo* response,
193 const CompletionCallback& callback) { 191 const CompletionCallback& callback) {
194 base::Time request_time = base::Time::Now(); 192 base::Time request_time = base::Time::Now();
195 CHECK(stream_.get()); 193 CHECK(stream_.get());
196 194
197 stream_->SetDelegate(this); 195 stream_->SetDelegate(this);
198 196
199 linked_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); 197 linked_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
200 CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, 198 CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers,
201 headers.get(), stream_->GetProtocolVersion(), 199 headers.get(), stream_->GetProtocolVersion(),
202 direct_); 200 direct_);
203 stream_->set_spdy_headers(headers); 201 stream_->set_spdy_headers(headers);
204 202
205 stream_->SetRequestTime(request_time); 203 stream_->SetRequestTime(request_time);
206 // This should only get called in the case of a request occurring 204 // This should only get called in the case of a request occurring
207 // during server push that has already begun but hasn't finished, 205 // during server push that has already begun but hasn't finished,
208 // so we set the response's request time to be the actual one 206 // so we set the response's request time to be the actual one
209 if (response_info_) 207 if (response_info_)
210 response_info_->request_time = request_time; 208 response_info_->request_time = request_time;
211 209
212 CHECK(!request_body_stream_.get()); 210 CHECK(!request_body_stream_.get());
213 if (request_body != NULL) { 211 if (request_body != NULL) {
214 if (request_body->size() || request_body->is_chunked()) { 212 if (request_body->size() || request_body->is_chunked()) {
215 request_body_stream_.reset(request_body.release()); 213 request_body_stream_.reset(request_body.release());
214 request_body_stream_->set_chunk_callback(this);
216 // Use kMaxSpdyFrameChunkSize as the buffer size, since the request 215 // Use kMaxSpdyFrameChunkSize as the buffer size, since the request
217 // body data is written with this size at a time. 216 // body data is written with this size at a time.
218 raw_request_body_buf_ = new IOBufferWithSize(kMaxSpdyFrameChunkSize); 217 raw_request_body_buf_ = new IOBufferWithSize(kMaxSpdyFrameChunkSize);
219 // The request body buffer is empty at first. 218 // The request body buffer is empty at first.
220 request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_, 0); 219 request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_, 0);
221 } 220 }
222 } 221 }
223 222
224 CHECK(!callback.is_null()); 223 CHECK(!callback.is_null());
225 CHECK(!stream_->cancelled()); 224 CHECK(!stream_->cancelled());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 } 263 }
265 264
266 void SpdyHttpStream::Cancel() { 265 void SpdyHttpStream::Cancel() {
267 if (spdy_session_) 266 if (spdy_session_)
268 spdy_session_->CancelPendingCreateStreams(&stream_); 267 spdy_session_->CancelPendingCreateStreams(&stream_);
269 callback_.Reset(); 268 callback_.Reset();
270 if (stream_) 269 if (stream_)
271 stream_->Cancel(); 270 stream_->Cancel();
272 } 271 }
273 272
273 int SpdyHttpStream::SendData() {
274 CHECK(request_body_stream_.get());
275 CHECK_EQ(0, request_body_buf_->BytesRemaining());
276
277 // Read the data from the request body stream.
278 const int bytes_read = request_body_stream_->Read(
279 raw_request_body_buf_, raw_request_body_buf_->size());
280
281 if (request_body_stream_->is_chunked() && bytes_read == ERR_IO_PENDING) {
282 waiting_for_chunk_ = true;
Ryan Sleevi 2012/07/04 00:52:49 Note that this does mean you can get in a weird st
ramant (doing other things) 2012/07/04 21:04:33 Done.
283 return ERR_IO_PENDING;
284 }
285
286 // ERR_IO_PENDING with chunked encoding is the only possible error.
287 DCHECK_GE(bytes_read, 0);
288
289 request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_,
290 bytes_read);
291
292 DCHECK_GE(request_body_buf_->BytesRemaining(), 0);
Ryan Sleevi 2012/07/04 00:52:49 This check is probably overkill, imo. It's not tes
ramant (doing other things) 2012/07/04 21:04:33 Done.
293 const bool eof = request_body_stream_->IsEOF();
294 return stream_->WriteStreamData(
295 request_body_buf_,
296 request_body_buf_->BytesRemaining(),
297 eof ? DATA_FLAG_FIN : DATA_FLAG_NONE);
298 }
299
274 bool SpdyHttpStream::OnSendHeadersComplete(int status) { 300 bool SpdyHttpStream::OnSendHeadersComplete(int status) {
275 if (!callback_.is_null()) 301 if (!callback_.is_null())
276 DoCallback(status); 302 DoCallback(status);
277 return request_body_stream_.get() == NULL; 303 return request_body_stream_.get() == NULL;
278 } 304 }
279 305
280 int SpdyHttpStream::OnSendBody() { 306 int SpdyHttpStream::OnSendBody() {
281 CHECK(request_body_stream_.get()); 307 CHECK(request_body_stream_.get());
308 const bool eof = request_body_stream_->IsEOF();
309 if (request_body_buf_->BytesRemaining() > 0) {
310 return stream_->WriteStreamData(
311 request_body_buf_,
312 request_body_buf_->BytesRemaining(),
313 eof ? DATA_FLAG_FIN : DATA_FLAG_NONE);
314 }
282 315
283 // TODO(satorux): Clean up the logic here. This behavior is weird. Reading 316 // The entire body data has been sent.
284 // of upload data should happen in OnSendBody(). crbug.com/113107. 317 if (eof)
285 //
286 // Nothing to send. This happens when OnSendBody() is first called.
287 // A read of the upload data stream is initiated in OnSendBodyComplete().
288 if (request_body_buf_->BytesRemaining() == 0)
289 return OK; 318 return OK;
290 319
291 const bool eof = request_body_stream_->IsEOF(); 320 return SendData();
292 return stream_->WriteStreamData(
293 request_body_buf_,
294 request_body_buf_->BytesRemaining(),
295 eof ? DATA_FLAG_FIN : DATA_FLAG_NONE);
296 } 321 }
297 322
298 int SpdyHttpStream::OnSendBodyComplete(int status, bool* eof) { 323 int SpdyHttpStream::OnSendBodyComplete(int status, bool* eof) {
299 // |status| is the number of bytes written to the SPDY stream. 324 // |status| is the number of bytes written to the SPDY stream.
300 CHECK(request_body_stream_.get()); 325 CHECK(request_body_stream_.get());
301 *eof = false; 326 *eof = false;
302 327
303 if (status > 0) { 328 if (status > 0) {
304 request_body_buf_->DidConsume(status); 329 request_body_buf_->DidConsume(status);
305 if (request_body_buf_->BytesRemaining()) { 330 if (request_body_buf_->BytesRemaining()) {
306 // Go back to OnSendBody() to send the remaining data. 331 // Go back to OnSendBody() to send the remaining data.
307 return OK; 332 return OK;
308 } 333 }
309 } 334 }
310 335
311 // Check if the entire body data has been sent. 336 // Check if the entire body data has been sent.
312 *eof = (request_body_stream_->IsEOF() && 337 *eof = (request_body_stream_->IsEOF() &&
313 !request_body_buf_->BytesRemaining()); 338 !request_body_buf_->BytesRemaining());
314 if (*eof)
315 return OK;
316
317 // Read the data from the request body stream.
318 const int bytes_read = request_body_stream_->Read(
319 raw_request_body_buf_, raw_request_body_buf_->size());
320 if (request_body_stream_->is_chunked() && bytes_read == ERR_IO_PENDING)
321 return ERR_IO_PENDING;
322 // ERR_IO_PENDING with chunked encoding is the only possible error.
323 DCHECK_GE(bytes_read, 0);
324
325 request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_,
326 bytes_read);
327 return OK; 339 return OK;
328 } 340 }
329 341
330 int SpdyHttpStream::OnResponseReceived(const SpdyHeaderBlock& response, 342 int SpdyHttpStream::OnResponseReceived(const SpdyHeaderBlock& response,
331 base::Time response_time, 343 base::Time response_time,
332 int status) { 344 int status) {
333 if (!response_info_) { 345 if (!response_info_) {
334 DCHECK(stream_->pushed()); 346 DCHECK(stream_->pushed());
335 push_response_info_.reset(new HttpResponseInfo); 347 push_response_info_.reset(new HttpResponseInfo);
336 response_info_ = push_response_info_.get(); 348 response_info_ = push_response_info_.get();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 } 411 }
400 412
401 void SpdyHttpStream::OnDataSent(int length) { 413 void SpdyHttpStream::OnDataSent(int length) {
402 // For HTTP streams, no data is sent from the client while in the OPEN state, 414 // For HTTP streams, no data is sent from the client while in the OPEN state,
403 // so it is never called. 415 // so it is never called.
404 NOTREACHED(); 416 NOTREACHED();
405 } 417 }
406 418
407 void SpdyHttpStream::OnClose(int status) { 419 void SpdyHttpStream::OnClose(int status) {
408 bool invoked_callback = false; 420 bool invoked_callback = false;
421 if (request_body_stream_ != NULL)
422 request_body_stream_->set_chunk_callback(NULL);
409 if (status == net::OK) { 423 if (status == net::OK) {
410 // We need to complete any pending buffered read now. 424 // We need to complete any pending buffered read now.
411 invoked_callback = DoBufferedReadCallback(); 425 invoked_callback = DoBufferedReadCallback();
412 } 426 }
413 if (!invoked_callback && !callback_.is_null()) 427 if (!invoked_callback && !callback_.is_null())
414 DoCallback(status); 428 DoCallback(status);
415 } 429 }
416 430
431 void SpdyHttpStream::OnChunkAvailable() {
432 if (waiting_for_chunk_) {
Ryan Sleevi 2012/07/04 00:52:49 nit: You can handle this as a short circuit, to re
ramant (doing other things) 2012/07/04 21:04:33 Done.
433 DCHECK(request_body_stream_->is_chunked());
434 waiting_for_chunk_ = false;
435 SendData();
436 }
437 }
438
417 void SpdyHttpStream::ScheduleBufferedReadCallback() { 439 void SpdyHttpStream::ScheduleBufferedReadCallback() {
418 // If there is already a scheduled DoBufferedReadCallback, don't issue 440 // If there is already a scheduled DoBufferedReadCallback, don't issue
419 // another one. Mark that we have received more data and return. 441 // another one. Mark that we have received more data and return.
420 if (buffered_read_callback_pending_) { 442 if (buffered_read_callback_pending_) {
421 more_read_data_pending_ = true; 443 more_read_data_pending_ = true;
422 return; 444 return;
423 } 445 }
424 446
425 more_read_data_pending_ = false; 447 more_read_data_pending_ = false;
426 buffered_read_callback_pending_ = true; 448 buffered_read_callback_pending_ = true;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 bool SpdyHttpStream::IsSpdyHttpStream() const { 526 bool SpdyHttpStream::IsSpdyHttpStream() const {
505 return true; 527 return true;
506 } 528 }
507 529
508 void SpdyHttpStream::Drain(HttpNetworkSession* session) { 530 void SpdyHttpStream::Drain(HttpNetworkSession* session) {
509 Close(false); 531 Close(false);
510 delete this; 532 delete this;
511 } 533 }
512 534
513 } // namespace net 535 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698