2 // Simple WebTransport test
5 /* import-globals-from head_webtransport.js */
12 var { setTimeout } = ChromeUtils.importESModule(
13 "resource://gre/modules/Timer.sys.mjs"
16 registerCleanupFunction(async () => {
17 Services.prefs.clearUserPref("network.dns.localDomains");
18 Services.prefs.clearUserPref("network.webtransport.datagrams.enabled");
21 add_task(async function setup() {
22 Services.prefs.setCharPref("network.dns.localDomains", "foo.example.com");
23 Services.prefs.setBoolPref("network.webtransport.datagrams.enabled", true);
25 h3Port = Services.env.get("MOZHTTP3_PORT");
26 Assert.notEqual(h3Port, null);
27 Assert.notEqual(h3Port, "");
28 host = "foo.example.com:" + h3Port;
31 let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
34 // `../unit/` so that unit_ipc tests can use as well
35 addCertFromFile(certdb, "../unit/http2-ca.pem", "CTu,u,u");
38 add_task(async function test_wt_datagram() {
39 let webTransport = NetUtil.newWebTransport();
40 let listener = new WebTransportListener().QueryInterface(
41 Ci.WebTransportSessionEventListener
44 let pReady = new Promise(resolve => {
45 listener.ready = resolve;
47 let pData = new Promise(resolve => {
48 listener.onDatagram = resolve;
50 let pSize = new Promise(resolve => {
51 listener.onMaxDatagramSize = resolve;
53 let pOutcome = new Promise(resolve => {
54 listener.onDatagramOutcome = resolve;
57 webTransport.asyncConnect(
58 NetUtil.newURI(`https://${host}/success`),
59 Services.scriptSecurityManager.getSystemPrincipal(),
60 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
66 webTransport.getMaxDatagramSize();
67 let size = await pSize;
68 info("max size:" + size);
70 let rawData = new Uint8Array(size);
73 webTransport.sendDatagram(rawData, 1);
74 let { id, outcome } = await pOutcome;
76 Assert.equal(outcome, Ci.WebTransportSessionEventListener.SENT);
78 let received = await pData;
79 Assert.deepEqual(received, rawData);
81 webTransport.getMaxDatagramSize();
83 info("max size:" + size);
85 rawData = new Uint8Array(size + 1);
86 webTransport.sendDatagram(rawData, 2);
88 pOutcome = new Promise(resolve => {
89 listener.onDatagramOutcome = resolve;
91 ({ id, outcome } = await pOutcome);
95 Ci.WebTransportSessionEventListener.DROPPED_TOO_MUCH_DATA
98 webTransport.closeSession(0, "");
101 add_task(async function test_connect_wt() {
102 let webTransport = NetUtil.newWebTransport();
104 await new Promise(resolve => {
105 let listener = new WebTransportListener().QueryInterface(
106 Ci.WebTransportSessionEventListener
108 listener.ready = resolve;
110 webTransport.asyncConnect(
111 NetUtil.newURI(`https://${host}/success`),
112 Services.scriptSecurityManager.getSystemPrincipal(),
113 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
118 webTransport.closeSession(0, "");
121 add_task(async function test_redirect_wt() {
122 let webTransport = NetUtil.newWebTransport();
124 await new Promise(resolve => {
125 let listener = new WebTransportListener().QueryInterface(
126 Ci.WebTransportSessionEventListener
129 listener.closed = resolve;
131 webTransport.asyncConnect(
132 NetUtil.newURI(`https://${host}/redirect`),
133 Services.scriptSecurityManager.getSystemPrincipal(),
134 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
140 add_task(async function test_reject() {
141 let webTransport = NetUtil.newWebTransport();
143 await new Promise(resolve => {
144 let listener = new WebTransportListener().QueryInterface(
145 Ci.WebTransportSessionEventListener
147 listener.closed = resolve;
149 webTransport.asyncConnect(
150 NetUtil.newURI(`https://${host}/reject`),
151 Services.scriptSecurityManager.getSystemPrincipal(),
152 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
158 async function test_closed(path) {
159 let webTransport = NetUtil.newWebTransport();
161 let listener = new WebTransportListener().QueryInterface(
162 Ci.WebTransportSessionEventListener
165 let pReady = new Promise(resolve => {
166 listener.ready = resolve;
168 let pClose = new Promise(resolve => {
169 listener.closed = resolve;
171 webTransport.asyncConnect(
172 NetUtil.newURI(`https://${host}${path}`),
173 Services.scriptSecurityManager.getSystemPrincipal(),
174 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
182 add_task(async function test_closed_0ms() {
183 await test_closed("/closeafter0ms");
186 add_task(async function test_closed_100ms() {
187 await test_closed("/closeafter100ms");
190 add_task(async function test_wt_stream_create() {
191 let webTransport = NetUtil.newWebTransport().QueryInterface(
195 await new Promise(resolve => {
196 let listener = new WebTransportListener().QueryInterface(
197 Ci.WebTransportSessionEventListener
199 listener.ready = resolve;
201 webTransport.asyncConnect(
202 NetUtil.newURI(`https://${host}/success`),
203 Services.scriptSecurityManager.getSystemPrincipal(),
204 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
209 await streamCreatePromise(webTransport, true);
210 await streamCreatePromise(webTransport, false);
212 webTransport.closeSession(0, "");
215 add_task(async function test_wt_stream_send_and_stats() {
216 let webTransport = NetUtil.newWebTransport().QueryInterface(
220 await new Promise(resolve => {
221 let listener = new WebTransportListener().QueryInterface(
222 Ci.WebTransportSessionEventListener
224 listener.ready = resolve;
226 webTransport.asyncConnect(
227 NetUtil.newURI(`https://${host}/success`),
228 Services.scriptSecurityManager.getSystemPrincipal(),
229 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
234 let stream = await streamCreatePromise(webTransport, false);
235 let outputStream = stream.outputStream;
237 let data = "1234567890ABC";
238 outputStream.write(data, data.length);
240 // We need some time to send the packet out.
241 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
242 await new Promise(resolve => setTimeout(resolve, 2000));
244 let stats = await sendStreamStatsPromise(stream);
245 Assert.equal(stats.bytesSent, data.length);
247 webTransport.closeSession(0, "");
250 add_task(async function test_wt_receive_stream_and_stats() {
251 let webTransport = NetUtil.newWebTransport().QueryInterface(
255 let listener = new WebTransportListener().QueryInterface(
256 Ci.WebTransportSessionEventListener
259 let pReady = new Promise(resolve => {
260 listener.ready = resolve;
262 let pStreamReady = new Promise(resolve => {
263 listener.streamAvailable = resolve;
265 webTransport.asyncConnect(
266 NetUtil.newURI(`https://${host}/create_unidi_stream_and_hello`),
267 Services.scriptSecurityManager.getSystemPrincipal(),
268 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
273 let stream = await pStreamReady;
275 let data = await new Promise(resolve => {
276 let handler = new inputStreamReader().QueryInterface(
277 Ci.nsIInputStreamCallback
279 handler.finish = resolve;
280 let inputStream = stream.inputStream;
281 inputStream.asyncWait(handler, 0, 0, Services.tm.currentThread);
284 info("data: " + data);
285 Assert.equal(data, "qwerty");
287 let stats = await receiveStreamStatsPromise(stream);
288 Assert.equal(stats.bytesReceived, data.length);
290 stream.sendStopSending(0);
292 webTransport.closeSession(0, "");
295 add_task(async function test_wt_outgoing_bidi_stream() {
296 let webTransport = NetUtil.newWebTransport().QueryInterface(
300 await new Promise(resolve => {
301 let listener = new WebTransportListener().QueryInterface(
302 Ci.WebTransportSessionEventListener
304 listener.ready = resolve;
306 webTransport.asyncConnect(
307 NetUtil.newURI(`https://${host}/success`),
308 Services.scriptSecurityManager.getSystemPrincipal(),
309 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
314 let stream = await streamCreatePromise(webTransport, true);
315 let outputStream = stream.outputStream;
317 let data = "1234567";
318 outputStream.write(data, data.length);
320 let received = await new Promise(resolve => {
321 let handler = new inputStreamReader().QueryInterface(
322 Ci.nsIInputStreamCallback
324 handler.finish = resolve;
325 let inputStream = stream.inputStream;
326 inputStream.asyncWait(handler, 0, 0, Services.tm.currentThread);
329 info("received: " + received);
330 Assert.equal(received, data);
332 let stats = await sendStreamStatsPromise(stream);
333 Assert.equal(stats.bytesSent, data.length);
335 stats = await receiveStreamStatsPromise(stream);
336 Assert.equal(stats.bytesReceived, data.length);
338 webTransport.closeSession(0, "");
341 add_task(async function test_wt_incoming_bidi_stream() {
342 let webTransport = NetUtil.newWebTransport().QueryInterface(
346 let listener = new WebTransportListener().QueryInterface(
347 Ci.WebTransportSessionEventListener
350 let pReady = new Promise(resolve => {
351 listener.ready = resolve;
353 let pStreamReady = new Promise(resolve => {
354 listener.streamAvailable = resolve;
356 webTransport.asyncConnect(
357 NetUtil.newURI(`https://${host}/create_bidi_stream`),
358 Services.scriptSecurityManager.getSystemPrincipal(),
359 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
364 let stream = await pStreamReady;
366 let outputStream = stream.outputStream;
368 let data = "12345678";
369 outputStream.write(data, data.length);
371 let received = await new Promise(resolve => {
372 let handler = new inputStreamReader().QueryInterface(
373 Ci.nsIInputStreamCallback
375 handler.finish = resolve;
376 let inputStream = stream.inputStream;
377 inputStream.asyncWait(handler, 0, 0, Services.tm.currentThread);
380 info("received: " + received);
381 Assert.equal(received, data);
383 let stats = await sendStreamStatsPromise(stream);
384 Assert.equal(stats.bytesSent, data.length);
386 stats = await receiveStreamStatsPromise(stream);
387 Assert.equal(stats.bytesReceived, data.length);
389 webTransport.closeSession(0, "");