@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.
Files changed (90) hide show
  1. package/CMakeLists.txt +110 -73
  2. package/build.js +32 -8
  3. package/dist/lib/client.d.ts +74 -0
  4. package/dist/lib/client.d.ts.map +1 -0
  5. package/dist/lib/dom.d.ts +70 -0
  6. package/dist/lib/dom.d.ts.map +1 -0
  7. package/dist/lib/event-loop.d.ts +26 -0
  8. package/dist/lib/event-loop.d.ts.map +1 -0
  9. package/dist/lib/index.d.ts +79 -0
  10. package/dist/lib/index.d.ts.map +1 -0
  11. package/dist/lib/native.d.ts +2 -0
  12. package/dist/lib/native.d.ts.map +1 -0
  13. package/dist/lib/server.d.ts +75 -0
  14. package/dist/lib/server.d.ts.map +1 -0
  15. package/dist/lib/session.d.ts +221 -0
  16. package/dist/lib/session.d.ts.map +1 -0
  17. package/dist/lib/stream.d.ts +116 -0
  18. package/dist/lib/stream.d.ts.map +1 -0
  19. package/dist/lib/transport.d.ts +25 -0
  20. package/dist/lib/transport.d.ts.map +1 -0
  21. package/dist/lib/types.d.ts +157 -0
  22. package/dist/lib/types.d.ts.map +1 -0
  23. package/dist/lib/utils.d.ts +6 -0
  24. package/dist/lib/utils.d.ts.map +1 -0
  25. package/dist/lib/webtransport.d.ts +35 -0
  26. package/dist/lib/webtransport.d.ts.map +1 -0
  27. package/dist/test/bidirectional-streams.spec.d.ts +5 -0
  28. package/dist/test/bidirectional-streams.spec.d.ts.map +1 -0
  29. package/dist/test/datagrams.spec.d.ts +5 -0
  30. package/dist/test/datagrams.spec.d.ts.map +1 -0
  31. package/dist/test/echoclient.d.ts +2 -0
  32. package/dist/test/echoclient.d.ts.map +1 -0
  33. package/dist/test/echoserver.d.ts +2 -0
  34. package/dist/test/echoserver.d.ts.map +1 -0
  35. package/dist/test/event-loop.spec.d.ts +2 -0
  36. package/dist/test/event-loop.spec.d.ts.map +1 -0
  37. package/dist/test/fixtures/certificate.d.ts +21 -0
  38. package/dist/test/fixtures/certificate.d.ts.map +1 -0
  39. package/dist/test/fixtures/chai.d.ts +2 -0
  40. package/dist/test/fixtures/chai.d.ts.map +1 -0
  41. package/dist/test/fixtures/read-stream.d.ts +10 -0
  42. package/dist/test/fixtures/read-stream.d.ts.map +1 -0
  43. package/dist/test/fixtures/reader-value.d.ts +7 -0
  44. package/dist/test/fixtures/reader-value.d.ts.map +1 -0
  45. package/dist/test/fixtures/server.d.ts +10 -0
  46. package/dist/test/fixtures/server.d.ts.map +1 -0
  47. package/dist/test/fixtures/write-stream.d.ts +10 -0
  48. package/dist/test/fixtures/write-stream.d.ts.map +1 -0
  49. package/dist/test/test.d.ts +2 -0
  50. package/dist/test/test.d.ts.map +1 -0
  51. package/dist/test/testsuite.d.ts +25 -0
  52. package/dist/test/testsuite.d.ts.map +1 -0
  53. package/dist/test/unidirectional-streams.spec.d.ts +5 -0
  54. package/dist/test/unidirectional-streams.spec.d.ts.map +1 -0
  55. package/lib/client.js +163 -0
  56. package/lib/dom.ts +95 -0
  57. package/lib/event-loop.js +79 -0
  58. package/lib/index.js +33 -0
  59. package/lib/native.js +25 -0
  60. package/lib/server.js +165 -0
  61. package/lib/session.js +422 -0
  62. package/lib/stream.js +325 -0
  63. package/lib/transport.js +42 -0
  64. package/lib/types.ts +181 -0
  65. package/lib/utils.js +22 -0
  66. package/lib/webtransport.js +114 -0
  67. package/package.json +18 -6
  68. package/readme.md +28 -5
  69. package/src/http3client.h +0 -1
  70. package/src/http3eventloop.cc +52 -0
  71. package/src/http3eventloop.h +22 -1
  72. package/src/http3server.cc +4 -1
  73. package/src/http3server.h +8 -0
  74. package/src/http3serversession.h +1 -1
  75. package/test/bidirectional-streams.spec.js +138 -0
  76. package/test/datagrams.spec.js +132 -0
  77. package/test/echoclient.js +10 -6
  78. package/test/echoserver.js +6 -8
  79. package/test/event-loop.spec.js +24 -0
  80. package/test/{certificate.js → fixtures/certificate.js} +31 -15
  81. package/test/fixtures/chai.js +6 -0
  82. package/test/fixtures/read-stream.js +36 -0
  83. package/test/fixtures/reader-value.js +24 -0
  84. package/test/fixtures/server.js +58 -0
  85. package/test/fixtures/write-stream.js +17 -0
  86. package/test/test.js +29 -3
  87. package/test/testsuite.js +22 -0
  88. package/test/unidirectional-streams.spec.js +128 -0
  89. package/tsconfig.json +40 -0
  90. 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,5 @@
1
+ /**
2
+ * <T>
3
+ */
4
+ export type Deferred<T> = import('../lib/types').Deferred<T>;
5
+ //# sourceMappingURL=bidirectional-streams.spec.d.ts.map
@@ -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,5 @@
1
+ /**
2
+ * <T>
3
+ */
4
+ export type Deferred<T> = import('../lib/types').Deferred<T>;
5
+ //# sourceMappingURL=datagrams.spec.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=echoclient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"echoclient.d.ts","sourceRoot":"","sources":["../../test/echoclient.js"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=echoserver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"echoserver.d.ts","sourceRoot":"","sources":["../../test/echoserver.js"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=event-loop.spec.d.ts.map
@@ -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,2 @@
1
+ export const expect: Chai.ExpectStatic;
2
+ //# sourceMappingURL=chai.d.ts.map
@@ -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,7 @@
1
+ /**
2
+ * @template T
3
+ * @param {ReadableStream<T>} readableStream
4
+ * @returns {Promise<T>}
5
+ */
6
+ export function getReaderValue<T>(readableStream: ReadableStream<T>): Promise<T>;
7
+ //# sourceMappingURL=reader-value.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test.d.ts.map
@@ -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,5 @@
1
+ /**
2
+ * <T>
3
+ */
4
+ export type Deferred<T> = import('../lib/types').Deferred<T>;
5
+ //# sourceMappingURL=unidirectional-streams.spec.d.ts.map
@@ -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)