@fails-components/webtransport 0.0.9 → 0.1.0-macarmbuild.6
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 +110 -73
- package/build.js +32 -8
- package/dist/lib/client.d.ts +74 -0
- package/dist/lib/client.d.ts.map +1 -0
- package/dist/lib/dom.d.ts +70 -0
- package/dist/lib/dom.d.ts.map +1 -0
- package/dist/lib/event-loop.d.ts +26 -0
- package/dist/lib/event-loop.d.ts.map +1 -0
- package/dist/lib/index.d.ts +79 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/native.d.ts +2 -0
- package/dist/lib/native.d.ts.map +1 -0
- package/dist/lib/server.d.ts +75 -0
- package/dist/lib/server.d.ts.map +1 -0
- package/dist/lib/session.d.ts +221 -0
- package/dist/lib/session.d.ts.map +1 -0
- package/dist/lib/stream.d.ts +116 -0
- package/dist/lib/stream.d.ts.map +1 -0
- package/dist/lib/transport.d.ts +25 -0
- package/dist/lib/transport.d.ts.map +1 -0
- package/dist/lib/types.d.ts +157 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/utils.d.ts +6 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/webtransport.d.ts +35 -0
- package/dist/lib/webtransport.d.ts.map +1 -0
- package/dist/test/bidirectional-streams.spec.d.ts +5 -0
- package/dist/test/bidirectional-streams.spec.d.ts.map +1 -0
- package/dist/test/datagrams.spec.d.ts +5 -0
- package/dist/test/datagrams.spec.d.ts.map +1 -0
- package/dist/test/echoclient.d.ts +2 -0
- package/dist/test/echoclient.d.ts.map +1 -0
- package/dist/test/echoserver.d.ts +2 -0
- package/dist/test/echoserver.d.ts.map +1 -0
- package/dist/test/event-loop.spec.d.ts +2 -0
- package/dist/test/event-loop.spec.d.ts.map +1 -0
- package/dist/test/fixtures/certificate.d.ts +21 -0
- package/dist/test/fixtures/certificate.d.ts.map +1 -0
- package/dist/test/fixtures/chai.d.ts +2 -0
- package/dist/test/fixtures/chai.d.ts.map +1 -0
- package/dist/test/fixtures/read-stream.d.ts +10 -0
- package/dist/test/fixtures/read-stream.d.ts.map +1 -0
- package/dist/test/fixtures/reader-value.d.ts +7 -0
- package/dist/test/fixtures/reader-value.d.ts.map +1 -0
- package/dist/test/fixtures/server.d.ts +10 -0
- package/dist/test/fixtures/server.d.ts.map +1 -0
- package/dist/test/fixtures/write-stream.d.ts +10 -0
- package/dist/test/fixtures/write-stream.d.ts.map +1 -0
- package/dist/test/test.d.ts +2 -0
- package/dist/test/test.d.ts.map +1 -0
- package/dist/test/testsuite.d.ts +25 -0
- package/dist/test/testsuite.d.ts.map +1 -0
- package/dist/test/unidirectional-streams.spec.d.ts +5 -0
- package/dist/test/unidirectional-streams.spec.d.ts.map +1 -0
- package/lib/client.js +163 -0
- package/lib/dom.ts +95 -0
- package/lib/event-loop.js +79 -0
- package/lib/index.js +33 -0
- package/lib/native.js +25 -0
- package/lib/server.js +165 -0
- package/lib/session.js +422 -0
- package/lib/stream.js +325 -0
- package/lib/transport.js +42 -0
- package/lib/types.ts +181 -0
- package/lib/utils.js +22 -0
- package/lib/webtransport.js +114 -0
- package/package.json +18 -6
- package/readme.md +28 -5
- package/src/http3client.h +0 -1
- package/src/http3eventloop.cc +52 -0
- package/src/http3eventloop.h +22 -1
- package/src/http3server.cc +4 -1
- package/src/http3server.h +8 -0
- package/src/http3serversession.h +1 -1
- package/test/bidirectional-streams.spec.js +138 -0
- package/test/datagrams.spec.js +132 -0
- package/test/echoclient.js +10 -6
- package/test/echoserver.js +6 -8
- package/test/event-loop.spec.js +24 -0
- package/test/{certificate.js → fixtures/certificate.js} +31 -15
- package/test/fixtures/chai.js +6 -0
- package/test/fixtures/read-stream.js +36 -0
- package/test/fixtures/reader-value.js +24 -0
- package/test/fixtures/server.js +58 -0
- package/test/fixtures/write-stream.js +17 -0
- package/test/test.js +29 -3
- package/test/testsuite.js +22 -0
- package/test/unidirectional-streams.spec.js +128 -0
- package/tsconfig.json +40 -0
- package/src/webtransport.js +0 -870
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webtransport.d.ts","sourceRoot":"","sources":["../../lib/webtransport.js"],"names":[],"mappings":"AAMA;;;;GAIG;AAEH;;;;GAIG;AACH;IACE;;;OAGG;IACH,iBAHW,MAAM,0DAyDhB;IAlCC,qBAA6B;IAC7B,uDAA+B;IAE/B,4DAAqC;IAErC,8DAA8D;IAC9D,8BADW,eAAe,+BAA+B,CAAC,CACiB;IAE3E,wDAAwD;IACxD,+BADW,eAAe,yBAAyB,CAAC,CAEV;IA0B5C;;OAEG;IACH,2EASC;IAED,sFASC;IAED,8EASC;CACF;oCA1GY,OAAO,OAAO,EAAE,qBAAqB;8CACrC,OAAO,OAAO,EAAE,+BAA+B;wCAC/C,OAAO,OAAO,EAAE,yBAAyB;oCAIzC,OAAO,OAAO,EAAE,YAAY"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bidirectional-streams.spec.d.ts","sourceRoot":"","sources":["../../test/bidirectional-streams.spec.js"],"names":[],"mappings":";;;0BAYa,OAAO,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datagrams.spec.d.ts","sourceRoot":"","sources":["../../test/datagrams.spec.js"],"names":[],"mappings":";;;0BAYa,OAAO,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"echoclient.d.ts","sourceRoot":"","sources":["../../test/echoclient.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"echoserver.d.ts","sourceRoot":"","sources":["../../test/echoserver.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-loop.spec.d.ts","sourceRoot":"","sources":["../../test/event-loop.spec.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} Certificate
|
|
3
|
+
* @property {string} public
|
|
4
|
+
* @property {string} private
|
|
5
|
+
* @property {string} cert
|
|
6
|
+
* @property {Uint8Array} hash
|
|
7
|
+
* @property {string} fingerprint
|
|
8
|
+
*
|
|
9
|
+
* @param {*} attrs
|
|
10
|
+
* @param {*} options
|
|
11
|
+
* @returns {Promise<Certificate | null>}
|
|
12
|
+
*/
|
|
13
|
+
export function generateWebTransportCertificate(attrs: any, options: any): Promise<Certificate | null>;
|
|
14
|
+
export type Certificate = {
|
|
15
|
+
public: string;
|
|
16
|
+
private: string;
|
|
17
|
+
cert: string;
|
|
18
|
+
hash: Uint8Array;
|
|
19
|
+
fingerprint: string;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=certificate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certificate.d.ts","sourceRoot":"","sources":["../../../test/fixtures/certificate.js"],"names":[],"mappings":"AAgVA;;;;;;;;;;;GAWG;AACH,2EAFa,QAAQ,WAAW,GAAG,IAAI,CAAC,CA8GvC;;YAtHa,MAAM;aACN,MAAM;UACN,MAAM;UACN,UAAU;iBACV,MAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chai.d.ts","sourceRoot":"","sources":["../../../test/fixtures/chai.js"],"names":[],"mappings":"AAKA,uCAAiC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read a stream contents to the end and return it
|
|
3
|
+
*
|
|
4
|
+
* @template T
|
|
5
|
+
* @param {ReadableStream<T>} readable
|
|
6
|
+
* @param {number} [expected]
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
export function readStream<T>(readable: ReadableStream<T>, expected?: number | undefined): Promise<T[]>;
|
|
10
|
+
//# sourceMappingURL=read-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-stream.d.ts","sourceRoot":"","sources":["../../../test/fixtures/read-stream.js"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wGA2BC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader-value.d.ts","sourceRoot":"","sources":["../../../test/fixtures/reader-value.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,iFAkBC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function createServer(): Promise<{
|
|
2
|
+
server: Http3Server;
|
|
3
|
+
certificate: import("./certificate.js").Certificate;
|
|
4
|
+
}>;
|
|
5
|
+
/**
|
|
6
|
+
* @param {import('../../lib/server.js').Http3Server} server
|
|
7
|
+
* @param {string} path
|
|
8
|
+
*/
|
|
9
|
+
export function getServerSession(server: import('../../lib/server.js').Http3Server, path: string): Promise<import("../../lib/types.js").WebTransportSession>;
|
|
10
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../test/fixtures/server.js"],"names":[],"mappings":"AAGA;;;GA6BC;AAED;;;GAGG;AACH,yCAHW,OAAO,qBAAqB,EAAE,WAAW,QACzC,MAAM,6DAqBhB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write contents to a stream and close it
|
|
3
|
+
*
|
|
4
|
+
* @template T
|
|
5
|
+
* @param {WritableStream<T>} writable
|
|
6
|
+
* @param {T[]} input
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
export function writeStream<T>(writable: WritableStream<T>, input: T[]): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=write-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-stream.d.ts","sourceRoot":"","sources":["../../../test/fixtures/write-stream.js"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,uFAQC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../test/test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {import('../lib/dom').WebTransport} session
|
|
3
|
+
*/
|
|
4
|
+
export function incomingBidirectionalEchoTest(session: import('../lib/dom').WebTransport): Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* @param {import('../lib/dom').WebTransport} session
|
|
7
|
+
*/
|
|
8
|
+
export function outgoingBidirectionalEchoTest(session: import('../lib/dom').WebTransport): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* @param {import('../lib/dom').WebTransport} session
|
|
11
|
+
*/
|
|
12
|
+
export function unidirectionalEchoTest(session: import('../lib/dom').WebTransport): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* @param {import('../lib/dom').WebTransport} session
|
|
15
|
+
*/
|
|
16
|
+
export function datagramEchoTest(session: import('../lib/dom').WebTransport): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* @param {import('../lib').Http3Server} server
|
|
19
|
+
*/
|
|
20
|
+
export function runEchoServer(server: import('../lib').Http3Server): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* @param {import('../lib/dom').WebTransport} transport
|
|
23
|
+
*/
|
|
24
|
+
export function echoTestsConnection(transport: import('../lib/dom').WebTransport): Promise<void>;
|
|
25
|
+
//# sourceMappingURL=testsuite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testsuite.d.ts","sourceRoot":"","sources":["../../test/testsuite.js"],"names":[],"mappings":"AAIA;;GAEG;AACH,uDAFW,OAAO,YAAY,EAAE,YAAY,iBAsB3C;AAED;;GAEG;AACH,uDAFW,OAAO,YAAY,EAAE,YAAY,iBAS3C;AAED;;GAEG;AACH,gDAFW,OAAO,YAAY,EAAE,YAAY,iBAuB3C;AAED;;GAEG;AACH,0CAFW,OAAO,YAAY,EAAE,YAAY,iBAQ3C;AAED;;GAEG;AACH,sCAFW,OAAO,QAAQ,EAAE,WAAW,iBAmCtC;AAcD;;GAEG;AACH,+CAFW,OAAO,YAAY,EAAE,YAAY,iBAqM3C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unidirectional-streams.spec.d.ts","sourceRoot":"","sources":["../../test/unidirectional-streams.spec.js"],"names":[],"mappings":";;;0BAYa,OAAO,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC"}
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { Http3WebTransport } from './transport.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import('./session').Http3WTSession} Http3WTSession
|
|
5
|
+
*
|
|
6
|
+
* Http3Client events
|
|
7
|
+
* @typedef {import('./types').Http3ClientEventHandler} Http3ClientEventHandler
|
|
8
|
+
* @typedef {import('./types').ClientConnectedEvent} ClientConnectedEvent
|
|
9
|
+
* @typedef {import('./types').ClientWebtransportSupportEvent} ClientWebtransportSupportEvent
|
|
10
|
+
* @typedef {import('./types').Http3WTSessionVisitorEvent} Http3WTSessionVisitorEvent
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @implements {Http3ClientEventHandler}
|
|
15
|
+
*/
|
|
16
|
+
export class Http3Client extends Http3WebTransport {
|
|
17
|
+
/**
|
|
18
|
+
* @param {*} args
|
|
19
|
+
*/
|
|
20
|
+
constructor(args) {
|
|
21
|
+
super(args, 'client')
|
|
22
|
+
|
|
23
|
+
/** @type {{ resolve: (value?: any) => void, reject: (err?: Error) => void} | null | undefined} */
|
|
24
|
+
this.sessionProm = null
|
|
25
|
+
|
|
26
|
+
/** @type {Promise<void> | undefined} */
|
|
27
|
+
this.sessionobj = new Promise((resolve, reject) => {
|
|
28
|
+
this.sessionProm = { resolve, reject }
|
|
29
|
+
}).catch(() => {}) // add default handler if no one cares
|
|
30
|
+
/** @type {Http3WTSession | null | undefined} */
|
|
31
|
+
this.sessionobjint = null
|
|
32
|
+
this.closeHookSession = this.closeHookSession.bind(this)
|
|
33
|
+
|
|
34
|
+
/** @type {{ resolve: (value?: any) => void, reject: (err?: Error) => void} | null | undefined} */
|
|
35
|
+
this.webtransportProm = null
|
|
36
|
+
/** @type {{ resolve: (value?: any) => void, reject: (err?: Error) => void} | null | undefined} */
|
|
37
|
+
this.quicconnectedProm = null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async handleConnection() {
|
|
41
|
+
this.quicconnected = new Promise((resolve, reject) => {
|
|
42
|
+
this.quicconnectedProm = { resolve, reject }
|
|
43
|
+
})
|
|
44
|
+
this.webtransport = new Promise((resolve, reject) => {
|
|
45
|
+
this.webtransportProm = { resolve, reject }
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
setTimeout(() => {
|
|
50
|
+
if (this.quicconnectedProm) {
|
|
51
|
+
this.quicconnectedProm.reject(new Error('Timeout client connection'))
|
|
52
|
+
delete this.quicconnectedProm
|
|
53
|
+
}
|
|
54
|
+
}, 8000)
|
|
55
|
+
await this.quicconnected
|
|
56
|
+
// now create Webtransport session
|
|
57
|
+
setTimeout(() => {
|
|
58
|
+
if (this.webtransportProm) {
|
|
59
|
+
this.webtransportProm.reject(
|
|
60
|
+
new Error('Timeout webtransport support')
|
|
61
|
+
)
|
|
62
|
+
delete this.webtransportProm
|
|
63
|
+
}
|
|
64
|
+
}, 2000)
|
|
65
|
+
} catch (error) {
|
|
66
|
+
throw new Error('Cl:' + error)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {Http3WTSession} sessionobj
|
|
72
|
+
* @param {string} path
|
|
73
|
+
* @returns
|
|
74
|
+
*/
|
|
75
|
+
async createWTSession(sessionobj, path) {
|
|
76
|
+
// TODO
|
|
77
|
+
try {
|
|
78
|
+
await this.webtransport // wait for webtransport support
|
|
79
|
+
// ok now we open the session
|
|
80
|
+
this.sessionobjint = sessionobj
|
|
81
|
+
this.transportInt.openWTSession(path)
|
|
82
|
+
console.log('wait for session')
|
|
83
|
+
// we wait for a new session
|
|
84
|
+
const sessobj = await this.sessionobj
|
|
85
|
+
|
|
86
|
+
delete this.sessionobj
|
|
87
|
+
|
|
88
|
+
return sessobj
|
|
89
|
+
} catch (error) {
|
|
90
|
+
throw new Error('createWTSession failed ' + error)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
closeHookSession() {
|
|
95
|
+
this.transportInt.closeClient()
|
|
96
|
+
this.stopped = true
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {ClientConnectedEvent} args
|
|
101
|
+
*/
|
|
102
|
+
onClientConnected(args) {
|
|
103
|
+
if (this.quicconnectedProm) {
|
|
104
|
+
if (args.success) this.quicconnectedProm.resolve()
|
|
105
|
+
else
|
|
106
|
+
this.quicconnectedProm.reject(
|
|
107
|
+
new Error('Connecting quic client failed')
|
|
108
|
+
)
|
|
109
|
+
delete this.quicconnectedProm
|
|
110
|
+
} else throw new Error('Client connected with no pending promise')
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @param {ClientWebtransportSupportEvent} args
|
|
115
|
+
*/
|
|
116
|
+
onClientWebTransportSupport(args) {
|
|
117
|
+
if (this.webtransportProm) {
|
|
118
|
+
this.webtransportProm.resolve()
|
|
119
|
+
delete this.webtransportProm
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param {Http3WTSessionVisitorEvent} args
|
|
125
|
+
*/
|
|
126
|
+
onHttp3WTSessionVisitor(args) {
|
|
127
|
+
// create Http3 Visitor
|
|
128
|
+
if (args.session && this.sessionProm && this.sessionobjint) {
|
|
129
|
+
this.sessionobjint.setSessionObj(args.session)
|
|
130
|
+
args.session.jsobj.closeHook = this.closeHookSession
|
|
131
|
+
delete this.sessionobjint
|
|
132
|
+
this.sessionProm.resolve(args.session)
|
|
133
|
+
delete this.sessionProm
|
|
134
|
+
} else {
|
|
135
|
+
throw new Error(
|
|
136
|
+
'Http3WTSessionVisitor no object session or nor sessionprom'
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @param {ClientConnectedEvent | ClientWebtransportSupportEvent | Http3WTSessionVisitorEvent} args
|
|
143
|
+
*/
|
|
144
|
+
customCallback(args) {
|
|
145
|
+
// console.log('incoming callback custom client', args)
|
|
146
|
+
if (args.purpose) {
|
|
147
|
+
switch (args.purpose) {
|
|
148
|
+
case 'ClientConnected':
|
|
149
|
+
this.onClientConnected(args)
|
|
150
|
+
break
|
|
151
|
+
case 'ClientWebtransportSupport':
|
|
152
|
+
this.onClientWebTransportSupport(args)
|
|
153
|
+
break
|
|
154
|
+
case 'Http3WTSessionVisitor':
|
|
155
|
+
this.onHttp3WTSessionVisitor(args)
|
|
156
|
+
break
|
|
157
|
+
default: {
|
|
158
|
+
throw new Error('unknown purpose')
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
package/lib/dom.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Types taken from https://www.w3.org/TR/webtransport
|
|
2
|
+
// These can be removed when they are added to the default typescript types
|
|
3
|
+
|
|
4
|
+
export interface WebTransportDatagramStats {
|
|
5
|
+
timestamp: number
|
|
6
|
+
expiredOutgoing: bigint
|
|
7
|
+
droppedIncoming: bigint
|
|
8
|
+
lostOutgoing: bigint
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface WebTransportStats {
|
|
12
|
+
timestamp: number
|
|
13
|
+
bytesSent: bigint
|
|
14
|
+
packetsSent: bigint
|
|
15
|
+
packetsLost: bigint
|
|
16
|
+
numOutgoingStreamsCreated: number
|
|
17
|
+
numIncomingStreamsCreated: number
|
|
18
|
+
bytesReceived: bigint
|
|
19
|
+
packetsReceived: bigint
|
|
20
|
+
smoothedRtt: number
|
|
21
|
+
rttVariation: number
|
|
22
|
+
minRtt: number
|
|
23
|
+
datagrams: WebTransportDatagramStats
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface WebTransportCloseInfo {
|
|
27
|
+
closeCode: number
|
|
28
|
+
reason: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface WebTransportDatagramDuplexStream {
|
|
32
|
+
readable: ReadableStream<Uint8Array>
|
|
33
|
+
writable: WritableStream<Uint8Array>
|
|
34
|
+
// readonly maxDatagramSize: number
|
|
35
|
+
// incomingMaxAge?: number
|
|
36
|
+
// outgoingMaxAge?: number
|
|
37
|
+
// incomingHighWaterMark: number
|
|
38
|
+
// outgoingHighWaterMark: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface WebTransportBidirectionalStream {
|
|
42
|
+
readonly readable: ReadableStream<Uint8Array>
|
|
43
|
+
readonly writable: WritableStream<Uint8Array>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface WebTransportSendStreamStats {
|
|
47
|
+
timestamp: number
|
|
48
|
+
bytesWritten: bigint
|
|
49
|
+
bytesSent: bigint
|
|
50
|
+
bytesAcknowledged: bigint
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface WebTransportSendStream extends WritableStream<Uint8Array> {
|
|
54
|
+
getStats: () => Promise<WebTransportSendStreamStats>
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface WebTransportReceiveStreamStats {
|
|
58
|
+
timestamp: number
|
|
59
|
+
bytesReceived: bigint
|
|
60
|
+
bytesRead: bigint
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface WebTransportReceiveStream extends ReadableStream<Uint8Array> {
|
|
64
|
+
getStats: () => Promise<WebTransportReceiveStreamStats>
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface WebTransportHash {
|
|
68
|
+
algorithm: string
|
|
69
|
+
value: BufferSource
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface WebTransportOptions {
|
|
73
|
+
allowPooling?: boolean
|
|
74
|
+
requireUnreliable?: boolean
|
|
75
|
+
serverCertificateHashes?: WebTransportHash[]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface WebTransport {
|
|
79
|
+
// getStats: () => Promise<WebTransportStats>
|
|
80
|
+
readonly ready: Promise<void>
|
|
81
|
+
// readonly reliability: WebTransportReliabilityMode
|
|
82
|
+
readonly closed: Promise<WebTransportCloseInfo>
|
|
83
|
+
close: (closeInfo?: WebTransportCloseInfo) => void
|
|
84
|
+
readonly datagrams: WebTransportDatagramDuplexStream
|
|
85
|
+
|
|
86
|
+
createBidirectionalStream: () => Promise<WebTransportBidirectionalStream>
|
|
87
|
+
/* a ReadableStream of WebTransportBidirectionalStream objects */
|
|
88
|
+
readonly incomingBidirectionalStreams: ReadableStream<WebTransportBidirectionalStream>
|
|
89
|
+
|
|
90
|
+
createUnidirectionalStream: () => Promise<WebTransportSendStream>
|
|
91
|
+
/* a ReadableStream of WebTransportReceiveStream objects */
|
|
92
|
+
readonly incomingUnidirectionalStreams: ReadableStream<WebTransportReceiveStream>
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export type WebTransportReliabilityMode = 'pending' | 'reliable-only' | 'supports-unreliable'
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Http3WebTransport } from './transport.js'
|
|
2
|
+
import { Http3WTStream } from './stream.js'
|
|
3
|
+
import { Http3WTSession } from './session.js'
|
|
4
|
+
import { wtrouter } from './native.js'
|
|
5
|
+
|
|
6
|
+
export class Http3EventLoop {
|
|
7
|
+
/** @type {Http3EventLoop | null} */
|
|
8
|
+
static globalLoop = null
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {*} [args]
|
|
12
|
+
*/
|
|
13
|
+
constructor(args) {
|
|
14
|
+
this.eventloopInt = new wtrouter.Http3EventLoop({
|
|
15
|
+
transportCallback: Http3WebTransport.transportCallback,
|
|
16
|
+
streamCallback: Http3WTStream.callback,
|
|
17
|
+
sessionCallback: Http3WTSession.callback,
|
|
18
|
+
eventloopCallback: Http3EventLoop.callback
|
|
19
|
+
})
|
|
20
|
+
this.eventloopInt.jsobj = this
|
|
21
|
+
|
|
22
|
+
this.refObjects = new Set()
|
|
23
|
+
this.loopGuardian = this.loopGuardian.bind(this)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
startEventLoop() {
|
|
27
|
+
console.log('start GlobalEventLoop')
|
|
28
|
+
this.eventloopInt.startEventLoop()
|
|
29
|
+
this.loopGuardianTimer = setInterval(this.loopGuardian, 5000)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
shutdownEventLoop() {
|
|
33
|
+
console.log('shutdown GlobalEventLoop')
|
|
34
|
+
Http3EventLoop.globalLoop = null
|
|
35
|
+
clearInterval(this.loopGuardianTimer)
|
|
36
|
+
this.eventloopInt.shutDownEventLoop()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
loopGuardian() {
|
|
40
|
+
for (const item of this.refObjects) {
|
|
41
|
+
if (typeof item.deref() === 'undefined' || item.deref()?.stopped)
|
|
42
|
+
this.refObjects.delete(item)
|
|
43
|
+
}
|
|
44
|
+
if (this.refObjects.size === 0) {
|
|
45
|
+
const now = Date.now()
|
|
46
|
+
if (!this.refObjectsEmptyTime) this.refObjectsEmptyTime = now
|
|
47
|
+
else if (now - this.refObjectsEmptyTime > 20 * 1000)
|
|
48
|
+
this.shutdownEventLoop()
|
|
49
|
+
} else if (this.refObjectsEmptyTime) delete this.refObjectsEmptyTime
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static callback() {
|
|
53
|
+
console.log('final eventloop callback called')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @returns {Http3EventLoop}
|
|
58
|
+
*/
|
|
59
|
+
static createGlobalEventLoop() {
|
|
60
|
+
if (!Http3EventLoop.globalLoop) {
|
|
61
|
+
Http3EventLoop.globalLoop = new Http3EventLoop()
|
|
62
|
+
Http3EventLoop.globalLoop.startEventLoop()
|
|
63
|
+
console.log('createGlobalEventLoop')
|
|
64
|
+
}
|
|
65
|
+
return Http3EventLoop.globalLoop
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {any} object
|
|
70
|
+
* @returns {Http3EventLoop}
|
|
71
|
+
*/
|
|
72
|
+
static getGlobalEventLoop(object) {
|
|
73
|
+
if (!object) throw new Error('getGlobalEventLoop without reference object')
|
|
74
|
+
const loop =
|
|
75
|
+
Http3EventLoop.globalLoop ?? Http3EventLoop.createGlobalEventLoop()
|
|
76
|
+
loop.refObjects.add(new WeakRef(object))
|
|
77
|
+
return loop
|
|
78
|
+
}
|
|
79
|
+
}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* eslint-disable no-prototype-builtins */
|
|
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
|
+
import { Http3EventLoop } from './event-loop.js'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* // Spec
|
|
10
|
+
* @typedef {import('./dom').WebTransportDatagramStats} WebTransportDatagramStats
|
|
11
|
+
* @typedef {import('./dom').WebTransportStats} WebTransportStats
|
|
12
|
+
* @typedef {import('./dom').WebTransportCloseInfo} WebTransportCloseInfo
|
|
13
|
+
* @typedef {import('./dom').WebTransportDatagramDuplexStream} WebTransportDatagramDuplexStream
|
|
14
|
+
* @typedef {import('./dom').WebTransportBidirectionalStream} WebTransportBidirectionalStream
|
|
15
|
+
* @typedef {import('./dom').WebTransportSendStreamStats} WebTransportSendStreamStats
|
|
16
|
+
* @typedef {import('./dom').WebTransportSendStream} WebTransportSendStream
|
|
17
|
+
* @typedef {import('./dom').WebTransportReceiveStreamStats} WebTransportReceiveStreamStats
|
|
18
|
+
* @typedef {import('./dom').WebTransportReceiveStream} WebTransportReceiveStream
|
|
19
|
+
* @typedef {import('./dom').WebTransportHash} WebTransportHash
|
|
20
|
+
* @typedef {import('./dom').WebTransportOptions} WebTransportOptions
|
|
21
|
+
* @typedef {import('./dom').WebTransportReliabilityMode} WebTransportReliabilityMode
|
|
22
|
+
*
|
|
23
|
+
* Public API
|
|
24
|
+
* @typedef {import('./types').WebTransportSession} WebTransportSession
|
|
25
|
+
* @typedef {import('./types').Http3ServerInit} Http3ServerInit
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export function testcheck() {
|
|
29
|
+
return !Http3EventLoop.globalLoop
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { Http3Server } from './server.js'
|
|
33
|
+
export { WebTransport } from './webtransport.js'
|
package/lib/native.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { existsSync } from 'fs'
|
|
2
|
+
import { createRequire } from 'module'
|
|
3
|
+
import * as path from 'path'
|
|
4
|
+
import * as url from 'url'
|
|
5
|
+
import { arch, platform } from 'node:process'
|
|
6
|
+
|
|
7
|
+
const binplatform = platform + '_' + arch
|
|
8
|
+
const require = createRequire(import.meta.url)
|
|
9
|
+
const dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
|
10
|
+
let buildpath = '../build_' + binplatform
|
|
11
|
+
|
|
12
|
+
if (!existsSync(path.join(dirname, buildpath))) buildpath = '../build' // use precompiled only if own compilation does not exist
|
|
13
|
+
|
|
14
|
+
let wtpath = buildpath + '/Release/webtransport.node'
|
|
15
|
+
|
|
16
|
+
if (
|
|
17
|
+
process.env.NODE_ENV !== 'production' &&
|
|
18
|
+
existsSync(path.join(dirname, buildpath + '/Debug/webtransport.node'))
|
|
19
|
+
) {
|
|
20
|
+
wtpath = buildpath + '/Debug/webtransport.node'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
console.log('load webtransport binary:', wtpath)
|
|
24
|
+
|
|
25
|
+
export const wtrouter = require(wtpath)
|