test_webtransport_simple.js (12130B)
1 // 2 // Simple WebTransport test 3 // 4 5 /* import-globals-from head_webtransport.js */ 6 7 "use strict"; 8 9 var h3Port; 10 var host; 11 12 var { setTimeout } = ChromeUtils.importESModule( 13 "resource://gre/modules/Timer.sys.mjs" 14 ); 15 16 registerCleanupFunction(async () => { 17 Services.prefs.clearUserPref("network.dns.localDomains"); 18 Services.prefs.clearUserPref( 19 "network.http.http3.alt-svc-mapping-for-testing" 20 ); 21 }); 22 23 add_task(async function setup() { 24 await http3_setup_tests("h3"); 25 26 h3Port = Services.env.get("MOZHTTP3_PORT"); 27 Assert.notEqual(h3Port, null); 28 Assert.notEqual(h3Port, ""); 29 host = "foo.example.com:" + h3Port; 30 }); 31 32 function makeChan(url) { 33 let chan = NetUtil.newChannel({ 34 uri: url, 35 loadUsingSystemPrincipal: true, 36 contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT, 37 }).QueryInterface(Ci.nsIHttpChannel); 38 chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI; 39 return chan; 40 } 41 42 function channelOpenPromise(chan, flags) { 43 // eslint-disable-next-line no-async-promise-executor 44 return new Promise(async resolve => { 45 function finish(req, buffer) { 46 resolve([req, buffer]); 47 } 48 chan.asyncOpen(new ChannelListener(finish, null, flags)); 49 }); 50 } 51 52 function bytesFromString(str) { 53 return new TextEncoder().encode(str); 54 } 55 56 add_task(async function test_wt_datagram() { 57 let webTransport = NetUtil.newWebTransport(); 58 let listener = new WebTransportListener().QueryInterface( 59 Ci.WebTransportSessionEventListener 60 ); 61 62 let pReady = new Promise(resolve => { 63 listener.ready = resolve; 64 }); 65 let pSize = new Promise(resolve => { 66 listener.onMaxDatagramSize = resolve; 67 }); 68 let pOutcome = new Promise(resolve => { 69 listener.onDatagramOutcome = resolve; 70 }); 71 72 webTransport.asyncConnect( 73 NetUtil.newURI(`https://${host}/success`), 74 true, 75 [], 76 Services.scriptSecurityManager.getSystemPrincipal(), 77 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 78 listener 79 ); 80 81 await pReady; 82 83 webTransport.getMaxDatagramSize(); 84 let size = await pSize; 85 info("max size:" + size); 86 87 let rawData = new Uint8Array(size); 88 rawData.fill(42); 89 90 webTransport.sendDatagram(rawData, 1); 91 let { id, outcome } = await pOutcome; 92 Assert.equal(id, 1); 93 Assert.equal(outcome, Ci.WebTransportSessionEventListener.SENT); 94 95 let chan = makeChan(`https://${host}/get_webtransport_datagram`); 96 let [req, buffer] = await channelOpenPromise(chan); 97 Assert.equal(req.protocolVersion, "h3"); 98 99 Assert.deepEqual(bytesFromString(buffer), rawData); 100 101 webTransport.getMaxDatagramSize(); 102 size = await pSize; 103 info("max size:" + size); 104 105 rawData = new Uint8Array(size + 1); 106 webTransport.sendDatagram(rawData, 2); 107 108 pOutcome = new Promise(resolve => { 109 listener.onDatagramOutcome = resolve; 110 }); 111 ({ id, outcome } = await pOutcome); 112 Assert.equal(id, 2); 113 Assert.equal( 114 outcome, 115 Ci.WebTransportSessionEventListener.DROPPED_TOO_MUCH_DATA 116 ); 117 118 webTransport.closeSession(0, ""); 119 }); 120 121 add_task(async function test_connect_wt() { 122 let webTransport = NetUtil.newWebTransport(); 123 124 await new Promise(resolve => { 125 let listener = new WebTransportListener().QueryInterface( 126 Ci.WebTransportSessionEventListener 127 ); 128 listener.ready = resolve; 129 130 webTransport.asyncConnect( 131 NetUtil.newURI(`https://${host}/success`), 132 true, 133 [], 134 Services.scriptSecurityManager.getSystemPrincipal(), 135 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 136 listener 137 ); 138 }); 139 140 webTransport.closeSession(0, ""); 141 }); 142 143 add_task(async function test_redirect_wt() { 144 let webTransport = NetUtil.newWebTransport(); 145 146 await new Promise(resolve => { 147 let listener = new WebTransportListener().QueryInterface( 148 Ci.WebTransportSessionEventListener 149 ); 150 151 listener.closed = resolve; 152 153 webTransport.asyncConnect( 154 NetUtil.newURI(`https://${host}/redirect`), 155 true, 156 [], 157 Services.scriptSecurityManager.getSystemPrincipal(), 158 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 159 listener 160 ); 161 }); 162 }); 163 164 add_task(async function test_reject() { 165 let webTransport = NetUtil.newWebTransport(); 166 167 await new Promise(resolve => { 168 let listener = new WebTransportListener().QueryInterface( 169 Ci.WebTransportSessionEventListener 170 ); 171 listener.closed = resolve; 172 173 webTransport.asyncConnect( 174 NetUtil.newURI(`https://${host}/reject`), 175 true, 176 [], 177 Services.scriptSecurityManager.getSystemPrincipal(), 178 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 179 listener 180 ); 181 }); 182 }); 183 184 async function test_closed(path) { 185 let webTransport = NetUtil.newWebTransport(); 186 187 let listener = new WebTransportListener().QueryInterface( 188 Ci.WebTransportSessionEventListener 189 ); 190 191 let pReady = new Promise(resolve => { 192 listener.ready = resolve; 193 }); 194 let pClose = new Promise(resolve => { 195 listener.closed = resolve; 196 }); 197 webTransport.asyncConnect( 198 NetUtil.newURI(`https://${host}${path}`), 199 true, 200 [], 201 Services.scriptSecurityManager.getSystemPrincipal(), 202 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 203 listener 204 ); 205 206 await pReady; 207 await pClose; 208 } 209 210 add_task(async function test_closed_0ms() { 211 await test_closed("/closeafter0ms"); 212 }); 213 214 add_task(async function test_closed_100ms() { 215 await test_closed("/closeafter100ms"); 216 }); 217 218 add_task(async function test_wt_stream_create() { 219 let webTransport = NetUtil.newWebTransport().QueryInterface( 220 Ci.nsIWebTransport 221 ); 222 223 await new Promise(resolve => { 224 let listener = new WebTransportListener().QueryInterface( 225 Ci.WebTransportSessionEventListener 226 ); 227 listener.ready = resolve; 228 229 webTransport.asyncConnect( 230 NetUtil.newURI(`https://${host}/success`), 231 true, 232 [], 233 Services.scriptSecurityManager.getSystemPrincipal(), 234 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 235 listener 236 ); 237 }); 238 239 await streamCreatePromise(webTransport, true); 240 await streamCreatePromise(webTransport, false); 241 242 webTransport.closeSession(0, ""); 243 }); 244 245 add_task(async function test_wt_stream_send_and_stats() { 246 let webTransport = NetUtil.newWebTransport().QueryInterface( 247 Ci.nsIWebTransport 248 ); 249 250 await new Promise(resolve => { 251 let listener = new WebTransportListener().QueryInterface( 252 Ci.WebTransportSessionEventListener 253 ); 254 listener.ready = resolve; 255 256 webTransport.asyncConnect( 257 NetUtil.newURI(`https://${host}/success`), 258 true, 259 [], 260 Services.scriptSecurityManager.getSystemPrincipal(), 261 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 262 listener 263 ); 264 }); 265 266 let stream = await streamCreatePromise(webTransport, false); 267 let outputStream = stream.outputStream; 268 269 let data = "1234567890ABC"; 270 outputStream.write(data, data.length); 271 272 // We need some time to send the packet out. 273 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout 274 await new Promise(resolve => setTimeout(resolve, 2000)); 275 276 let stats = await sendStreamStatsPromise(stream); 277 Assert.equal(stats.bytesSent, data.length); 278 279 webTransport.closeSession(0, ""); 280 }); 281 282 add_task(async function test_wt_receive_stream_and_stats() { 283 let webTransport = NetUtil.newWebTransport().QueryInterface( 284 Ci.nsIWebTransport 285 ); 286 287 let listener = new WebTransportListener().QueryInterface( 288 Ci.WebTransportSessionEventListener 289 ); 290 291 let pReady = new Promise(resolve => { 292 listener.ready = resolve; 293 }); 294 let pStreamReady = new Promise(resolve => { 295 listener.streamAvailable = resolve; 296 }); 297 webTransport.asyncConnect( 298 NetUtil.newURI(`https://${host}/create_unidi_stream_and_hello`), 299 true, 300 [], 301 Services.scriptSecurityManager.getSystemPrincipal(), 302 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 303 listener 304 ); 305 306 await pReady; 307 let stream = await pStreamReady; 308 309 let data = await new Promise(resolve => { 310 let handler = new inputStreamReader().QueryInterface( 311 Ci.nsIInputStreamCallback 312 ); 313 handler.finish = resolve; 314 let inputStream = stream.inputStream; 315 inputStream.asyncWait(handler, 0, 0, Services.tm.currentThread); 316 }); 317 318 info("data: " + data); 319 Assert.equal(data, "qwerty"); 320 321 let stats = await receiveStreamStatsPromise(stream); 322 Assert.equal(stats.bytesReceived, data.length); 323 324 stream.sendStopSending(0); 325 326 webTransport.closeSession(0, ""); 327 }); 328 329 add_task(async function test_wt_outgoing_bidi_stream() { 330 let webTransport = NetUtil.newWebTransport().QueryInterface( 331 Ci.nsIWebTransport 332 ); 333 334 await new Promise(resolve => { 335 let listener = new WebTransportListener().QueryInterface( 336 Ci.WebTransportSessionEventListener 337 ); 338 listener.ready = resolve; 339 340 webTransport.asyncConnect( 341 NetUtil.newURI(`https://${host}/success`), 342 true, 343 [], 344 Services.scriptSecurityManager.getSystemPrincipal(), 345 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 346 listener 347 ); 348 }); 349 350 let stream = await streamCreatePromise(webTransport, true); 351 let outputStream = stream.outputStream; 352 353 let data = "1234567"; 354 outputStream.write(data, data.length); 355 356 let received = await new Promise(resolve => { 357 let handler = new inputStreamReader().QueryInterface( 358 Ci.nsIInputStreamCallback 359 ); 360 handler.finish = resolve; 361 let inputStream = stream.inputStream; 362 inputStream.asyncWait(handler, 0, 0, Services.tm.currentThread); 363 }); 364 365 info("received: " + received); 366 Assert.equal(received, data); 367 368 let stats = await sendStreamStatsPromise(stream); 369 Assert.equal(stats.bytesSent, data.length); 370 371 stats = await receiveStreamStatsPromise(stream); 372 Assert.equal(stats.bytesReceived, data.length); 373 374 webTransport.closeSession(0, ""); 375 }); 376 377 add_task(async function test_wt_incoming_bidi_stream() { 378 let webTransport = NetUtil.newWebTransport().QueryInterface( 379 Ci.nsIWebTransport 380 ); 381 382 let listener = new WebTransportListener().QueryInterface( 383 Ci.WebTransportSessionEventListener 384 ); 385 386 let pReady = new Promise(resolve => { 387 listener.ready = resolve; 388 }); 389 let pStreamReady = new Promise(resolve => { 390 listener.streamAvailable = resolve; 391 }); 392 webTransport.asyncConnect( 393 NetUtil.newURI(`https://${host}/create_bidi_stream`), 394 true, 395 [], 396 Services.scriptSecurityManager.getSystemPrincipal(), 397 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 398 listener 399 ); 400 401 await pReady; 402 let stream = await pStreamReady; 403 404 let outputStream = stream.outputStream; 405 406 let data = "12345678"; 407 outputStream.write(data, data.length); 408 409 let received = await new Promise(resolve => { 410 let handler = new inputStreamReader().QueryInterface( 411 Ci.nsIInputStreamCallback 412 ); 413 handler.finish = resolve; 414 let inputStream = stream.inputStream; 415 inputStream.asyncWait(handler, 0, 0, Services.tm.currentThread); 416 }); 417 418 info("received: " + received); 419 Assert.equal(received, data); 420 421 let stats = await sendStreamStatsPromise(stream); 422 Assert.equal(stats.bytesSent, data.length); 423 424 stats = await receiveStreamStatsPromise(stream); 425 Assert.equal(stats.bytesReceived, data.length); 426 427 webTransport.closeSession(0, ""); 428 }); 429 430 async function createWebTransportAndConnect() { 431 let webTransport = NetUtil.newWebTransport(); 432 433 await new Promise(resolve => { 434 let listener = new WebTransportListener().QueryInterface( 435 Ci.WebTransportSessionEventListener 436 ); 437 listener.ready = resolve; 438 439 webTransport.asyncConnect( 440 NetUtil.newURI(`https://${host}/success`), 441 true, 442 [], 443 Services.scriptSecurityManager.getSystemPrincipal(), 444 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 445 listener 446 ); 447 }); 448 449 return webTransport; 450 } 451 452 add_task(async function test_multple_webtransport_connnection() { 453 let webTransports = []; 454 for (let i = 0; i < 3; i++) { 455 let transport = await createWebTransportAndConnect(); 456 webTransports.push(transport); 457 } 458 459 let first = webTransports[0]; 460 await streamCreatePromise(first, true); 461 462 for (let i = 0; i < 3; i++) { 463 webTransports[i].closeSession(0, ""); 464 } 465 });