File: outgoing_stream.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (188 lines) | stat: -rw-r--r-- 6,501 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBTRANSPORT_OUTGOING_STREAM_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBTRANSPORT_OUTGOING_STREAM_H_

#include <cstddef>
#include <cstdint>

#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#include "base/types/strong_alias.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/abort_signal.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/prefinalizer.h"
#include "v8/include/v8.h"

namespace blink {

class ExceptionState;
class ScriptState;
class WritableStream;
class WritableStreamDefaultController;

// Implementation of the OutgoingStream mixin from the standard. SendStream and
// BidirectionalStream delegate to this.
class MODULES_EXPORT OutgoingStream final
    : public GarbageCollected<OutgoingStream> {
  USING_PRE_FINALIZER(OutgoingStream, Dispose);

 public:
  // An interface for SendStream and BidirectionalStream to implement when using
  // this class. At most one of these methods will be called.
  class Client : public GarbageCollectedMixin {
   public:
    virtual ~Client() = default;

    // Request that a Fin message for this stream be sent to the server.
    virtual void SendFin() = 0;

    // Notify that the stream is either closed or errored and WebTransport
    // should drop its reference to the stream.
    virtual void ForgetStream() = 0;

    // Send RESET_STREAM with `code`. This does not imply ForgetStream().
    virtual void Reset(uint8_t code) = 0;
  };

  enum class State {
    kOpen,
    kSentFin,
    kAborted,
  };

  OutgoingStream(ScriptState*, Client*, mojo::ScopedDataPipeProducerHandle);
  ~OutgoingStream();

  // Init() or InitWithExistingWritableStream() must be called before the stream
  // is used.
  void Init(ExceptionState&);

  void InitWithExistingWritableStream(WritableStream*, ExceptionState&);

  void AbortAlgorithm(OutgoingStream*);

  // Implementation of OutgoingStream IDL, used by client classes to implement
  // it. https://wicg.github.io/web-transport/#outgoing-stream
  WritableStream* Writable() const {
    DVLOG(1) << "OutgoingStream::writable() called";

    return writable_.Get();
  }

  ScriptState* GetScriptState() { return script_state_.Get(); }

  // Called from WebTransport via a WebTransportStream.
  void OnOutgoingStreamClosed();

  // Errors the associated stream with the given reason. Expects a JavaScript
  // scope to be entered.
  void Error(ScriptValue reason);

  State GetState() const { return state_; }

  // Called from WebTransport rather than using
  // ExecutionContextLifecycleObserver to ensure correct destruction order.
  // Does not execute JavaScript.
  void ContextDestroyed();

  void Trace(Visitor*) const;

 private:
  class UnderlyingSink;

  using IsLocalAbort = base::StrongAlias<class IsLocalAbortTag, bool>;

  // Called when |data_pipe_| becomes writable or errored.
  void OnHandleReady(MojoResult, const mojo::HandleSignalsState&);

  // Called when |data_pipe_| is closed.
  void OnPeerClosed(MojoResult, const mojo::HandleSignalsState&);

  // Rejects any unfinished write() calls and resets |data_pipe_|.
  void HandlePipeClosed();

  // Implements UnderlyingSink::write().
  ScriptPromise<IDLUndefined> SinkWrite(ScriptState*,
                                        ScriptValue chunk,
                                        ExceptionState&);

  // Writes |data| to |data_pipe_|, possible saving unwritten data to
  // |cached_data_|.
  ScriptPromise<IDLUndefined> WriteOrCacheData(ScriptState*,
                                               base::span<const uint8_t> data);

  // Attempts to write some more of |cached_data_| to |data_pipe_|.
  void WriteCachedData();

  // Writes zero or more bytes of |data| synchronously to |data_pipe_|,
  // returning the number of bytes that were written.
  size_t WriteDataSynchronously(base::span<const uint8_t> data);

  // Creates a DOMException indicating that the stream has been aborted.
  // If IsLocalAbort it true it will indicate a locally-initiated abort,
  // otherwise it will indicate a remote-initiated abort.
  ScriptValue CreateAbortException(IsLocalAbort);

  // Errors |writable_|, and resets |data_pipe_|.
  void ErrorStreamAbortAndReset(ScriptValue reason);

  // Reset the |data_pipe_|.
  void AbortAndReset();

  // Resets |data_pipe_| and clears the watchers. Also discards |cached_data_|.
  // If the pipe is open it will be closed as a side-effect.
  void ResetPipe();

  // Prepares the object for destruction.
  void Dispose();

  const Member<ScriptState> script_state_;
  Member<Client> client_;
  mojo::ScopedDataPipeProducerHandle data_pipe_;

  // Only armed when we need to write something.
  mojo::SimpleWatcher write_watcher_;

  // Always armed to detect close.
  mojo::SimpleWatcher close_watcher_;

  // Data which has been passed to write() but still needs to be written
  // asynchronously.
  // Uses a custom CachedDataBuffer rather than a Vector because
  // WTF::Vector is currently limited to 2GB.
  // TODO(ricea): Change this to a Vector when it becomes 64-bit safe.
  class CachedDataBuffer;
  std::unique_ptr<CachedDataBuffer> cached_data_;

  // The offset into |cached_data_| of the first byte that still needs to be
  // written.
  size_t offset_ = 0;

  Member<WritableStream> writable_;
  Member<AbortSignal::AlgorithmHandle> send_stream_abort_handle_;
  Member<WritableStreamDefaultController> controller_;

  // If an asynchronous write() on the underlying sink object is pending, this
  // will be non-null.
  Member<ScriptPromiseResolver<IDLUndefined>> write_promise_resolver_;

  // If a close() on the underlying sink object is pending, this will be
  // non-null.
  Member<ScriptPromiseResolver<IDLUndefined>> close_promise_resolver_;

  Member<ScriptPromiseResolver<IDLUndefined>> pending_operation_;

  State state_ = State::kOpen;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBTRANSPORT_OUTGOING_STREAM_H_