blob: 0fb988aed3784dbc720131aee1db22dac82c21af [file] [log] [blame]
vasilvv312e3a52019-10-18 15:06:14 -07001// Copyright (c) 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
6
7#include <sys/types.h>
8
vasilvv4e6ab332020-01-07 07:54:07 -08009#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
10#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
vasilvv312e3a52019-10-18 15:06:14 -070011#include "net/third_party/quiche/src/quic/core/quic_types.h"
12#include "net/third_party/quiche/src/quic/core/quic_utils.h"
dmcardle1ec11192019-12-12 10:36:42 -080013#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
vasilvv312e3a52019-10-18 15:06:14 -070014
15namespace quic {
16
17QuicTransportStream::QuicTransportStream(
18 QuicStreamId id,
19 QuicSession* session,
20 QuicTransportSessionInterface* session_interface)
21 : QuicStream(id,
22 session,
23 /*is_static=*/false,
24 QuicUtils::GetStreamType(id,
25 session->connection()->perspective(),
renjietangd262e252020-06-19 15:11:24 -070026 session->IsIncomingStream(id),
27 session->version())),
vasilvv312e3a52019-10-18 15:06:14 -070028 session_interface_(session_interface) {}
29
30size_t QuicTransportStream::Read(char* buffer, size_t buffer_size) {
31 if (!session_interface_->IsSessionReady()) {
32 return 0;
33 }
34
35 iovec iov;
36 iov.iov_base = buffer;
37 iov.iov_len = buffer_size;
vasilvvd88f1622019-11-04 13:50:53 -080038 const size_t result = sequencer()->Readv(&iov, 1);
vasilvvcf918142020-03-30 11:45:27 -070039 if (sequencer()->IsClosed()) {
40 MaybeNotifyFinRead();
vasilvvd88f1622019-11-04 13:50:53 -080041 }
42 return result;
43}
44
45size_t QuicTransportStream::Read(std::string* output) {
46 const size_t old_size = output->size();
47 const size_t bytes_to_read = ReadableBytes();
48 output->resize(old_size + bytes_to_read);
49 size_t bytes_read = Read(&(*output)[old_size], bytes_to_read);
50 DCHECK_EQ(bytes_to_read, bytes_read);
51 output->resize(old_size + bytes_read);
52 return bytes_read;
vasilvv312e3a52019-10-18 15:06:14 -070053}
54
dmcardle1ec11192019-12-12 10:36:42 -080055bool QuicTransportStream::Write(quiche::QuicheStringPiece data) {
vasilvv312e3a52019-10-18 15:06:14 -070056 if (!CanWrite()) {
57 return false;
58 }
59
vasilvv4e6ab332020-01-07 07:54:07 -080060 QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
61 session()->connection()->helper()->GetStreamSendBufferAllocator(),
62 data.size());
63 memcpy(buffer.get(), data.data(), data.size());
64 QuicMemSlice memslice(std::move(buffer), data.size());
65 QuicConsumedData consumed =
66 WriteMemSlices(QuicMemSliceSpan(&memslice), /*fin=*/false);
67
68 if (consumed.bytes_consumed == data.size()) {
69 return true;
70 }
71 if (consumed.bytes_consumed == 0) {
72 return false;
73 }
74 // QuicTransportStream::Write() is an all-or-nothing write API. To achieve
75 // that property, it relies on WriteMemSlices() being an all-or-nothing API.
76 // If WriteMemSlices() fails to provide that guarantee, we have no way to
77 // communicate a partial write to the caller, and thus it's safer to just
78 // close the connection.
79 QUIC_BUG << "WriteMemSlices() unexpectedly partially consumed the input "
80 "data, provided: "
81 << data.size() << ", written: " << consumed.bytes_consumed;
renjietang87df0d02020-02-13 11:53:52 -080082 OnUnrecoverableError(
vasilvv4e6ab332020-01-07 07:54:07 -080083 QUIC_INTERNAL_ERROR,
84 "WriteMemSlices() unexpectedly partially consumed the input data");
85 return false;
vasilvv312e3a52019-10-18 15:06:14 -070086}
87
88bool QuicTransportStream::SendFin() {
89 if (!CanWrite()) {
90 return false;
91 }
92
vasilvv4e6ab332020-01-07 07:54:07 -080093 QuicMemSlice empty;
94 QuicConsumedData consumed =
95 WriteMemSlices(QuicMemSliceSpan(&empty), /*fin=*/true);
96 DCHECK_EQ(consumed.bytes_consumed, 0u);
97 return consumed.fin_consumed;
vasilvv312e3a52019-10-18 15:06:14 -070098}
99
100bool QuicTransportStream::CanWrite() const {
vasilvv54deda72020-01-07 11:19:36 -0800101 return session_interface_->IsSessionReady() && CanWriteNewData() &&
102 !write_side_closed();
vasilvv312e3a52019-10-18 15:06:14 -0700103}
104
105size_t QuicTransportStream::ReadableBytes() const {
106 if (!session_interface_->IsSessionReady()) {
107 return 0;
108 }
109
110 return sequencer()->ReadableBytes();
111}
112
113void QuicTransportStream::OnDataAvailable() {
vasilvvd88f1622019-11-04 13:50:53 -0800114 if (sequencer()->IsClosed()) {
vasilvvcf918142020-03-30 11:45:27 -0700115 MaybeNotifyFinRead();
vasilvvd88f1622019-11-04 13:50:53 -0800116 return;
117 }
118
119 if (visitor_ == nullptr) {
120 return;
121 }
vasilvv312e3a52019-10-18 15:06:14 -0700122 if (ReadableBytes() == 0) {
123 return;
124 }
vasilvvd88f1622019-11-04 13:50:53 -0800125 visitor_->OnCanRead();
vasilvv312e3a52019-10-18 15:06:14 -0700126}
127
128void QuicTransportStream::OnCanWriteNewData() {
129 // Ensure the origin check has been completed, as the stream can be notified
130 // about being writable before that.
131 if (!CanWrite()) {
132 return;
133 }
134 if (visitor_ != nullptr) {
135 visitor_->OnCanWrite();
136 }
137}
138
vasilvvcf918142020-03-30 11:45:27 -0700139void QuicTransportStream::MaybeNotifyFinRead() {
140 if (visitor_ == nullptr || fin_read_notified_) {
141 return;
142 }
143 fin_read_notified_ = true;
144 visitor_->OnFinRead();
145 OnFinRead();
146}
147
vasilvv312e3a52019-10-18 15:06:14 -0700148} // namespace quic