summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc')
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc63
1 files changed, 49 insertions, 14 deletions
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc
index 61f4345d61b..401ae7e4278 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc
@@ -6,9 +6,11 @@
#include <sys/types.h>
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -33,8 +35,8 @@ size_t QuicTransportStream::Read(char* buffer, size_t buffer_size) {
iov.iov_base = buffer;
iov.iov_len = buffer_size;
const size_t result = sequencer()->Readv(&iov, 1);
- if (sequencer()->IsClosed() && visitor_ != nullptr) {
- visitor_->OnFinRead();
+ if (sequencer()->IsClosed()) {
+ MaybeNotifyFinRead();
}
return result;
}
@@ -49,14 +51,37 @@ size_t QuicTransportStream::Read(std::string* output) {
return bytes_read;
}
-bool QuicTransportStream::Write(QuicStringPiece data) {
+bool QuicTransportStream::Write(quiche::QuicheStringPiece data) {
if (!CanWrite()) {
return false;
}
- // TODO(vasilvv): use WriteMemSlices()
- WriteOrBufferData(data, /*fin=*/false, nullptr);
- return true;
+ QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
+ session()->connection()->helper()->GetStreamSendBufferAllocator(),
+ data.size());
+ memcpy(buffer.get(), data.data(), data.size());
+ QuicMemSlice memslice(std::move(buffer), data.size());
+ QuicConsumedData consumed =
+ WriteMemSlices(QuicMemSliceSpan(&memslice), /*fin=*/false);
+
+ if (consumed.bytes_consumed == data.size()) {
+ return true;
+ }
+ if (consumed.bytes_consumed == 0) {
+ return false;
+ }
+ // QuicTransportStream::Write() is an all-or-nothing write API. To achieve
+ // that property, it relies on WriteMemSlices() being an all-or-nothing API.
+ // If WriteMemSlices() fails to provide that guarantee, we have no way to
+ // communicate a partial write to the caller, and thus it's safer to just
+ // close the connection.
+ QUIC_BUG << "WriteMemSlices() unexpectedly partially consumed the input "
+ "data, provided: "
+ << data.size() << ", written: " << consumed.bytes_consumed;
+ OnUnrecoverableError(
+ QUIC_INTERNAL_ERROR,
+ "WriteMemSlices() unexpectedly partially consumed the input data");
+ return false;
}
bool QuicTransportStream::SendFin() {
@@ -64,12 +89,16 @@ bool QuicTransportStream::SendFin() {
return false;
}
- WriteOrBufferData(QuicStringPiece(), /*fin=*/true, nullptr);
- return true;
+ QuicMemSlice empty;
+ QuicConsumedData consumed =
+ WriteMemSlices(QuicMemSliceSpan(&empty), /*fin=*/true);
+ DCHECK_EQ(consumed.bytes_consumed, 0u);
+ return consumed.fin_consumed;
}
bool QuicTransportStream::CanWrite() const {
- return session_interface_->IsSessionReady() && CanWriteNewData();
+ return session_interface_->IsSessionReady() && CanWriteNewData() &&
+ !write_side_closed();
}
size_t QuicTransportStream::ReadableBytes() const {
@@ -82,10 +111,7 @@ size_t QuicTransportStream::ReadableBytes() const {
void QuicTransportStream::OnDataAvailable() {
if (sequencer()->IsClosed()) {
- if (visitor_ != nullptr) {
- visitor_->OnFinRead();
- }
- OnFinRead();
+ MaybeNotifyFinRead();
return;
}
@@ -109,4 +135,13 @@ void QuicTransportStream::OnCanWriteNewData() {
}
}
+void QuicTransportStream::MaybeNotifyFinRead() {
+ if (visitor_ == nullptr || fin_read_notified_) {
+ return;
+ }
+ fin_read_notified_ = true;
+ visitor_->OnFinRead();
+ OnFinRead();
+}
+
} // namespace quic