1 // Copyright 2023 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 // General-purpose abstractions for a write stream.
6
7 #ifndef QUICHE_COMMON_QUICHE_STREAM_H_
8 #define QUICHE_COMMON_QUICHE_STREAM_H_
9
10 #include "absl/status/status.h"
11 #include "absl/strings/string_view.h"
12 #include "absl/types/span.h"
13 #include "quiche/common/platform/api/quiche_export.h"
14
15 namespace quiche {
16
17 // A shared base class for read and write stream to support abrupt termination.
18 class QUICHE_EXPORT TerminableStream {
19 public:
20 virtual ~TerminableStream() = default;
21
22 // Abruptly terminate the stream due to an error. If `error` is not OK, it may
23 // carry the error information that could be potentially communicated to the
24 // peer in case the stream is remote. If the stream is a duplex stream, both
25 // ends of the stream are terminated.
26 virtual void AbruptlyTerminate(absl::Status error) = 0;
27 };
28
29 // A general-purpose visitor API that gets notifications for WriteStream-related
30 // events.
31 class QUICHE_EXPORT WriteStreamVisitor {
32 public:
~WriteStreamVisitor()33 virtual ~WriteStreamVisitor() {}
34
35 // Called whenever the stream is not write-blocked and can accept new data.
36 virtual void OnCanWrite() = 0;
37 };
38
39 // Options for writing data into a WriteStream.
40 class QUICHE_EXPORT StreamWriteOptions {
41 public:
42 StreamWriteOptions() = default;
43
44 // If send_fin() is sent to true, the write operation also sends a FIN on the
45 // stream.
send_fin()46 bool send_fin() const { return send_fin_; }
set_send_fin(bool send_fin)47 void set_send_fin(bool send_fin) { send_fin_ = send_fin; }
48
49 private:
50 bool send_fin_ = false;
51 };
52
53 inline constexpr StreamWriteOptions kDefaultStreamWriteOptions =
54 StreamWriteOptions();
55
56 // WriteStream is an object that can accept a stream of bytes.
57 //
58 // The writes into a WriteStream are all-or-nothing. A WriteStream object has
59 // to either accept all data written into it by returning absl::OkStatus, or ask
60 // the caller to try again once via OnCanWrite() by returning
61 // absl::UnavailableError.
62 class QUICHE_EXPORT WriteStream : public TerminableStream {
63 public:
~WriteStream()64 virtual ~WriteStream() {}
65
66 // Writes |data| into the stream.
67 virtual absl::Status Writev(absl::Span<const absl::string_view> data,
68 const StreamWriteOptions& options) = 0;
69
70 // Indicates whether it is possible to write into stream right now.
71 virtual bool CanWrite() const = 0;
72
73 // Legacy convenience method for writing a single string_view. New users
74 // should use quiche::WriteIntoStream instead, since this method does not
75 // return useful failure information.
SendFin()76 [[nodiscard]] bool SendFin() {
77 StreamWriteOptions options;
78 options.set_send_fin(true);
79 return Writev(absl::Span<const absl::string_view>(), options).ok();
80 }
81
82 // Legacy convenience method for writing a single string_view. New users
83 // should use quiche::WriteIntoStream instead, since this method does not
84 // return useful failure information.
Write(absl::string_view data)85 [[nodiscard]] bool Write(absl::string_view data) {
86 return Writev(absl::MakeSpan(&data, 1), kDefaultStreamWriteOptions).ok();
87 }
88 };
89
90 // Convenience methods to write a single chunk of data into the stream.
91 inline absl::Status WriteIntoStream(
92 WriteStream& stream, absl::string_view data,
93 const StreamWriteOptions& options = kDefaultStreamWriteOptions) {
94 return stream.Writev(absl::MakeSpan(&data, 1), options);
95 }
96
97 // Convenience methods to send a FIN on the stream.
SendFinOnStream(WriteStream & stream)98 inline absl::Status SendFinOnStream(WriteStream& stream) {
99 StreamWriteOptions options;
100 options.set_send_fin(true);
101 return stream.Writev(absl::Span<const absl::string_view>(), options);
102 }
103
104 } // namespace quiche
105
106 #endif // QUICHE_COMMON_QUICHE_STREAM_H_
107