@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.
- package/CMakeLists.txt +978 -0
- package/LICENSE +39 -0
- package/LICENSE.chromium +27 -0
- package/LICENSE.envoy +207 -0
- package/build.js +315 -0
- package/lib/clientsocket.js +80 -0
- package/lib/index.js +47 -0
- package/lib/serversocket.js +80 -0
- package/lib/socket.js +118 -0
- package/lib/types.ts +15 -0
- package/lib/utils.js +12 -0
- package/package.json +68 -0
- package/platform/icufix/fakedata.cpp +8 -0
- package/platform/quiche/quic/core/io/socket_win.inc +3 -0
- package/platform/quiche_platform_impl/quiche_bug_tracker_impl.h +7 -0
- package/platform/quiche_platform_impl/quiche_client_stats_impl.h +7 -0
- package/platform/quiche_platform_impl/quiche_command_line_flags_impl.h +7 -0
- package/platform/quiche_platform_impl/quiche_containers_impl.h +7 -0
- package/platform/quiche_platform_impl/quiche_event_loop_impl.h +7 -0
- package/platform/quiche_platform_impl/quiche_export_impl.h +6 -0
- package/platform/quiche_platform_impl/quiche_flag_utils_impl.h +11 -0
- package/platform/quiche_platform_impl/quiche_flags_impl.h +8 -0
- package/platform/quiche_platform_impl/quiche_googleurl_impl.h +8 -0
- package/platform/quiche_platform_impl/quiche_iovec_impl.h +10 -0
- package/platform/quiche_platform_impl/quiche_logging_impl.h +21 -0
- package/platform/quiche_platform_impl/quiche_mem_slice_impl.h +2 -0
- package/platform/quiche_platform_impl/quiche_mutex_impl.h +8 -0
- package/platform/quiche_platform_impl/quiche_prefetch_impl.h +11 -0
- package/platform/quiche_platform_impl/quiche_reference_counted_impl.h +16 -0
- package/platform/quiche_platform_impl/quiche_server_stats_impl.h +7 -0
- package/platform/quiche_platform_impl/quiche_stack_trace_impl.h +12 -0
- package/platform/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h +8 -0
- package/platform/quiche_platform_impl/quiche_testvalue_impl.h +1 -0
- package/platform/quiche_platform_impl/quiche_thread_local_impl.h +6 -0
- package/platform/quiche_platform_impl/quiche_time_utils_impl.h +13 -0
- package/platform/quiche_platform_impl/quiche_udp_socket_platform_impl.h +39 -0
- package/readme.md +20 -0
- package/src/http3backendresponse.cc +36 -0
- package/src/http3backendresponse.h +109 -0
- package/src/http3client.cc +1402 -0
- package/src/http3client.h +531 -0
- package/src/http3clientsession.cc +65 -0
- package/src/http3clientsession.h +58 -0
- package/src/http3clientstream.cc +52 -0
- package/src/http3clientstream.h +42 -0
- package/src/http3dispatcher.cc +62 -0
- package/src/http3dispatcher.h +57 -0
- package/src/http3server.cc +529 -0
- package/src/http3server.h +149 -0
- package/src/http3serverbackend.cc +104 -0
- package/src/http3serverbackend.h +96 -0
- package/src/http3serversession.cc +123 -0
- package/src/http3serversession.h +95 -0
- package/src/http3serverstream.cc +463 -0
- package/src/http3serverstream.h +114 -0
- package/src/http3sessioncache.cc +85 -0
- package/src/http3sessioncache.h +59 -0
- package/src/http3wtsessionvisitor.cc +312 -0
- package/src/http3wtsessionvisitor.h +257 -0
- package/src/http3wtstreamvisitor.cc +286 -0
- package/src/http3wtstreamvisitor.h +323 -0
- package/src/librarymain.cc +86 -0
- package/src/librarymain.h +42 -0
- package/src/napialarmfactory.cc +51 -0
- package/src/napialarmfactory.h +165 -0
- package/src/socketjswriter.cc +46 -0
- 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
|