| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/quic/core/quic_headers_stream.h" | 5 #include "net/quic/core/quic_headers_stream.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 } | 307 } |
| 308 | 308 |
| 309 void OnReceiveCompressedFrame(SpdyStreamId stream_id, | 309 void OnReceiveCompressedFrame(SpdyStreamId stream_id, |
| 310 SpdyFrameType type, | 310 SpdyFrameType type, |
| 311 size_t frame_len) override { | 311 size_t frame_len) override { |
| 312 if (stream_->IsConnected()) { | 312 if (stream_->IsConnected()) { |
| 313 stream_->OnCompressedFrameSize(frame_len); | 313 stream_->OnCompressedFrameSize(frame_len); |
| 314 } | 314 } |
| 315 } | 315 } |
| 316 | 316 |
| 317 void set_max_uncompressed_header_bytes( |
| 318 size_t set_max_uncompressed_header_bytes) { |
| 319 header_list_.set_max_uncompressed_header_bytes( |
| 320 set_max_uncompressed_header_bytes); |
| 321 } |
| 322 |
| 317 private: | 323 private: |
| 318 void CloseConnection(const string& details) { | 324 void CloseConnection(const string& details) { |
| 319 if (stream_->IsConnected()) { | 325 if (stream_->IsConnected()) { |
| 320 stream_->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, | 326 stream_->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, |
| 321 details); | 327 details); |
| 322 } | 328 } |
| 323 } | 329 } |
| 324 | 330 |
| 325 private: | 331 private: |
| 326 QuicHeadersStream* stream_; | 332 QuicHeadersStream* stream_; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 | 386 |
| 381 // PUSH_PROMISE must not be the last frame sent out, at least followed by | 387 // PUSH_PROMISE must not be the last frame sent out, at least followed by |
| 382 // response headers. | 388 // response headers. |
| 383 push_promise.set_fin(false); | 389 push_promise.set_fin(false); |
| 384 | 390 |
| 385 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise)); | 391 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise)); |
| 386 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr); | 392 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr); |
| 387 return frame.size(); | 393 return frame.size(); |
| 388 } | 394 } |
| 389 | 395 |
| 390 void QuicHeadersStream::WriteDataFrame( | |
| 391 QuicStreamId id, | |
| 392 StringPiece data, | |
| 393 bool fin, | |
| 394 QuicAckListenerInterface* ack_notifier_delegate) { | |
| 395 SpdyDataIR spdy_data(id, data); | |
| 396 spdy_data.set_fin(fin); | |
| 397 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); | |
| 398 scoped_refptr<ForceHolAckListener> ack_listener; | |
| 399 if (ack_notifier_delegate != nullptr) { | |
| 400 ack_listener = new ForceHolAckListener(ack_notifier_delegate, | |
| 401 frame.size() - data.length()); | |
| 402 } | |
| 403 // Use buffered writes so that coherence of framing is preserved | |
| 404 // between streams. | |
| 405 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, | |
| 406 ack_listener.get()); | |
| 407 } | |
| 408 | |
| 409 QuicConsumedData QuicHeadersStream::WritevStreamData( | 396 QuicConsumedData QuicHeadersStream::WritevStreamData( |
| 410 QuicStreamId id, | 397 QuicStreamId id, |
| 411 QuicIOVector iov, | 398 QuicIOVector iov, |
| 412 QuicStreamOffset offset, | 399 QuicStreamOffset offset, |
| 413 bool fin, | 400 bool fin, |
| 414 QuicAckListenerInterface* ack_notifier_delegate) { | 401 QuicAckListenerInterface* ack_notifier_delegate) { |
| 415 const size_t max_len = kSpdyInitialFrameSizeLimit - | 402 const size_t max_len = kSpdyInitialFrameSizeLimit - |
| 416 SpdyConstants::GetDataFrameMinimumSize(HTTP2); | 403 SpdyConstants::GetDataFrameMinimumSize(HTTP2); |
| 417 | 404 |
| 418 QuicConsumedData result(0, false); | 405 QuicConsumedData result(0, false); |
| 419 size_t total_length = iov.total_length; | 406 size_t total_length = iov.total_length; |
| 420 | 407 |
| 421 if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) { | 408 // Encapsulate the data into HTTP/2 DATA frames. The outer loop |
| 422 // Encapsulate the data into HTTP/2 DATA frames. The outer loop | 409 // handles each element of the source iov, the inner loop handles |
| 423 // handles each element of the source iov, the inner loop handles | 410 // the possibility of fragmenting eacho of those into multiple DATA |
| 424 // the possibility of fragmenting eacho of those into multiple DATA | 411 // frames, as the DATA frames have a max size of 16KB. |
| 425 // frames, as the DATA frames have a max size of 16KB. | 412 for (int i = 0; i < iov.iov_count; i++) { |
| 426 for (int i = 0; i < iov.iov_count; i++) { | 413 size_t offset = 0; |
| 427 size_t offset = 0; | 414 const struct iovec* src_iov = &iov.iov[i]; |
| 428 const struct iovec* src_iov = &iov.iov[i]; | 415 do { |
| 429 do { | 416 size_t len = |
| 430 size_t len = std::min(std::min(src_iov->iov_len - offset, max_len), | 417 std::min(std::min(src_iov->iov_len - offset, max_len), total_length); |
| 431 total_length); | 418 char* data = static_cast<char*>(src_iov->iov_base) + offset; |
| 432 char* data = static_cast<char*>(src_iov->iov_base) + offset; | 419 SpdyDataIR spdy_data(id, StringPiece(data, len)); |
| 433 SpdyDataIR spdy_data(id, StringPiece(data, len)); | 420 offset += len; |
| 434 offset += len; | 421 // fin handling, set it only it only very last generated HTTP/2 |
| 435 // fin handling, only set it for the final HTTP/2 DATA frame. | 422 // DATA frame. |
| 436 bool last_iov = i == iov.iov_count - 1; | 423 bool last_iov = i == iov.iov_count - 1; |
| 437 bool last_fragment_within_iov = offset >= src_iov->iov_len; | 424 bool last_fragment_within_iov = offset >= src_iov->iov_len; |
| 438 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; | 425 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; |
| 439 spdy_data.set_fin(frame_fin); | 426 spdy_data.set_fin(frame_fin); |
| 440 if (frame_fin) { | 427 if (frame_fin) { |
| 441 result.fin_consumed = true; | 428 result.fin_consumed = true; |
| 442 } | 429 } |
| 443 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); | 430 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); |
| 444 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " | 431 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " |
| 445 << len << " fin " << spdy_data.fin() << " remaining " | 432 << len << " fin " << spdy_data.fin() << " remaining " |
| 446 << src_iov->iov_len - offset; | 433 << src_iov->iov_len - offset; |
| 447 | 434 |
| 448 scoped_refptr<ForceHolAckListener> ack_listener; | 435 scoped_refptr<ForceHolAckListener> ack_listener; |
| 449 if (ack_notifier_delegate != nullptr) { | 436 if (ack_notifier_delegate != nullptr) { |
| 450 ack_listener = new ForceHolAckListener(ack_notifier_delegate, | 437 ack_listener = |
| 451 frame.size() - len); | 438 new ForceHolAckListener(ack_notifier_delegate, frame.size() - len); |
| 452 } | 439 } |
| 453 | 440 |
| 454 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, | 441 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, |
| 455 ack_listener.get()); | 442 ack_listener.get()); |
| 456 result.bytes_consumed += len; | 443 result.bytes_consumed += len; |
| 457 total_length -= len; | 444 total_length -= len; |
| 458 if (total_length <= 0) { | 445 if (total_length <= 0) { |
| 459 return result; | 446 return result; |
| 460 } | 447 } |
| 461 } while (offset < src_iov->iov_len); | 448 } while (offset < src_iov->iov_len); |
| 462 } | |
| 463 } else { | |
| 464 if (total_length == 0 && fin) { | |
| 465 WriteDataFrame(id, StringPiece(), true, ack_notifier_delegate); | |
| 466 result.fin_consumed = true; | |
| 467 return result; | |
| 468 } | |
| 469 | |
| 470 // Encapsulate the data into HTTP/2 DATA frames. The outer loop | |
| 471 // handles each element of the source iov, the inner loop handles | |
| 472 // the possibility of fragmenting each of those into multiple DATA | |
| 473 // frames, as the DATA frames have a max size of 16KB. | |
| 474 for (int i = 0; i < iov.iov_count; i++) { | |
| 475 size_t src_iov_offset = 0; | |
| 476 const struct iovec* src_iov = &iov.iov[i]; | |
| 477 do { | |
| 478 if (queued_data_bytes() > 0) { | |
| 479 // Limit the amount of buffering to the minimum needed to | |
| 480 // preserve framing. | |
| 481 return result; | |
| 482 } | |
| 483 size_t len = std::min( | |
| 484 std::min(src_iov->iov_len - src_iov_offset, max_len), total_length); | |
| 485 char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset; | |
| 486 src_iov_offset += len; | |
| 487 offset += len; | |
| 488 // fin handling, only set it for the final HTTP/2 DATA frame. | |
| 489 bool last_iov = i == iov.iov_count - 1; | |
| 490 bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len; | |
| 491 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; | |
| 492 WriteDataFrame(id, StringPiece(data, len), frame_fin, | |
| 493 ack_notifier_delegate); | |
| 494 result.bytes_consumed += len; | |
| 495 if (frame_fin) { | |
| 496 result.fin_consumed = true; | |
| 497 } | |
| 498 DCHECK_GE(total_length, len); | |
| 499 total_length -= len; | |
| 500 if (total_length <= 0) { | |
| 501 return result; | |
| 502 } | |
| 503 } while (src_iov_offset < src_iov->iov_len); | |
| 504 } | |
| 505 } | 449 } |
| 506 | |
| 507 return result; | 450 return result; |
| 508 } | 451 } |
| 509 | 452 |
| 510 void QuicHeadersStream::OnDataAvailable() { | 453 void QuicHeadersStream::OnDataAvailable() { |
| 511 char buffer[1024]; | 454 char buffer[1024]; |
| 512 struct iovec iov; | 455 struct iovec iov; |
| 513 QuicTime timestamp(QuicTime::Zero()); | 456 QuicTime timestamp(QuicTime::Zero()); |
| 514 while (true) { | 457 while (true) { |
| 515 iov.iov_base = buffer; | 458 iov.iov_base = buffer; |
| 516 iov.iov_len = arraysize(buffer); | 459 iov.iov_len = arraysize(buffer); |
| 517 if (!sequencer()->GetReadableRegion(&iov, ×tamp)) { | 460 if (!sequencer()->GetReadableRegion(&iov, ×tamp)) { |
| 518 // No more data to read. | 461 // No more data to read. |
| 519 break; | 462 break; |
| 520 } | 463 } |
| 521 DCHECK(timestamp.IsInitialized()); | 464 DCHECK(timestamp.IsInitialized()); |
| 522 cur_max_timestamp_ = std::max(timestamp, cur_max_timestamp_); | 465 cur_max_timestamp_ = std::max(timestamp, cur_max_timestamp_); |
| 523 if (spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base), | 466 if (spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base), |
| 524 iov.iov_len) != iov.iov_len) { | 467 iov.iov_len) != iov.iov_len) { |
| 525 // Error processing data. | 468 // Error processing data. |
| 526 return; | 469 return; |
| 527 } | 470 } |
| 528 sequencer()->MarkConsumed(iov.iov_len); | 471 sequencer()->MarkConsumed(iov.iov_len); |
| 529 } | 472 } |
| 530 } | 473 } |
| 531 | 474 |
| 475 void QuicHeadersStream::set_max_uncompressed_header_bytes( |
| 476 size_t set_max_uncompressed_header_bytes) { |
| 477 spdy_framer_visitor_->set_max_uncompressed_header_bytes( |
| 478 set_max_uncompressed_header_bytes); |
| 479 } |
| 480 |
| 532 void QuicHeadersStream::OnHeaders(SpdyStreamId stream_id, | 481 void QuicHeadersStream::OnHeaders(SpdyStreamId stream_id, |
| 533 bool has_priority, | 482 bool has_priority, |
| 534 SpdyPriority priority, | 483 SpdyPriority priority, |
| 535 bool fin) { | 484 bool fin) { |
| 536 if (has_priority) { | 485 if (has_priority) { |
| 537 if (session()->perspective() == Perspective::IS_CLIENT) { | 486 if (session()->perspective() == Perspective::IS_CLIENT) { |
| 538 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, | 487 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, |
| 539 "Server must not send priorities."); | 488 "Server must not send priorities."); |
| 540 return; | 489 return; |
| 541 } | 490 } |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 return true; | 655 return true; |
| 707 } | 656 } |
| 708 frame_len_ -= len; | 657 frame_len_ -= len; |
| 709 // Ignore fin_ while there is more data coming, if frame_len_ > 0. | 658 // Ignore fin_ while there is more data coming, if frame_len_ > 0. |
| 710 spdy_session_->OnStreamFrameData(stream_id, data, len, | 659 spdy_session_->OnStreamFrameData(stream_id, data, len, |
| 711 frame_len_ > 0 ? false : fin_); | 660 frame_len_ > 0 ? false : fin_); |
| 712 return true; | 661 return true; |
| 713 } | 662 } |
| 714 | 663 |
| 715 } // namespace net | 664 } // namespace net |
| OLD | NEW |