@fails-components/webtransport 0.1.7 → 0.2.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 -2
- package/build.js +4 -4
- package/dist/lib/session.d.ts +12 -2
- package/dist/lib/session.d.ts.map +1 -1
- package/dist/lib/stream.d.ts +9 -1
- package/dist/lib/stream.d.ts.map +1 -1
- package/dist/lib/types.d.ts +11 -2
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/test/bidirectional-streams.spec.d.ts.map +1 -1
- package/dist/test/datagrams.spec.d.ts.map +1 -1
- package/dist/test/fixtures/p-timeout.d.ts +8 -0
- package/dist/test/fixtures/p-timeout.d.ts.map +1 -0
- package/dist/test/fixtures/read-stream.d.ts.map +1 -1
- package/dist/test/unidirectional-streams.spec.d.ts.map +1 -1
- package/lib/session.js +20 -1
- package/lib/stream.js +115 -11
- package/lib/types.ts +12 -2
- package/package.json +4 -3
- package/platform/base/strings/utf_ostream_operators.h +5 -0
- package/src/http3clientsession.cc +51 -42
- package/src/http3clientsession.h +41 -37
- package/src/http3eventloop.cc +46 -13
- package/src/http3eventloop.h +8 -2
- package/src/http3server.cc +1 -1
- package/src/http3serversession.h +8 -7
- package/src/http3wtsessionvisitor.h +19 -0
- package/src/http3wtstreamvisitor.cc +35 -8
- package/src/http3wtstreamvisitor.h +81 -3
- package/test/bidirectional-streams.spec.js +15 -7
- package/test/datagrams.spec.js +30 -20
- package/test/fixtures/p-timeout.js +33 -0
- package/test/fixtures/read-stream.js +4 -1
- package/test/unidirectional-streams.spec.js +23 -15
|
@@ -7,6 +7,7 @@ import { expect } from './fixtures/chai.js'
|
|
|
7
7
|
import { readStream } from './fixtures/read-stream.js'
|
|
8
8
|
import { writeStream } from './fixtures/write-stream.js'
|
|
9
9
|
import { defer } from '../lib/utils.js'
|
|
10
|
+
import * as ui8 from 'uint8arrays'
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* @template T
|
|
@@ -60,6 +61,7 @@ describe('bidirectional streams', function () {
|
|
|
60
61
|
// server context - waits for the client to open a bidi stream and pipes it back to them
|
|
61
62
|
Promise.resolve().then(async () => {
|
|
62
63
|
const session = await getReaderValue(server.sessionStream(SERVER_PATH))
|
|
64
|
+
if (!session) throw new Error('Got no session')
|
|
63
65
|
const bidiStream = await getReaderValue(
|
|
64
66
|
session.incomingBidirectionalStreams
|
|
65
67
|
)
|
|
@@ -87,9 +89,9 @@ describe('bidirectional streams', function () {
|
|
|
87
89
|
const stream = await client.createBidirectionalStream()
|
|
88
90
|
await writeStream(stream.writable, input)
|
|
89
91
|
|
|
90
|
-
const output = await readStream(stream.readable)
|
|
91
|
-
expect(output).to.deep.equal(
|
|
92
|
-
input,
|
|
92
|
+
const output = await readStream(stream.readable, ui8.concat(input).length)
|
|
93
|
+
expect(ui8.concat(output)).to.deep.equal(
|
|
94
|
+
ui8.concat(input),
|
|
93
95
|
'Did not receive the same bytes we sent'
|
|
94
96
|
)
|
|
95
97
|
})
|
|
@@ -107,12 +109,14 @@ describe('bidirectional streams', function () {
|
|
|
107
109
|
// server context - waits for the client to connect, opens a bidi stream, sends some data and reads the response
|
|
108
110
|
Promise.resolve().then(async () => {
|
|
109
111
|
const session = await getReaderValue(server.sessionStream(SERVER_PATH))
|
|
112
|
+
if (!session) throw new Error('Got no session')
|
|
110
113
|
const stream = await session.createBidirectionalStream()
|
|
111
114
|
|
|
112
115
|
await writeStream(stream.writable, input)
|
|
113
116
|
|
|
114
|
-
const output = await readStream(stream.readable)
|
|
117
|
+
const output = await readStream(stream.readable, ui8.concat(input).length)
|
|
115
118
|
serverData.resolve(output)
|
|
119
|
+
await stream.readable.cancel() // cancel so that the client can progress
|
|
116
120
|
})
|
|
117
121
|
|
|
118
122
|
// client context - waits for the server to open a bidi stream then pipes it back to them
|
|
@@ -128,11 +132,15 @@ describe('bidirectional streams', function () {
|
|
|
128
132
|
|
|
129
133
|
const bidiStream = await getReaderValue(client.incomingBidirectionalStreams)
|
|
130
134
|
// redirect input to output
|
|
131
|
-
|
|
135
|
+
try {
|
|
136
|
+
await bidiStream.readable.pipeTo(bidiStream.writable)
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.log('Pipe to error (ignore)', error) // Actually all you can get is, that the fin is catched
|
|
139
|
+
}
|
|
132
140
|
|
|
133
141
|
const received = await serverData.promise
|
|
134
|
-
expect(received).to.deep.equal(
|
|
135
|
-
input,
|
|
142
|
+
expect(ui8.concat(received)).to.deep.equal(
|
|
143
|
+
ui8.concat(input),
|
|
136
144
|
'Did not receive the same bytes we sent'
|
|
137
145
|
)
|
|
138
146
|
})
|
package/test/datagrams.spec.js
CHANGED
|
@@ -6,7 +6,8 @@ import { WebTransport } from '../lib/index.js'
|
|
|
6
6
|
import { expect } from './fixtures/chai.js'
|
|
7
7
|
import { readStream } from './fixtures/read-stream.js'
|
|
8
8
|
import { writeStream } from './fixtures/write-stream.js'
|
|
9
|
-
import
|
|
9
|
+
import * as ui8 from 'uint8arrays'
|
|
10
|
+
import { pTimeout } from './fixtures/p-timeout.js'
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* @template T
|
|
@@ -80,7 +81,10 @@ describe('datagrams', function () {
|
|
|
80
81
|
|
|
81
82
|
await writeStream(client.datagrams.writable, input)
|
|
82
83
|
|
|
83
|
-
const output = await readStream(
|
|
84
|
+
const output = await readStream(
|
|
85
|
+
client.datagrams.readable,
|
|
86
|
+
ui8.concat(input).length
|
|
87
|
+
)
|
|
84
88
|
expect(output).to.deep.equal(
|
|
85
89
|
input,
|
|
86
90
|
'Did not receive the same bytes we sent'
|
|
@@ -89,25 +93,29 @@ describe('datagrams', function () {
|
|
|
89
93
|
|
|
90
94
|
it('receives datagrams from the server', async () => {
|
|
91
95
|
this.timeout(200)
|
|
92
|
-
/** @type {Deferred<Uint8Array[]>} */
|
|
93
|
-
const serverData = defer()
|
|
94
|
-
const input = [
|
|
95
|
-
Uint8Array.from([0, 1, 2, 3, 4]),
|
|
96
|
-
Uint8Array.from([5, 6, 7, 8, 9]),
|
|
97
|
-
Uint8Array.from([10, 11, 12, 13, 14])
|
|
98
|
-
]
|
|
99
96
|
|
|
100
97
|
// server context - waits for the client to connect, sends some datagrams and reads the response
|
|
101
98
|
Promise.resolve().then(async () => {
|
|
102
99
|
const session = await getReaderValue(server.sessionStream(SERVER_PATH))
|
|
103
100
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
let closed = false
|
|
102
|
+
const writer = session.datagrams.writable.getWriter()
|
|
103
|
+
Promise.resolve().then(async () => {
|
|
104
|
+
// eslint-disable-next-line no-unmodified-loop-condition
|
|
105
|
+
while (!closed) {
|
|
106
|
+
try {
|
|
107
|
+
await writer.ready
|
|
108
|
+
await writer.write(Uint8Array.from([0, 1, 2, 3, 4]))
|
|
109
|
+
await new Promise((resolve) => setTimeout(resolve, 1)) // do not flood everything
|
|
110
|
+
} catch {
|
|
111
|
+
// the session can be closed while we are writing
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
})
|
|
107
115
|
|
|
108
116
|
// have to close the session to end the client's datagram stream
|
|
109
|
-
session.
|
|
110
|
-
|
|
117
|
+
await session.closed
|
|
118
|
+
closed = true
|
|
111
119
|
})
|
|
112
120
|
|
|
113
121
|
// client context - pipes the server's datagrams back to them
|
|
@@ -121,13 +129,15 @@ describe('datagrams', function () {
|
|
|
121
129
|
})
|
|
122
130
|
await client.ready
|
|
123
131
|
|
|
124
|
-
//
|
|
125
|
-
|
|
132
|
+
// datagram transport is unreliable, at least one message should make it through
|
|
133
|
+
const expected = 1
|
|
126
134
|
|
|
127
|
-
const received = await
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
'Did not receive the same bytes we sent'
|
|
135
|
+
const received = await pTimeout(
|
|
136
|
+
readStream(client.datagrams.readable, expected),
|
|
137
|
+
1000
|
|
131
138
|
)
|
|
139
|
+
await client.close()
|
|
140
|
+
client = undefined
|
|
141
|
+
expect(received).to.have.lengthOf(expected)
|
|
132
142
|
})
|
|
133
143
|
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
class TimeoutError extends Error {
|
|
2
|
+
/**
|
|
3
|
+
* @param {string} message
|
|
4
|
+
*/
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message)
|
|
7
|
+
|
|
8
|
+
this.name = this[Symbol.toStringTag] = 'TimeoutError'
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @template T
|
|
14
|
+
* @param {Promise<T>} promise
|
|
15
|
+
* @param {number} timeout
|
|
16
|
+
* @returns {Promise<T>}
|
|
17
|
+
*/
|
|
18
|
+
export async function pTimeout(promise, timeout) {
|
|
19
|
+
let ref
|
|
20
|
+
|
|
21
|
+
const value = await Promise.race([
|
|
22
|
+
promise,
|
|
23
|
+
new Promise((resolve, reject) => {
|
|
24
|
+
ref = setTimeout(() => {
|
|
25
|
+
reject(new TimeoutError('timeout'))
|
|
26
|
+
}, timeout)
|
|
27
|
+
})
|
|
28
|
+
])
|
|
29
|
+
|
|
30
|
+
clearTimeout(ref)
|
|
31
|
+
|
|
32
|
+
return value
|
|
33
|
+
}
|
|
@@ -12,6 +12,7 @@ export async function readStream(readable, expected) {
|
|
|
12
12
|
try {
|
|
13
13
|
/** @type {T[]} */
|
|
14
14
|
const output = []
|
|
15
|
+
let outputlength = 0
|
|
15
16
|
|
|
16
17
|
while (true) {
|
|
17
18
|
const { done, value } = await reader.read()
|
|
@@ -21,10 +22,12 @@ export async function readStream(readable, expected) {
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
if (value != null) {
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
outputlength += value.length
|
|
24
27
|
output.push(value)
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
if (expected != null &&
|
|
30
|
+
if (expected != null && outputlength >= expected) {
|
|
28
31
|
break
|
|
29
32
|
}
|
|
30
33
|
}
|
|
@@ -7,6 +7,7 @@ import { expect } from 'chai'
|
|
|
7
7
|
import { readStream } from './fixtures/read-stream.js'
|
|
8
8
|
import { writeStream } from './fixtures/write-stream.js'
|
|
9
9
|
import { defer } from '../lib/utils.js'
|
|
10
|
+
import * as ui8 from 'uint8arrays'
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* @template T
|
|
@@ -56,13 +57,21 @@ describe('unidirectional streams', function () {
|
|
|
56
57
|
/** @type {Deferred<Uint8Array[]>} */
|
|
57
58
|
const serverData = defer()
|
|
58
59
|
|
|
60
|
+
const input = [
|
|
61
|
+
Uint8Array.from([0, 1, 2, 3, 4]),
|
|
62
|
+
Uint8Array.from([5, 6, 7, 8, 9]),
|
|
63
|
+
Uint8Array.from([10, 11, 12, 13, 14])
|
|
64
|
+
]
|
|
65
|
+
|
|
59
66
|
// server context - waits for the client to open a bidi stream and pipes it back to them
|
|
60
67
|
Promise.resolve().then(async () => {
|
|
61
68
|
const session = await getReaderValue(server.sessionStream(SERVER_PATH))
|
|
69
|
+
if (!session) throw new Error('no session')
|
|
62
70
|
const stream = await getReaderValue(session.incomingUnidirectionalStreams)
|
|
63
71
|
|
|
64
|
-
const output = await readStream(stream)
|
|
72
|
+
const output = await readStream(stream, ui8.concat(input).length)
|
|
65
73
|
serverData.resolve(output)
|
|
74
|
+
await stream.cancel() // cancel so that the client can progress
|
|
66
75
|
})
|
|
67
76
|
|
|
68
77
|
// client context - connects to the server, opens a bidi stream, sends some data and reads the response
|
|
@@ -76,18 +85,12 @@ describe('unidirectional streams', function () {
|
|
|
76
85
|
})
|
|
77
86
|
await client.ready
|
|
78
87
|
|
|
79
|
-
const input = [
|
|
80
|
-
Uint8Array.from([0, 1, 2, 3, 4]),
|
|
81
|
-
Uint8Array.from([5, 6, 7, 8, 9]),
|
|
82
|
-
Uint8Array.from([10, 11, 12, 13, 14])
|
|
83
|
-
]
|
|
84
|
-
|
|
85
88
|
const stream = await client.createUnidirectionalStream()
|
|
86
89
|
await writeStream(stream, input)
|
|
87
90
|
|
|
88
91
|
const received = await serverData.promise
|
|
89
|
-
expect(received).to.deep.equal(
|
|
90
|
-
input,
|
|
92
|
+
expect(ui8.concat(received)).to.deep.equal(
|
|
93
|
+
ui8.concat(input),
|
|
91
94
|
'Server did not receive the same bytes we sent'
|
|
92
95
|
)
|
|
93
96
|
})
|
|
@@ -103,6 +106,7 @@ describe('unidirectional streams', function () {
|
|
|
103
106
|
// server context - waits for the client to connect, opens a bidi stream, sends some data and reads the response
|
|
104
107
|
Promise.resolve().then(async () => {
|
|
105
108
|
const session = await getReaderValue(server.sessionStream(SERVER_PATH))
|
|
109
|
+
if (!session) throw new Error('no session')
|
|
106
110
|
const stream = await session.createUnidirectionalStream()
|
|
107
111
|
|
|
108
112
|
await writeStream(stream, input)
|
|
@@ -120,9 +124,9 @@ describe('unidirectional streams', function () {
|
|
|
120
124
|
await client.ready
|
|
121
125
|
|
|
122
126
|
const stream = await getReaderValue(client.incomingUnidirectionalStreams)
|
|
123
|
-
const received = await readStream(stream)
|
|
124
|
-
expect(received).to.deep.equal(
|
|
125
|
-
input,
|
|
127
|
+
const received = await readStream(stream, ui8.concat(input).length)
|
|
128
|
+
expect(ui8.concat(received)).to.deep.equal(
|
|
129
|
+
ui8.concat(input),
|
|
126
130
|
'Did not receive the same bytes we sent'
|
|
127
131
|
)
|
|
128
132
|
})
|
|
@@ -135,6 +139,7 @@ describe('unidirectional streams', function () {
|
|
|
135
139
|
|
|
136
140
|
Promise.resolve().then(async () => {
|
|
137
141
|
const session = await getReaderValue(server.sessionStream(SERVER_PATH))
|
|
142
|
+
if (!session) throw new Error('Got no session')
|
|
138
143
|
const stream = await getReaderValue(session.incomingUnidirectionalStreams)
|
|
139
144
|
|
|
140
145
|
serverStream.resolve(stream)
|
|
@@ -172,9 +177,12 @@ describe('unidirectional streams', function () {
|
|
|
172
177
|
|
|
173
178
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
174
179
|
|
|
175
|
-
const received = await readStream(
|
|
176
|
-
|
|
177
|
-
input
|
|
180
|
+
const received = await readStream(
|
|
181
|
+
await serverStream.promise,
|
|
182
|
+
ui8.concat(input).length
|
|
183
|
+
)
|
|
184
|
+
expect(ui8.concat(received)).to.deep.equal(
|
|
185
|
+
ui8.concat(input),
|
|
178
186
|
'Did not receive the same bytes we sent'
|
|
179
187
|
)
|
|
180
188
|
})
|