@fails-components/webtransport-transport-http3-quiche 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CMakeLists.txt +978 -0
  2. package/LICENSE +39 -0
  3. package/LICENSE.chromium +27 -0
  4. package/LICENSE.envoy +207 -0
  5. package/build.js +315 -0
  6. package/lib/clientsocket.js +80 -0
  7. package/lib/index.js +47 -0
  8. package/lib/serversocket.js +80 -0
  9. package/lib/socket.js +118 -0
  10. package/lib/types.ts +15 -0
  11. package/lib/utils.js +12 -0
  12. package/package.json +68 -0
  13. package/platform/icufix/fakedata.cpp +8 -0
  14. package/platform/quiche/quic/core/io/socket_win.inc +3 -0
  15. package/platform/quiche_platform_impl/quiche_bug_tracker_impl.h +7 -0
  16. package/platform/quiche_platform_impl/quiche_client_stats_impl.h +7 -0
  17. package/platform/quiche_platform_impl/quiche_command_line_flags_impl.h +7 -0
  18. package/platform/quiche_platform_impl/quiche_containers_impl.h +7 -0
  19. package/platform/quiche_platform_impl/quiche_event_loop_impl.h +7 -0
  20. package/platform/quiche_platform_impl/quiche_export_impl.h +6 -0
  21. package/platform/quiche_platform_impl/quiche_flag_utils_impl.h +11 -0
  22. package/platform/quiche_platform_impl/quiche_flags_impl.h +8 -0
  23. package/platform/quiche_platform_impl/quiche_googleurl_impl.h +8 -0
  24. package/platform/quiche_platform_impl/quiche_iovec_impl.h +10 -0
  25. package/platform/quiche_platform_impl/quiche_logging_impl.h +21 -0
  26. package/platform/quiche_platform_impl/quiche_mem_slice_impl.h +2 -0
  27. package/platform/quiche_platform_impl/quiche_mutex_impl.h +8 -0
  28. package/platform/quiche_platform_impl/quiche_prefetch_impl.h +11 -0
  29. package/platform/quiche_platform_impl/quiche_reference_counted_impl.h +16 -0
  30. package/platform/quiche_platform_impl/quiche_server_stats_impl.h +7 -0
  31. package/platform/quiche_platform_impl/quiche_stack_trace_impl.h +12 -0
  32. package/platform/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h +8 -0
  33. package/platform/quiche_platform_impl/quiche_testvalue_impl.h +1 -0
  34. package/platform/quiche_platform_impl/quiche_thread_local_impl.h +6 -0
  35. package/platform/quiche_platform_impl/quiche_time_utils_impl.h +13 -0
  36. package/platform/quiche_platform_impl/quiche_udp_socket_platform_impl.h +39 -0
  37. package/readme.md +20 -0
  38. package/src/http3backendresponse.cc +36 -0
  39. package/src/http3backendresponse.h +109 -0
  40. package/src/http3client.cc +1402 -0
  41. package/src/http3client.h +531 -0
  42. package/src/http3clientsession.cc +65 -0
  43. package/src/http3clientsession.h +58 -0
  44. package/src/http3clientstream.cc +52 -0
  45. package/src/http3clientstream.h +42 -0
  46. package/src/http3dispatcher.cc +62 -0
  47. package/src/http3dispatcher.h +57 -0
  48. package/src/http3server.cc +529 -0
  49. package/src/http3server.h +149 -0
  50. package/src/http3serverbackend.cc +104 -0
  51. package/src/http3serverbackend.h +96 -0
  52. package/src/http3serversession.cc +123 -0
  53. package/src/http3serversession.h +95 -0
  54. package/src/http3serverstream.cc +463 -0
  55. package/src/http3serverstream.h +114 -0
  56. package/src/http3sessioncache.cc +85 -0
  57. package/src/http3sessioncache.h +59 -0
  58. package/src/http3wtsessionvisitor.cc +312 -0
  59. package/src/http3wtsessionvisitor.h +257 -0
  60. package/src/http3wtstreamvisitor.cc +286 -0
  61. package/src/http3wtstreamvisitor.h +323 -0
  62. package/src/librarymain.cc +86 -0
  63. package/src/librarymain.h +42 -0
  64. package/src/napialarmfactory.cc +51 -0
  65. package/src/napialarmfactory.h +165 -0
  66. package/src/socketjswriter.cc +46 -0
  67. package/src/socketjswriter.h +100 -0
@@ -0,0 +1,59 @@
1
+ // modifications
2
+ // Copyright (c) 2022 Marten Richter or other contributers (see commit). All rights reserved.
3
+ // Use of this source code is governed by a BSD-style license that can be
4
+ // found in the LICENSE file.
5
+
6
+ // original copyright, see LICENSE.chromium
7
+ // Copyright (c) 2019 The Chromium Authors. All rights reserved.
8
+ // Use of this source code is governed by a BSD-style license that can be
9
+ // found in the LICENSE file.
10
+
11
+
12
+ #ifndef HTTP3_SESSION_CACHE_H
13
+ #define HTTP3_SESSION_CACHE_H
14
+
15
+ #include <memory>
16
+
17
+ #include "quiche/quic/core/crypto/quic_crypto_client_config.h"
18
+ #include "quiche/quic/core/crypto/transport_parameters.h"
19
+
20
+ namespace quic {
21
+
22
+ // Http3SessionCache provides a simple implementation of SessionCache that
23
+ // stores only one QuicResumptionState per QuicServerId. No limit is placed on
24
+ // the total number of entries in the cache. When Lookup is called, if a cache
25
+ // entry exists for the provided QuicServerId, the entry will be removed from
26
+ // the cached when it is returned.
27
+ // TODO(fayang): Remove Http3SessionCache by using QuicClientSessionCache.
28
+ class Http3SessionCache : public SessionCache {
29
+ public:
30
+ Http3SessionCache() = default;
31
+ ~Http3SessionCache() override = default;
32
+
33
+ void Insert(const QuicServerId& server_id,
34
+ bssl::UniquePtr<SSL_SESSION> session,
35
+ const TransportParameters& params,
36
+ const ApplicationState* application_state) override;
37
+ std::unique_ptr<QuicResumptionState> Lookup(const QuicServerId& server_id,
38
+ QuicWallTime now,
39
+ const SSL_CTX* ctx) override;
40
+ void ClearEarlyData(const QuicServerId& server_id) override;
41
+ void OnNewTokenReceived(const QuicServerId& server_id,
42
+ absl::string_view token) override;
43
+ void RemoveExpiredEntries(QuicWallTime now) override;
44
+ void Clear() override;
45
+
46
+ private:
47
+ struct Entry {
48
+ bssl::UniquePtr<SSL_SESSION> session;
49
+ std::unique_ptr<TransportParameters> params;
50
+ std::unique_ptr<ApplicationState> application_state;
51
+ std::string token;
52
+ };
53
+ std::map<QuicServerId, Entry> cache_entries_;
54
+ };
55
+
56
+
57
+ } // namespace quic
58
+
59
+ #endif // QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_CACHE_H_
@@ -0,0 +1,312 @@
1
+ // Copyright (c) 2022 Marten Richter or other contributers (see commit). 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 "src/http3wtsessionvisitor.h"
6
+
7
+ namespace quic
8
+ {
9
+
10
+ Http3WTSession::Visitor::~Visitor()
11
+ {
12
+ // printf("~Visitor %d %x %x\n", getpid(), this, session_);
13
+ Http3WTSessionJS *sessobj = session_->getJS();
14
+ if (sessobj) {
15
+ session_->getJS()->Unref();
16
+ } else
17
+ delete session_;
18
+ session_ = nullptr;
19
+ }
20
+
21
+ void Http3WTSession::Visitor::OnSessionClosed(WebTransportSessionError error_code,
22
+ const std::string &error_message)
23
+ {
24
+ // printf("OnSessionClosed %d %x %x\n", getpid(), this, session_);
25
+ session_->session_ = nullptr;
26
+ session_->getJS()->processSessionClose(error_code, error_message);
27
+ }
28
+
29
+
30
+ void Http3WTSession::Visitor::OnIncomingBidirectionalStreamAvailable()
31
+ {
32
+ if (!session_->session_)
33
+ return;
34
+ while (true)
35
+ {
36
+ WebTransportStream *stream =
37
+ session_->session_->AcceptIncomingBidirectionalStream();
38
+ if (stream == nullptr)
39
+ {
40
+ return;
41
+ }
42
+ Http3WTStream *wtstream = new Http3WTStream(stream);
43
+ QUIC_DVLOG(1)
44
+ << "Http3WTSession received a bidirectional stream "
45
+ << stream->GetStreamId();
46
+ stream->SetVisitor(
47
+ std::make_unique<Http3WTStream::Visitor>(wtstream));
48
+ session_->getJS()->processStream(true, true, static_cast<Http3WTStream *>(wtstream));
49
+ stream->visitor()->OnCanRead();
50
+ }
51
+ }
52
+
53
+ void Http3WTSession::Visitor::OnIncomingUnidirectionalStreamAvailable()
54
+ {
55
+ if (!session_->session_)
56
+ return;
57
+ while (true)
58
+ {
59
+ WebTransportStream *stream =
60
+ session_->session_->AcceptIncomingUnidirectionalStream();
61
+ if (stream == nullptr)
62
+ {
63
+ return;
64
+ }
65
+ Http3WTStream *wtstream = new Http3WTStream(stream);
66
+ QUIC_DVLOG(1)
67
+ << "Http3WTSession received a unidirectional stream";
68
+ stream->SetVisitor(
69
+ std::make_unique<Http3WTStream::Visitor>(wtstream));
70
+ session_->getJS()->processStream(true, false, static_cast<Http3WTStream *>(wtstream));
71
+ stream->visitor()->OnCanRead();
72
+ }
73
+ }
74
+
75
+ void Http3WTSession::Visitor::OnDatagramReceived(absl::string_view datagram)
76
+ {
77
+ // printf("OnDatagramReceived %d %x %x\n", getpid(), this, session_);
78
+ session_->getJS()->processDatagramReceived(new std::string(datagram));
79
+ /*auto buffer = MakeUniqueBuffer(&allocator_, datagram.size());
80
+ memcpy(buffer.get(), datagram.data(), datagram.size());
81
+ quiche::QuicheMemSlice slice(std::move(buffer), datagram.size());
82
+ session_->SendOrQueueDatagram(std::move(slice));*/
83
+ }
84
+
85
+ void Http3WTSession::init(WebTransportSession *session)
86
+ {
87
+ session_ = session;
88
+ if (session_)
89
+ {
90
+ session_->SetOnDraining([this]()
91
+ { getJS()->processGoawayReceived(); });
92
+ }
93
+ }
94
+
95
+ void Http3WTSession::orderSessionStatsInt()
96
+ {
97
+ if (session_)
98
+ getJS()->processSessionStats(session_->GetSessionStats());
99
+ }
100
+
101
+ void Http3WTSession::orderDatagramStatsInt()
102
+ {
103
+ if (session_)
104
+ getJS()->processDatagramStats(session_->GetDatagramStats());
105
+ }
106
+
107
+ void Http3WTSession::TrySendingBidirectionalStreams()
108
+ {
109
+ if (!session_)
110
+ return;
111
+ while (ordBidiStreams > 0 &&
112
+ session_->CanOpenNextOutgoingBidirectionalStream())
113
+ {
114
+ QUIC_DVLOG(1)
115
+ << "Http3WTSessionVisitor opens a bidirectional stream";
116
+ WebTransportStream *stream = session_->OpenOutgoingBidirectionalStream();
117
+ Http3WTStream *wtstream = new Http3WTStream(stream);
118
+ stream->SetVisitor(
119
+ std::make_unique<Http3WTStream::Visitor>(wtstream));
120
+ getJS()->processStream(false, true, static_cast<Http3WTStream *>(wtstream));
121
+ stream->visitor()->OnCanWrite();
122
+ ordBidiStreams--;
123
+ }
124
+ }
125
+
126
+ void Http3WTSession::Visitor::OnSessionReady()
127
+ {
128
+ if (!session_->session_) return;
129
+
130
+ session_->getJS()->processSessionReady();
131
+
132
+ if (session_->session_->CanOpenNextOutgoingBidirectionalStream())
133
+ {
134
+ OnCanCreateNewOutgoingBidirectionalStream();
135
+ }
136
+ if (session_->session_->CanOpenNextOutgoingUnidirectionalStream())
137
+ {
138
+ OnCanCreateNewOutgoingUnidirectionalStream();
139
+ }
140
+ }
141
+
142
+ void Http3WTSession::TrySendingUnidirectionalStreams()
143
+ {
144
+ if (!session_)
145
+ return;
146
+ // move to some where else?
147
+ while (ordUnidiStreams > 0 &&
148
+ session_->CanOpenNextOutgoingUnidirectionalStream())
149
+ {
150
+ QUIC_DVLOG(1)
151
+ << "Http3WTSessionVisitor opened a unidirectional stream";
152
+ WebTransportStream *stream = session_->OpenOutgoingUnidirectionalStream();
153
+ Http3WTStream *wtstream = new Http3WTStream(stream);
154
+ stream->SetVisitor(
155
+ std::make_unique<Http3WTStream::Visitor>(wtstream));
156
+
157
+ getJS()->processStream(false, false, static_cast<Http3WTStream *>(wtstream));
158
+ stream->visitor()->OnCanWrite();
159
+ ordUnidiStreams--;
160
+ }
161
+ }
162
+
163
+ void Http3WTSession::writeDatagramInt(char *buffer, size_t len, Napi::ObjectReference *bufferhandle)
164
+ {
165
+ // printf("Datagram write %d %x %x\n", getpid(), this, session_ );
166
+ if (!session_)
167
+ {
168
+ // printf("Datagram session gone %d %x %x\n", getpid(), this, session_);
169
+ getJS()->processDatagramSend(bufferhandle);
170
+ return;
171
+ }
172
+ auto status = session_->SendOrQueueDatagram(absl::string_view(buffer, len));
173
+ // printf("Datagram status %d %d %s %x %x\n", getpid(), status.code, status.error_message.c_str(), this, session_);
174
+ getJS()->processDatagramSend(bufferhandle);
175
+ }
176
+
177
+ void Http3WTSessionJS::processStream(bool incom, bool bidi, Http3WTStream *stream)
178
+ {
179
+ Napi::HandleScope scope(Env());
180
+ Http3Constructors *constr = Env().GetInstanceData<Http3Constructors>();
181
+ Napi::Object strobj = constr->stream.New({});
182
+ Http3WTStreamJS *strjs = Napi::ObjectWrap<Http3WTStreamJS>::Unwrap(strobj);
183
+ strjs->setObj(stream);
184
+ if (!stream->gone())
185
+ strjs->Ref();
186
+
187
+ stream->setJS(strjs);
188
+
189
+ Napi::Object objVal = Value().Get("jsobj").As<Napi::Object>();
190
+
191
+ Napi::Object retObj = Napi::Object::New(Env());
192
+ retObj.Set("stream", strobj);
193
+ retObj.Set("incoming", incom);
194
+ retObj.Set("bidirectional", bidi);
195
+
196
+ objVal.Get("onStream").As<Napi::Function>().Call(objVal, {retObj});
197
+ }
198
+
199
+ void Http3WTSessionJS::processGoawayReceived()
200
+ {
201
+ Napi::HandleScope scope(Env());
202
+
203
+ Napi::Object objVal = Value().Get("jsobj").As<Napi::Object>();
204
+
205
+ Napi::Object retObj = Napi::Object::New(Env());
206
+ objVal.Get("onGoAwayReceived").As<Napi::Function>().Call(objVal, {retObj});
207
+ }
208
+
209
+ void Http3WTSessionJS::processSessionStats(webtransport::SessionStats sessstats)
210
+ {
211
+ Napi::HandleScope scope(Env());
212
+
213
+ Napi::Object objVal = Value().Get("jsobj").As<Napi::Object>();
214
+
215
+ Napi::Object retObj = Napi::Object::New(Env());
216
+ // expiredOutgoing: bigint
217
+ // lostOutgoing: bigint
218
+
219
+ // non Datagram
220
+ // minRtt: number
221
+ // smoothedRtt: number
222
+ // rttVariation: number
223
+ // estimatedSendRateBps: bigint
224
+ retObj.Set("timestamp", absl::ToDoubleMilliseconds(absl::Duration())); // absl::Duration
225
+ // datagram
226
+ retObj.Set("expiredOutgoing", Napi::BigInt::New(Env(), sessstats.datagram_stats.expired_outgoing)); // uint64_t
227
+ retObj.Set("lostOutgoing", Napi::BigInt::New(Env(), sessstats.datagram_stats.lost_outgoing)); // uint64_t
228
+
229
+ // non Datagram
230
+ retObj.Set("minRtt", absl::ToDoubleMilliseconds(sessstats.min_rtt)); // absl::Duration
231
+ retObj.Set("smoothedRtt", absl::ToDoubleMilliseconds(sessstats.smoothed_rtt)); // absl::Duration
232
+ retObj.Set("rttVariation", absl::ToDoubleMilliseconds(sessstats.rtt_variation)); // absl::Duration
233
+ retObj.Set("estimatedSendRateBps", sessstats.estimated_send_rate_bps); // absl::Duration
234
+
235
+ objVal.Get("onSessionStats").As<Napi::Function>().Call(objVal, {retObj});
236
+ }
237
+
238
+ void Http3WTSessionJS::processDatagramStats(webtransport::DatagramStats datastats)
239
+ {
240
+ Napi::HandleScope scope(Env());
241
+
242
+ Napi::Object objVal = Value().Get("jsobj").As<Napi::Object>();
243
+
244
+ Napi::Object retObj = Napi::Object::New(Env());
245
+ retObj.Set("timestamp", absl::ToDoubleMilliseconds(absl::Duration())); // absl::Duration
246
+ // datagram
247
+ retObj.Set("expiredOutgoing", Napi::BigInt::New(Env(), datastats.expired_outgoing)); // uint64_t
248
+ retObj.Set("lostOutgoing", Napi::BigInt::New(Env(), datastats.lost_outgoing)); // uint64_t
249
+
250
+ objVal.Get("onDatagramStats").As<Napi::Function>().Call(objVal, {retObj});
251
+ }
252
+
253
+ void Http3WTSessionJS::processDatagramSend(Napi::ObjectReference *bufferhandle)
254
+ {
255
+ bufferhandle->Unref(); // release the outgoing buffer
256
+ delete bufferhandle; // free the handle object
257
+
258
+ Napi::HandleScope scope(Env());
259
+ Napi::Object objVal = Value().Get("jsobj").As<Napi::Object>();
260
+
261
+ Napi::Object retObj = Napi::Object::New(Env());
262
+
263
+ objVal.Get("onDatagramSend").As<Napi::Function>().Call(objVal, {retObj});
264
+ }
265
+
266
+ void Http3WTSessionJS::processSessionReady()
267
+ {
268
+ Napi::HandleScope scope(Env());
269
+ Napi::Object objVal = Value().Get("jsobj").As<Napi::Object>();
270
+
271
+ Napi::Object retObj = Napi::Object::New(Env());
272
+
273
+ objVal.Get("onReady").As<Napi::Function>().Call(objVal, {retObj});
274
+ }
275
+
276
+ void Http3WTSessionJS::processSessionClose(uint32_t errorcode, const std::string &error)
277
+ {
278
+ Napi::HandleScope scope(Env());
279
+
280
+ Napi::Object objVal = Value().Get("jsobj").As<Napi::Object>();
281
+
282
+ Napi::Object retObj = Napi::Object::New(Env());
283
+ retObj.Set("error", error);
284
+ retObj.Set("errorcode", errorcode);
285
+
286
+ objVal.Get("onClose").As<Napi::Function>().Call(objVal, {retObj});
287
+ }
288
+
289
+ void Http3WTSessionJS::processDatagramReceived(std::string *datagram)
290
+ {
291
+ Napi::HandleScope scope(Env());
292
+ Napi::Object datagramVal =
293
+ Napi::Uint8Array::New(Env(),
294
+ datagram->length(),
295
+ Napi::ArrayBuffer::New(Env(), &(*datagram)[0], datagram->length(),
296
+ freeData, datagram),
297
+ 0);
298
+
299
+ Napi::Object objVal = Value().Get("jsobj").As<Napi::Object>();
300
+
301
+ Napi::Object retObj = Napi::Object::New(Env());
302
+ retObj.Set("datagram", datagramVal);
303
+
304
+ objVal.Get("onDatagramReceived").As<Napi::Function>().Call(objVal, {retObj});
305
+ }
306
+
307
+ void Http3WTSessionJS::freeData(Napi::Env env, void *data, std::string *hint)
308
+ {
309
+ // ok free data is actually using a string object
310
+ delete hint;
311
+ }
312
+ }
@@ -0,0 +1,257 @@
1
+ // modifications
2
+ // Copyright (c) 2022 Marten Richter or other contributers (see commit). All rights reserved.
3
+ // Use of this source code is governed by a BSD-style license that can be
4
+ // found in the LICENSE file.
5
+
6
+ // original copyright, see LICENSE.chromium
7
+ // Copyright (c) 2021 The Chromium Authors. All rights reserved.
8
+ // Use of this source code is governed by a BSD-style license that can be
9
+ // found in the LICENSE file.
10
+
11
+ #ifndef HTTP3_WT_SESSION_VISITOR_H_
12
+ #define HTTP3_WT_SESSION_VISITOR_H_
13
+
14
+ #include <napi.h>
15
+
16
+ #include <atomic>
17
+
18
+ #include <string>
19
+
20
+ #include "src/librarymain.h"
21
+ #include "src/http3wtstreamvisitor.h"
22
+ #include "src/http3wtsessionvisitor.h"
23
+
24
+ #include "quiche/quic/core/web_transport_interface.h"
25
+ #include "quiche/quic/platform/api/quic_logging.h"
26
+ #include "quiche/common/quiche_circular_deque.h"
27
+ #include "quiche/common/platform/api/quiche_mem_slice.h"
28
+
29
+ namespace quic
30
+ {
31
+ // class Http3Server;
32
+ class Http3WTSessionJS;
33
+
34
+ class Http3WTSession
35
+ {
36
+ friend Http3WTSessionJS;
37
+
38
+ public:
39
+ Http3WTSession()
40
+ : ordBidiStreams(0), ordUnidiStreams(0), session_(nullptr), js_(nullptr)
41
+ {
42
+ }
43
+
44
+ ~Http3WTSession()
45
+ {
46
+ // printf("session destruct %x\n", this);
47
+ }
48
+
49
+ // need to be called immediately after new
50
+ void init(WebTransportSession *session);
51
+
52
+ class Visitor : public WebTransportVisitor
53
+ {
54
+ public:
55
+ Visitor(Http3WTSession *session) : session_(session) {}
56
+
57
+ ~Visitor();
58
+
59
+ void OnSessionReady() override;
60
+
61
+ void OnSessionClosed(WebTransportSessionError error_code,
62
+ const std::string &error_message) override;
63
+
64
+ void OnIncomingBidirectionalStreamAvailable() override;
65
+
66
+ void OnIncomingUnidirectionalStreamAvailable() override;
67
+
68
+ void OnDatagramReceived(absl::string_view datagram) override;
69
+
70
+ void OnCanCreateNewOutgoingBidirectionalStream() override
71
+ {
72
+ // unclear how we can stich this together?
73
+ session_->TrySendingBidirectionalStreams();
74
+ }
75
+
76
+ void OnCanCreateNewOutgoingUnidirectionalStream() override
77
+ {
78
+ session_->TrySendingUnidirectionalStreams();
79
+ }
80
+
81
+ protected:
82
+ Http3WTSession *session_;
83
+ };
84
+
85
+ void
86
+ tryOpenBidiStream()
87
+ {
88
+ ordBidiStreams++;
89
+ TrySendingBidirectionalStreams();
90
+ }
91
+
92
+ void tryOpenUnidiStream()
93
+ {
94
+ ordUnidiStreams++;
95
+ TrySendingUnidirectionalStreams();
96
+ }
97
+
98
+ void TrySendingBidirectionalStreams();
99
+
100
+ void TrySendingUnidirectionalStreams();
101
+
102
+ Http3WTSessionJS *getJS() { return js_; };
103
+ void setJS(Http3WTSessionJS *js)
104
+ {
105
+ js_ = js;
106
+ };
107
+
108
+ private:
109
+ Http3WTSessionJS *js_;
110
+
111
+ void notifySessionDrainingInt()
112
+ {
113
+ if (session_)
114
+ session_->NotifySessionDraining();
115
+ }
116
+
117
+ void orderSessionStatsInt();
118
+
119
+ void orderDatagramStatsInt();
120
+
121
+ void closeInt(int code, std::string &reason)
122
+ {
123
+ if (session_)
124
+ session_->CloseSession(code, reason);
125
+ }
126
+
127
+ void writeDatagramInt(char *buffer, size_t len, Napi::ObjectReference *bufferhandle);
128
+
129
+ WebTransportSession *session_;
130
+ bool echo_stream_opened_ = false;
131
+ uint32_t ordBidiStreams;
132
+ uint32_t ordUnidiStreams;
133
+ };
134
+
135
+ class Http3WTSessionJS : public Napi::ObjectWrap<Http3WTSessionJS>
136
+ {
137
+ friend class Http3WTSession;
138
+ friend class Http3WTSession::Visitor;
139
+
140
+ public:
141
+ Http3WTSessionJS(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Http3WTSessionJS>(info)
142
+ {
143
+ }
144
+
145
+ void setObj(Http3WTSession *wtsession)
146
+ {
147
+ wtsession_ = std::unique_ptr<Http3WTSession>(wtsession);
148
+ }
149
+
150
+ Http3WTSession *getObj()
151
+ {
152
+ return wtsession_.get();
153
+ }
154
+
155
+ void orderBidiStream(const Napi::CallbackInfo &info)
156
+ {
157
+ wtsession_->tryOpenBidiStream();
158
+ }
159
+
160
+ void orderUnidiStream(const Napi::CallbackInfo &info)
161
+ {
162
+ wtsession_->tryOpenUnidiStream();
163
+ }
164
+
165
+ void writeDatagram(const Napi::CallbackInfo &info)
166
+ {
167
+ if (!info[0].IsUndefined())
168
+ {
169
+ Napi::Object bufferlocal = info[0].ToObject();
170
+ Napi::ObjectReference *bufferhandle = new Napi::ObjectReference();
171
+ *bufferhandle = Napi::Persistent(bufferlocal);
172
+ char *buffer = bufferlocal.As<Napi::Buffer<char>>().Data();
173
+ size_t len = bufferlocal.As<Napi::Buffer<char>>().Length();
174
+ wtsession_->writeDatagramInt(buffer, len, bufferhandle);
175
+ }
176
+ }
177
+
178
+ void notifySessionDraining(const Napi::CallbackInfo &info)
179
+ {
180
+ wtsession_->notifySessionDrainingInt();
181
+ }
182
+
183
+ void orderSessionStats(const Napi::CallbackInfo &info)
184
+ {
185
+ wtsession_->orderSessionStatsInt();
186
+ }
187
+
188
+ void orderDatagramStats(const Napi::CallbackInfo &info)
189
+ {
190
+ wtsession_->orderDatagramStatsInt();
191
+ }
192
+
193
+ void close(const Napi::CallbackInfo &info)
194
+ {
195
+ int code = 0;
196
+ std::string reason("unknown reason");
197
+
198
+ if (!info[0].IsUndefined())
199
+ {
200
+ Napi::Object obj = info[0].ToObject();
201
+ if (!obj.IsEmpty())
202
+ {
203
+ if (obj.Has("code") && !(obj).Get("code").IsEmpty())
204
+ {
205
+ Napi::Value codeValue = (obj).Get("code");
206
+ code = codeValue.As<Napi::Number>().Int32Value();
207
+ }
208
+ if (obj.Has("reason") && !(obj).Get("reason").IsEmpty())
209
+ {
210
+ Napi::Value reasonValue = (obj).Get("reason");
211
+ reason = reasonValue.ToString().Utf8Value();
212
+ }
213
+ }
214
+ }
215
+
216
+ wtsession_->closeInt(code, reason);
217
+ }
218
+
219
+ static void InitExports(Napi::Env env, Napi::Object exports, Http3Constructors *constr)
220
+ {
221
+ Napi::Function tplwt =
222
+ ObjectWrap<Http3WTSessionJS>::DefineClass(env, "Http3WTSessionVisitor",
223
+ {InstanceMethod<&Http3WTSessionJS::orderBidiStream>("orderBidiStream",
224
+ static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
225
+ InstanceMethod<&Http3WTSessionJS::orderUnidiStream>("orderUnidiStream",
226
+ static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
227
+ InstanceMethod<&Http3WTSessionJS::writeDatagram>("writeDatagram",
228
+ static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
229
+ InstanceMethod<&Http3WTSessionJS::notifySessionDraining>("notifySessionDraining",
230
+ static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
231
+ InstanceMethod<&Http3WTSessionJS::orderSessionStats>("orderSessionStats",
232
+ static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
233
+ InstanceMethod<&Http3WTSessionJS::orderDatagramStats>("orderDatagramStats",
234
+ static_cast<napi_property_attributes>(napi_writable | napi_configurable)),
235
+ InstanceMethod<&Http3WTSessionJS::close>("close",
236
+ static_cast<napi_property_attributes>(napi_writable | napi_configurable))});
237
+ constr->session = Napi::Persistent(tplwt);
238
+ exports.Set("Http3WTSessionVisitor", tplwt);
239
+ }
240
+
241
+ protected:
242
+ std::unique_ptr<Http3WTSession> wtsession_;
243
+
244
+ static void freeData(Napi::Env env, void *data, std::string *hint);
245
+
246
+ void processStream(bool incom, bool bidi, Http3WTStream *stream);
247
+ void processSessionStats(webtransport::SessionStats sessstats);
248
+ void processDatagramStats(webtransport::DatagramStats datastats);
249
+ void processGoawayReceived();
250
+ void processDatagramSend(Napi::ObjectReference *bufferhandle);
251
+ void processDatagramReceived(std::string *datagram);
252
+ void processSessionReady();
253
+ void processSessionClose(uint32_t errorcode, const std::string &error);
254
+ };
255
+
256
+ }
257
+ #endif