@fails-components/webtransport-transport-http3-quiche 1.0.10 → 1.1.0
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 +2 -0
- package/dist/lib/index.d.ts +2 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/socket.d.ts.map +1 -1
- package/dist/lib/types.d.ts +7 -1
- package/dist/lib/types.d.ts.map +1 -1
- package/lib/index.js +5 -1
- package/lib/socket.js +6 -2
- package/lib/types.ts +8 -2
- package/package.json +1 -1
- package/src/http3client.cc +5 -8
- package/src/http3client.h +4 -0
- package/src/http3server.cc +67 -14
- package/src/http3server.h +2 -2
- package/src/http3serverbackend.cc +12 -11
- package/src/http3wtstreamvisitor.cc +39 -14
- package/src/http3wtstreamvisitor.h +1 -0
- package/src/librarymain.cc +1 -1
- package/src/napialarmfactory.h +8 -1
package/CMakeLists.txt
CHANGED
|
@@ -539,6 +539,8 @@ third_party/quiche/quiche/quic/core/http/quic_spdy_stream.cc
|
|
|
539
539
|
third_party/quiche/quiche/quic/core/http/quic_spdy_stream.h
|
|
540
540
|
third_party/quiche/quiche/quic/core/http/quic_spdy_stream_body_manager.cc
|
|
541
541
|
third_party/quiche/quiche/quic/core/http/quic_spdy_stream_body_manager.h
|
|
542
|
+
third_party/quiche/quiche/quic/core/http/metadata_decoder.cc
|
|
543
|
+
third_party/quiche/quiche/quic/core/http/metadata_decoder.h
|
|
542
544
|
third_party/quiche/quiche/quic/core/http/spdy_utils.cc
|
|
543
545
|
third_party/quiche/quiche/quic/core/http/spdy_utils.h
|
|
544
546
|
third_party/quiche/quiche/quic/core/http/web_transport_http3.cc
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export const wtrouter: any;
|
|
2
2
|
export const quicheInit: any;
|
|
3
3
|
export function checkQuicheInit(args?: {
|
|
4
|
-
quicheLogVerbose?:
|
|
4
|
+
quicheLogVerbose?: import("./types.js").QUICHE_LOG | undefined;
|
|
5
5
|
path?: string | undefined;
|
|
6
6
|
} | undefined): void;
|
|
7
7
|
export const Http3WebTransportClient: any;
|
|
8
8
|
export const Http3WebTransportServer: any;
|
|
9
9
|
export { Http3WebTransportClientSocket } from "./clientsocket.js";
|
|
10
10
|
export { Http3WebTransportServerSocket } from "./serversocket.js";
|
|
11
|
+
export type QUICHE_LOG = import('./types.js').QUICHE_LOG;
|
|
11
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/index.js"],"names":[],"mappings":"AA8BA,2BAAuC;AACvC,6BAA6C;AAOtC;;;qBAON;AAED,0CAAuE;AACvE,0CAAuE;;;yBAxC1D,OAAO,YAAY,EAAE,UAAU"}
|
package/dist/lib/socket.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../lib/socket.js"],"names":[],"mappings":"AAqEA;IACE;;OAEG;IACH,kBAFW,OAAO,4BAA4B,EAAE,oBAAoB,GAAC,SAAS,EAa7E;IAVC,0CAA0C;IAE1C,WAFW,OAAO,YAAY,EAAE,MAAM,CAEZ;IAE1B,UAAqB;IACrB,oBAAuB;IAgCzB,
|
|
1
|
+
{"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../lib/socket.js"],"names":[],"mappings":"AAqEA;IACE;;OAEG;IACH,kBAFW,OAAO,4BAA4B,EAAE,oBAAoB,GAAC,SAAS,EAa7E;IAVC,0CAA0C;IAE1C,WAFW,OAAO,YAAY,EAAE,MAAM,CAEZ;IAE1B,UAAqB;IACrB,oBAAuB;IAgCzB,qBASC;IAlCD,+BAGC;IAPC,iBAAoB;IACpB,gBAAmB;IAQrB;;OAEG;IAEH,mDAHW,OAAO,SAAS,EAAE,mBAAmB,WAiB/C;CAYF"}
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -11,10 +11,16 @@ export interface Logger {
|
|
|
11
11
|
error: (formatter: any, ...args: any[]) => void;
|
|
12
12
|
trace: (formatter: any, ...args: any[]) => void;
|
|
13
13
|
}
|
|
14
|
+
export type QUICHE_LOG_OFF = -1;
|
|
15
|
+
export type QUICHE_LOG_INFO = 0;
|
|
16
|
+
export type QUICHE_LOG_WARNING = 1;
|
|
17
|
+
export type QUICHE_LOG_ERROR = 2;
|
|
18
|
+
export type QUICHE_LOG_FATAL = 3;
|
|
19
|
+
export type QUICHE_LOG = QUICHE_LOG_OFF | QUICHE_LOG_INFO | QUICHE_LOG_WARNING | QUICHE_LOG_ERROR | QUICHE_LOG_FATAL;
|
|
14
20
|
export interface HttpWebTransportInit extends WebTransportOptions {
|
|
15
21
|
host: string;
|
|
16
22
|
port: string | number;
|
|
17
|
-
quicheLogVerbose?:
|
|
23
|
+
quicheLogVerbose?: QUICHE_LOG;
|
|
18
24
|
forceIpv6?: boolean;
|
|
19
25
|
localPort?: number;
|
|
20
26
|
}
|
package/dist/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACpB,MAAM,uBAAuB,CAAA;AAE9B,MAAM,WAAW,mBAAmB;IAChC,GAAG,EAAG,UAAU,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAC,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,MAAM;IACrB,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IACtC,KAAK,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;IAC/C,KAAK,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;CAChD;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACpB,MAAM,uBAAuB,CAAA;AAE9B,MAAM,WAAW,mBAAmB;IAChC,GAAG,EAAG,UAAU,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAC,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,MAAM;IACrB,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IACtC,KAAK,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;IAC/C,KAAK,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;CAChD;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,CAAA;AAC/B,MAAM,MAAM,eAAe,GAAG,CAAC,CAAA;AAC/B,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAA;AAClC,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAA;AAChC,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAA;AAChC,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,eAAe,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,gBAAgB,CAAA;AAElH,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IACrB,gBAAgB,CAAC,EAAE,UAAU,CAAA;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB"}
|
package/lib/index.js
CHANGED
|
@@ -5,6 +5,10 @@ import * as url from 'url'
|
|
|
5
5
|
import { arch, platform } from 'node:process'
|
|
6
6
|
import { logger } from './utils.js'
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {import('./types.js').QUICHE_LOG} QUICHE_LOG
|
|
10
|
+
*/
|
|
11
|
+
|
|
8
12
|
const log = logger(`webtransport:native(${process?.pid})`)
|
|
9
13
|
|
|
10
14
|
const binplatform = platform + '_' + arch
|
|
@@ -30,7 +34,7 @@ export const quicheInit = wtrouter.quicheInit
|
|
|
30
34
|
let quicheInited = false
|
|
31
35
|
|
|
32
36
|
/**
|
|
33
|
-
* @param {{quicheLogVerbose?:
|
|
37
|
+
* @param {{quicheLogVerbose?: QUICHE_LOG, path?: string}} [args]
|
|
34
38
|
*/
|
|
35
39
|
export const checkQuicheInit = function (args) {
|
|
36
40
|
if (!quicheInited) {
|
package/lib/socket.js
CHANGED
|
@@ -110,8 +110,12 @@ export class Http3WebTransportSocket {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
packetSendCB() {
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
if (
|
|
114
|
+
!this.closed &&
|
|
115
|
+
// @ts-ignore
|
|
116
|
+
this.socketInt.getSendQueueCount() === 0 &&
|
|
117
|
+
this.blocked
|
|
118
|
+
) {
|
|
115
119
|
this.cobj.onCanWrite()
|
|
116
120
|
}
|
|
117
121
|
}
|
package/lib/types.ts
CHANGED
|
@@ -16,11 +16,17 @@ export interface UDPServerSocketSend {
|
|
|
16
16
|
trace: (formatter: any, ...args: any[]) => void
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
export type QUICHE_LOG_OFF = -1
|
|
20
|
+
export type QUICHE_LOG_INFO = 0
|
|
21
|
+
export type QUICHE_LOG_WARNING = 1
|
|
22
|
+
export type QUICHE_LOG_ERROR = 2
|
|
23
|
+
export type QUICHE_LOG_FATAL = 3
|
|
24
|
+
export type QUICHE_LOG = QUICHE_LOG_OFF | QUICHE_LOG_INFO | QUICHE_LOG_WARNING | QUICHE_LOG_ERROR | QUICHE_LOG_FATAL
|
|
25
|
+
|
|
19
26
|
export interface HttpWebTransportInit extends WebTransportOptions {
|
|
20
27
|
host: string
|
|
21
28
|
port: string | number
|
|
22
|
-
quicheLogVerbose?:
|
|
29
|
+
quicheLogVerbose?: QUICHE_LOG
|
|
23
30
|
forceIpv6?: boolean
|
|
24
31
|
localPort?: number
|
|
25
32
|
}
|
|
26
|
-
|
package/package.json
CHANGED
package/src/http3client.cc
CHANGED
|
@@ -532,7 +532,7 @@ namespace quic
|
|
|
532
532
|
if (wait_for_encryption_)
|
|
533
533
|
{
|
|
534
534
|
if (EncryptionBeingEstablished())
|
|
535
|
-
return
|
|
535
|
+
return true;
|
|
536
536
|
wait_for_encryption_ = false;
|
|
537
537
|
ParsedQuicVersion version = UnsupportedQuicVersion();
|
|
538
538
|
if (session_ != nullptr && !CanReconnectWithDifferentVersion(&version) && !session_->connection()->connected())
|
|
@@ -569,11 +569,6 @@ namespace quic
|
|
|
569
569
|
recheck = true;
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
-
if (checkSession())
|
|
573
|
-
{
|
|
574
|
-
recheck = true;
|
|
575
|
-
}
|
|
576
|
-
|
|
577
572
|
return recheck;
|
|
578
573
|
}
|
|
579
574
|
|
|
@@ -826,16 +821,18 @@ namespace quic
|
|
|
826
821
|
|
|
827
822
|
if (client_->connectionrecheck_)
|
|
828
823
|
{
|
|
829
|
-
client_->connectionrecheck_ =
|
|
824
|
+
client_->connectionrecheck_ = client_->handleConnecting();
|
|
830
825
|
}
|
|
826
|
+
if (client_->needsToCheckForSession()) client_->checkSession();
|
|
831
827
|
}
|
|
832
828
|
|
|
833
829
|
void Http3ClientJS::onCanWrite(const Napi::CallbackInfo &info)
|
|
834
830
|
{
|
|
835
831
|
if (client_->connectionrecheck_)
|
|
836
832
|
{
|
|
837
|
-
client_->connectionrecheck_ =
|
|
833
|
+
client_->connectionrecheck_ = client_->handleConnecting();
|
|
838
834
|
}
|
|
835
|
+
if (client_->needsToCheckForSession()) client_->checkSession();
|
|
839
836
|
client_->OnCanWrite();
|
|
840
837
|
}
|
|
841
838
|
|
package/src/http3client.h
CHANGED
|
@@ -349,6 +349,10 @@ namespace quic
|
|
|
349
349
|
|
|
350
350
|
bool checkSession();
|
|
351
351
|
|
|
352
|
+
bool needsToCheckForSession() {
|
|
353
|
+
return finish_stream_open_.size() > 0 && session_->CanOpenNextOutgoingBidirectionalStream();
|
|
354
|
+
}
|
|
355
|
+
|
|
352
356
|
// Read oldest received response and remove it from closed_stream_states_.
|
|
353
357
|
// void ReadNextResponse();
|
|
354
358
|
|
package/src/http3server.cc
CHANGED
|
@@ -91,8 +91,8 @@ namespace quic
|
|
|
91
91
|
Http3ServerJS::Http3ServerJS(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Http3ServerJS>(info)
|
|
92
92
|
{
|
|
93
93
|
std::string secret;
|
|
94
|
-
std::string cert;
|
|
95
|
-
std::string privkey;
|
|
94
|
+
std::vector<std::string> cert;
|
|
95
|
+
std::vector<std::string> privkey;
|
|
96
96
|
|
|
97
97
|
QuicConfig sconfig;
|
|
98
98
|
if (!info[0].IsUndefined())
|
|
@@ -113,7 +113,16 @@ namespace quic
|
|
|
113
113
|
if (lobj.Has("cert") && !(lobj).Get("cert").IsEmpty())
|
|
114
114
|
{
|
|
115
115
|
Napi::Value certValue = (lobj).Get("cert");
|
|
116
|
-
|
|
116
|
+
if (!certValue.IsArray()) {
|
|
117
|
+
cert.push_back(certValue.ToString().Utf8Value());
|
|
118
|
+
} else {
|
|
119
|
+
Napi::Array certArray = certValue.As<Napi::Array>();
|
|
120
|
+
if (certArray.Length() < 1) Napi::Error::New(Env(), "No cert in array for Http3Server").ThrowAsJavaScriptException();
|
|
121
|
+
for (uint32_t i = 0; i < certArray.Length(); i++) {
|
|
122
|
+
Napi::Value curval = certArray.Get(i);
|
|
123
|
+
cert.push_back(curval.ToString().Utf8Value());
|
|
124
|
+
}
|
|
125
|
+
}
|
|
117
126
|
}
|
|
118
127
|
else
|
|
119
128
|
{
|
|
@@ -123,13 +132,23 @@ namespace quic
|
|
|
123
132
|
if (lobj.Has("privKey") && !(lobj).Get("privKey").IsEmpty())
|
|
124
133
|
{
|
|
125
134
|
Napi::Value keyValue = (lobj).Get("privKey");
|
|
126
|
-
|
|
135
|
+
if (!keyValue.IsArray()) {
|
|
136
|
+
privkey.push_back(keyValue.ToString().Utf8Value());
|
|
137
|
+
} else {
|
|
138
|
+
Napi::Array keyArray = keyValue.As<Napi::Array>();
|
|
139
|
+
if (keyArray.Length() < 1) Napi::Error::New(Env(), "No key in array for Http3Server").ThrowAsJavaScriptException();
|
|
140
|
+
for (uint32_t i = 0; i < keyArray.Length(); i++) {
|
|
141
|
+
Napi::Value curval = keyArray.Get(i);
|
|
142
|
+
privkey.push_back(curval.ToString().Utf8Value());
|
|
143
|
+
}
|
|
144
|
+
}
|
|
127
145
|
}
|
|
128
146
|
else
|
|
129
147
|
{
|
|
130
148
|
Napi::Error::New(Env(), "No privKey set for Http3Server").ThrowAsJavaScriptException();
|
|
131
149
|
return;
|
|
132
150
|
}
|
|
151
|
+
if (privkey.size() != cert.size()) Napi::Error::New(Env(), "Key and cert array length for Http3Server do not match").ThrowAsJavaScriptException();
|
|
133
152
|
if (lobj.Has("maxConnections") && !(lobj).Get("maxConnections").IsEmpty())
|
|
134
153
|
{
|
|
135
154
|
Napi::Value maxconnValue = (lobj).Get("maxConnections");
|
|
@@ -176,10 +195,10 @@ namespace quic
|
|
|
176
195
|
}
|
|
177
196
|
// Callback *callback, int port, std::unique_ptr<ProofSource> proof_source, const char *secret
|
|
178
197
|
|
|
179
|
-
std::stringstream certstream(cert, std::ios_base::in);
|
|
198
|
+
std::stringstream certstream(cert[0], std::ios_base::in);
|
|
180
199
|
quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain(new ProofSource::Chain(CertificateView::LoadPemFromStream(&certstream)));
|
|
181
200
|
|
|
182
|
-
std::stringstream privkeystream(privkey, std::ios_base::in);
|
|
201
|
+
std::stringstream privkeystream(privkey[0], std::ios_base::in);
|
|
183
202
|
|
|
184
203
|
auto certprivkey = CertificatePrivateKey::LoadPemFromStream(&privkeystream);
|
|
185
204
|
if (certprivkey == nullptr)
|
|
@@ -194,6 +213,25 @@ namespace quic
|
|
|
194
213
|
Napi::Error::New(Env(), "LoadPemFromStream cert failed for Http3Server").ThrowAsJavaScriptException();
|
|
195
214
|
return;
|
|
196
215
|
}
|
|
216
|
+
// add additional certs to proof source
|
|
217
|
+
for (size_t i = 1; i < cert.size(); i++)
|
|
218
|
+
{
|
|
219
|
+
std::stringstream addcertstream(cert[0], std::ios_base::in);
|
|
220
|
+
quiche::QuicheReferenceCountedPointer<ProofSource::Chain> addchain(new ProofSource::Chain(CertificateView::LoadPemFromStream(&addcertstream)));
|
|
221
|
+
std::stringstream addprivkeystream(privkey[0], std::ios_base::in);
|
|
222
|
+
auto addcertprivkey = CertificatePrivateKey::LoadPemFromStream(&privkeystream);
|
|
223
|
+
if (addcertprivkey == nullptr)
|
|
224
|
+
{
|
|
225
|
+
Napi::Error::New(Env(), "LoadPemFromStream addprivKey failed for Http3Server").ThrowAsJavaScriptException();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (!proofsource->AddCertificateChain(addchain, std::move(*addcertprivkey)))
|
|
230
|
+
{
|
|
231
|
+
Napi::Error::New(Env(), "AddCertificateChain failed for Http3Server").ThrowAsJavaScriptException();
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
197
235
|
|
|
198
236
|
server_ = std::make_unique<Http3Server>(this, std::move(proofsource), secret.c_str(), sconfig);
|
|
199
237
|
|
|
@@ -207,7 +245,7 @@ namespace quic
|
|
|
207
245
|
}
|
|
208
246
|
|
|
209
247
|
Http3ServerJS::~Http3ServerJS()
|
|
210
|
-
{
|
|
248
|
+
{
|
|
211
249
|
}
|
|
212
250
|
|
|
213
251
|
void Http3ServerJS::destroy(const Napi::CallbackInfo &info)
|
|
@@ -357,7 +395,7 @@ namespace quic
|
|
|
357
395
|
}
|
|
358
396
|
}*/
|
|
359
397
|
|
|
360
|
-
void Http3ServerJS::processNewSession(Http3WTSession *session, const std::string &path, Napi::Reference<Napi::Value> *header)
|
|
398
|
+
void Http3ServerJS::processNewSession(Http3WTSession *session, const std::string &path, Napi::Reference<Napi::Value> *header, Napi::Reference<Napi::Value> *userData)
|
|
361
399
|
{
|
|
362
400
|
Napi::HandleScope scope(Env());
|
|
363
401
|
|
|
@@ -378,12 +416,17 @@ namespace quic
|
|
|
378
416
|
retObj.Set("header", header->Value());
|
|
379
417
|
header->Unref();
|
|
380
418
|
}
|
|
419
|
+
if (userData)
|
|
420
|
+
{
|
|
421
|
+
retObj.Set("userData", userData->Value());
|
|
422
|
+
userData->Unref();
|
|
423
|
+
}
|
|
381
424
|
objVal.Get("onHttpWTSessionVisitor")
|
|
382
425
|
.As<Napi::Function>()
|
|
383
426
|
.Call(objVal, {retObj});
|
|
384
427
|
}
|
|
385
428
|
|
|
386
|
-
void Http3ServerJS::processNewSessionRequest(WebTransportSession *session, const spdy::Http2HeaderBlock &reqhead, WebTransportRespPromisePtr
|
|
429
|
+
void Http3ServerJS::processNewSessionRequest(WebTransportSession *session, const spdy::Http2HeaderBlock &reqhead, WebTransportRespPromisePtr promise)
|
|
387
430
|
{
|
|
388
431
|
Napi::HandleScope scope(Env());
|
|
389
432
|
|
|
@@ -401,10 +444,11 @@ namespace quic
|
|
|
401
444
|
}
|
|
402
445
|
retObj.Set("header", headObj);
|
|
403
446
|
// delete reqheadcopy; // we own it and must free it!
|
|
404
|
-
|
|
447
|
+
|
|
448
|
+
WebTransportRespPromisePtr *prompointer = new WebTransportRespPromisePtr(promise);
|
|
405
449
|
// promise
|
|
406
450
|
Napi::External<WebTransportRespPromisePtr> promObj =
|
|
407
|
-
Napi::External<WebTransportRespPromisePtr>::New(Env(),
|
|
451
|
+
Napi::External<WebTransportRespPromisePtr>::New(Env(), prompointer,
|
|
408
452
|
[](Napi::Env /*env*/, WebTransportRespPromisePtr *ref)
|
|
409
453
|
{
|
|
410
454
|
delete ref; // we own it and must delete it
|
|
@@ -419,6 +463,7 @@ namespace quic
|
|
|
419
463
|
// does it outlife everything?
|
|
420
464
|
});
|
|
421
465
|
retObj.Set("session", wtsObj);
|
|
466
|
+
retObj.Set("protocol", "http3:libquiche");
|
|
422
467
|
|
|
423
468
|
objVal.Get("onSessionRequest")
|
|
424
469
|
.As<Napi::Function>()
|
|
@@ -465,7 +510,7 @@ namespace quic
|
|
|
465
510
|
path = pathValue.ToString().Utf8Value();
|
|
466
511
|
}
|
|
467
512
|
else
|
|
468
|
-
return Napi::Error::New(Env(), "No
|
|
513
|
+
return Napi::Error::New(Env(), "No path passed for finishSessionRequest").ThrowAsJavaScriptException();
|
|
469
514
|
WebTransportSession *session = nullptr;
|
|
470
515
|
if (lobj.Has("session") && !(lobj).Get("session").IsEmpty())
|
|
471
516
|
{
|
|
@@ -487,6 +532,7 @@ namespace quic
|
|
|
487
532
|
|
|
488
533
|
Http3ServerBackend::WebTransportRespPromisePtr *prom = promise.Data();
|
|
489
534
|
Napi::Reference<Napi::Value> *headerValue = nullptr;
|
|
535
|
+
Napi::Reference<Napi::Value> *userDataValue = nullptr;
|
|
490
536
|
if (status == 200)
|
|
491
537
|
{
|
|
492
538
|
|
|
@@ -498,7 +544,14 @@ namespace quic
|
|
|
498
544
|
headerValue = new Napi::Reference<Napi::Value>(Env(), ref);
|
|
499
545
|
}
|
|
500
546
|
else
|
|
501
|
-
return Napi::Error::New(Env(), "No
|
|
547
|
+
return Napi::Error::New(Env(), "No header passed for finishSessionRequest").ThrowAsJavaScriptException();
|
|
548
|
+
if (lobj.Has("userData") && !(lobj).Get("userData").IsEmpty())
|
|
549
|
+
{
|
|
550
|
+
napi_ref ref;
|
|
551
|
+
napi_status status = napi_create_reference(Env(), lobj.Get("userData"), 1, &ref);
|
|
552
|
+
NAPI_THROW_IF_FAILED(Env(), status, Reference<Napi::Value>());
|
|
553
|
+
userDataValue = new Napi::Reference<Napi::Value>(Env(), ref);
|
|
554
|
+
}
|
|
502
555
|
}
|
|
503
556
|
if (status != 200)
|
|
504
557
|
{
|
|
@@ -514,7 +567,7 @@ namespace quic
|
|
|
514
567
|
wtsession->init(session);
|
|
515
568
|
response->visitor =
|
|
516
569
|
std::make_unique<Http3WTSession::Visitor>(wtsession);
|
|
517
|
-
processNewSession(static_cast<Http3WTSession *>(wtsession), path, headerValue);
|
|
570
|
+
processNewSession(static_cast<Http3WTSession *>(wtsession), path, headerValue, userDataValue);
|
|
518
571
|
(*prom)->resolve(std::move(response));
|
|
519
572
|
}
|
|
520
573
|
}
|
package/src/http3server.h
CHANGED
|
@@ -84,8 +84,8 @@ namespace quic
|
|
|
84
84
|
exports.Set("Http3WebTransportServer", tplsrv);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
void processNewSession(Http3WTSession *session, const std::string &path, Napi::Reference<Napi::Value> *header);
|
|
88
|
-
void processNewSessionRequest(WebTransportSession *session, const spdy::Http2HeaderBlock &reqheadcopy, WebTransportRespPromisePtr
|
|
87
|
+
void processNewSession(Http3WTSession *session, const std::string &path, Napi::Reference<Napi::Value> *header, Napi::Reference<Napi::Value> *userData);
|
|
88
|
+
void processNewSessionRequest(WebTransportSession *session, const spdy::Http2HeaderBlock &reqheadcopy, WebTransportRespPromisePtr promise);
|
|
89
89
|
|
|
90
90
|
protected:
|
|
91
91
|
std::unique_ptr<Http3Server> server_;
|
|
@@ -67,27 +67,28 @@ namespace quic
|
|
|
67
67
|
}
|
|
68
68
|
std::string path(path_it->second);
|
|
69
69
|
|
|
70
|
+
if (jshandlerequesthandler_)
|
|
71
|
+
{
|
|
72
|
+
// first step pass header block along, due to thread safety, we need to copy
|
|
73
|
+
// not necessary anymore
|
|
74
|
+
|
|
75
|
+
// second step inform the js side
|
|
76
|
+
server_->getJS()->processNewSessionRequest(session, request_headers, promise);
|
|
77
|
+
return promise;
|
|
78
|
+
}
|
|
79
|
+
|
|
70
80
|
if (paths_.find(path) != paths_.end())
|
|
71
|
-
{ // to do handle our web transport paths
|
|
81
|
+
{ // to do handle our web transport paths, if no handler is present
|
|
72
82
|
std::unique_ptr<WebTransportResponse> response = std::make_unique<WebTransportResponse>();
|
|
73
83
|
Http3WTSession *wtsession = new Http3WTSession();
|
|
74
84
|
wtsession->init(session);
|
|
75
85
|
response->response_headers[":status"] = "200";
|
|
76
86
|
response->visitor =
|
|
77
87
|
std::make_unique<Http3WTSession::Visitor>(wtsession);
|
|
78
|
-
server_->getJS()->processNewSession(static_cast<Http3WTSession *>(wtsession), path, nullptr);
|
|
88
|
+
server_->getJS()->processNewSession(static_cast<Http3WTSession *>(wtsession), path, nullptr, nullptr);
|
|
79
89
|
promise->resolve(std::move(response));
|
|
80
90
|
return promise;
|
|
81
91
|
}
|
|
82
|
-
else if (jshandlerequesthandler_)
|
|
83
|
-
{
|
|
84
|
-
// first step pass header block along, due to thread safety, we need to copy
|
|
85
|
-
// not necessary anymore
|
|
86
|
-
|
|
87
|
-
// second step inform the js side
|
|
88
|
-
server_->getJS()->processNewSessionRequest(session, request_headers, &promise);
|
|
89
|
-
return promise;
|
|
90
|
-
}
|
|
91
92
|
|
|
92
93
|
std::unique_ptr<WebTransportResponse> response = std::make_unique<WebTransportResponse>();
|
|
93
94
|
response->response_headers[":status"] = "404";
|
|
@@ -83,34 +83,46 @@ namespace quic
|
|
|
83
83
|
void Http3WTStream::doCanRead()
|
|
84
84
|
{
|
|
85
85
|
// if (pause_reading_) return ; // back pressure folks!
|
|
86
|
+
WebTransportStream::PeekResult pr;
|
|
87
|
+
pr = stream_->PeekNextReadableRegion();
|
|
88
|
+
|
|
89
|
+
if (pr.fin_next && pr.peeked_data.size() == 0) {
|
|
90
|
+
bool fin = stream_->SkipBytes(0);
|
|
91
|
+
if (fin) {
|
|
92
|
+
getJS()->signalFinOnly();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
86
96
|
|
|
87
97
|
if (pause_reading_ && !drain_reads_)
|
|
88
98
|
{
|
|
89
99
|
can_read_pending_ = true;
|
|
90
100
|
return; // back pressure folks!
|
|
91
101
|
}
|
|
92
|
-
size_t readable = stream_->ReadableBytes();
|
|
93
102
|
bool read = false;
|
|
94
|
-
while (
|
|
103
|
+
while (!pr.peeked_data.empty())
|
|
95
104
|
{
|
|
96
105
|
Http3WTStreamJS::StreamReadBuffer rbuf(js_);
|
|
97
|
-
rbuf.getBuffer(
|
|
106
|
+
rbuf.getBuffer(stream_->ReadableBytes());
|
|
98
107
|
|
|
99
108
|
size_t remainSize = rbuf.bufferSize();
|
|
100
109
|
uint32_t writepos = 0;
|
|
101
110
|
|
|
102
|
-
while (
|
|
103
|
-
size_t len = remainSize;
|
|
104
|
-
|
|
105
|
-
|
|
111
|
+
while (!pr.peeked_data.empty() && remainSize > 0) {
|
|
112
|
+
size_t len = std::min(remainSize, pr.peeked_data.size());
|
|
113
|
+
if (len > 0) memcpy(((char *)rbuf.bufferData()) + writepos,pr.peeked_data.data(), len);
|
|
114
|
+
bool fin = stream_->SkipBytes(len);
|
|
106
115
|
QUIC_DVLOG(1) << "Attempted reading on WebTransport stream "
|
|
107
|
-
<< ", bytes read: " <<
|
|
108
|
-
writepos +=
|
|
109
|
-
remainSize -=
|
|
110
|
-
|
|
111
|
-
if (
|
|
116
|
+
<< ", bytes read: " << len;
|
|
117
|
+
writepos += len;
|
|
118
|
+
remainSize -= len;
|
|
119
|
+
pr = stream_->PeekNextReadableRegion();
|
|
120
|
+
if (fin) {
|
|
121
|
+
rbuf.setFin();
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
112
124
|
}
|
|
113
|
-
rbuf.commitBuffer(writepos,
|
|
125
|
+
rbuf.commitBuffer(writepos, pr.has_data());
|
|
114
126
|
}
|
|
115
127
|
}
|
|
116
128
|
|
|
@@ -142,8 +154,10 @@ namespace quic
|
|
|
142
154
|
if (send_fin_)
|
|
143
155
|
{
|
|
144
156
|
bool success = stream_->SendFin();
|
|
145
|
-
if (success)
|
|
157
|
+
if (success) {
|
|
146
158
|
fin_was_sent_ = true;
|
|
159
|
+
getJS()->processStreamNetworkFinish(NetworkTask::streamFinal);
|
|
160
|
+
}
|
|
147
161
|
}
|
|
148
162
|
}
|
|
149
163
|
|
|
@@ -165,6 +179,17 @@ namespace quic
|
|
|
165
179
|
}
|
|
166
180
|
}
|
|
167
181
|
|
|
182
|
+
|
|
183
|
+
void Http3WTStreamJS::signalFinOnly() {
|
|
184
|
+
Napi::HandleScope scope(Env());
|
|
185
|
+
Napi::Object retObj = Napi::Object::New(Env());
|
|
186
|
+
Napi::Object objVal = Value().Get("jsobj").As<Napi::Object>();
|
|
187
|
+
retObj.Set("fin", true);
|
|
188
|
+
Napi::Value bufferVal = objVal.Get("commitReadBuffer").As<Napi::Function>().Call(objVal, {retObj});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
168
193
|
void Http3WTStreamJS::processStreamNetworkFinish(NetworkTask task)
|
|
169
194
|
{
|
|
170
195
|
Napi::HandleScope scope(Env());
|
|
@@ -317,6 +317,7 @@ namespace quic
|
|
|
317
317
|
void processStreamWrite(Napi::ObjectReference *bufferhandle, bool success);
|
|
318
318
|
void processStreamNetworkFinish(NetworkTask task);
|
|
319
319
|
void processStreamRecvSignal(WebTransportStreamError error_code, NetworkTask task);
|
|
320
|
+
void signalFinOnly();
|
|
320
321
|
};
|
|
321
322
|
}
|
|
322
323
|
|
package/src/librarymain.cc
CHANGED
|
@@ -38,7 +38,7 @@ namespace quic
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
quiche_cmd_line.push_back(std::string("-v"));
|
|
41
|
-
if (lobj.Has("quicheLogVerbose") && lobj.Get("quicheLogVerbose").
|
|
41
|
+
if (lobj.Has("quicheLogVerbose") && lobj.Get("quicheLogVerbose").IsNumber())
|
|
42
42
|
{
|
|
43
43
|
Napi::Value verboseValue = (lobj).Get("quicheLogVerbose");
|
|
44
44
|
quiche_cmd_line.push_back(verboseValue.ToString().Utf8Value());
|
package/src/napialarmfactory.h
CHANGED
|
@@ -134,10 +134,17 @@ namespace quic
|
|
|
134
134
|
alarmref_.Unref();
|
|
135
135
|
timerset_ = false;
|
|
136
136
|
}
|
|
137
|
+
auto val = Napi::Value::From(alarmjs_->Env(), timedelay);
|
|
138
|
+
// Workaround for problem on windows plattform
|
|
139
|
+
if (val.ToNumber().DoubleValue() != timedelay) {
|
|
140
|
+
// printf("val %lg %lg\n", val.ToNumber().DoubleValue(), timedelay);
|
|
141
|
+
val = Napi::Value::From(alarmjs_->Env(), timedelay);
|
|
142
|
+
// printf("val2 %lg %lg\n", val.ToNumber().DoubleValue(), timedelay);
|
|
143
|
+
}
|
|
137
144
|
|
|
138
145
|
Napi::Value timeoutobj = NapiAlarmJS::FAILSsetTimeoutAlarm_.Call({
|
|
139
146
|
alarmjs_->Value().As<Napi::Object>(),
|
|
140
|
-
|
|
147
|
+
val,
|
|
141
148
|
});
|
|
142
149
|
alarmref_ = Napi::Reference<Napi::Object>::New(timeoutobj.As<Napi::Object>(), 1);
|
|
143
150
|
timerset_ = true;
|