11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciif (!common.hasCrypto)
51cb0ef41Sopenharmony_ci  common.skip('missing crypto');
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst assert = require('assert');
81cb0ef41Sopenharmony_ciconst http2 = require('http2');
91cb0ef41Sopenharmony_ciconst Countdown = require('../common/countdown');
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ciconst server = http2.createServer();
121cb0ef41Sopenharmony_ciserver.on('stream', common.mustCall((stream) => {
131cb0ef41Sopenharmony_ci  stream.session.altsvc('h2=":8000"', stream.id);
141cb0ef41Sopenharmony_ci  stream.respond();
151cb0ef41Sopenharmony_ci  stream.end('ok');
161cb0ef41Sopenharmony_ci}));
171cb0ef41Sopenharmony_ciserver.on('session', common.mustCall((session) => {
181cb0ef41Sopenharmony_ci  // Origin may be specified by string, URL object, or object with an
191cb0ef41Sopenharmony_ci  // origin property. For string and URL object, origin is guaranteed
201cb0ef41Sopenharmony_ci  // to be an ASCII serialized origin. For object with an origin
211cb0ef41Sopenharmony_ci  // property, it is up to the user to ensure proper serialization.
221cb0ef41Sopenharmony_ci  session.altsvc('h2=":8000"', 'https://example.org:8111/this');
231cb0ef41Sopenharmony_ci  session.altsvc('h2=":8000"', new URL('https://example.org:8111/this'));
241cb0ef41Sopenharmony_ci  session.altsvc('h2=":8000"', { origin: 'https://example.org:8111' });
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci  // Won't error, but won't send anything because the stream does not exist
271cb0ef41Sopenharmony_ci  session.altsvc('h2=":8000"', 3);
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  // Will error because the numeric stream id is out of valid range
301cb0ef41Sopenharmony_ci  [0, -1, 1.1, 0xFFFFFFFF + 1, Infinity, -Infinity].forEach((input) => {
311cb0ef41Sopenharmony_ci    assert.throws(
321cb0ef41Sopenharmony_ci      () => session.altsvc('h2=":8000"', input),
331cb0ef41Sopenharmony_ci      {
341cb0ef41Sopenharmony_ci        code: 'ERR_OUT_OF_RANGE',
351cb0ef41Sopenharmony_ci        name: 'RangeError',
361cb0ef41Sopenharmony_ci        message: 'The value of "originOrStream" is out of ' +
371cb0ef41Sopenharmony_ci                 `range. It must be > 0 && < 4294967296. Received ${input}`
381cb0ef41Sopenharmony_ci      }
391cb0ef41Sopenharmony_ci    );
401cb0ef41Sopenharmony_ci  });
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  // First argument must be a string
431cb0ef41Sopenharmony_ci  [0, {}, [], null, Infinity].forEach((input) => {
441cb0ef41Sopenharmony_ci    assert.throws(
451cb0ef41Sopenharmony_ci      () => session.altsvc(input),
461cb0ef41Sopenharmony_ci      {
471cb0ef41Sopenharmony_ci        code: 'ERR_INVALID_ARG_TYPE',
481cb0ef41Sopenharmony_ci        name: 'TypeError'
491cb0ef41Sopenharmony_ci      }
501cb0ef41Sopenharmony_ci    );
511cb0ef41Sopenharmony_ci  });
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  ['\u0001', 'h2="\uff20"', '�'].forEach((input) => {
541cb0ef41Sopenharmony_ci    assert.throws(
551cb0ef41Sopenharmony_ci      () => session.altsvc(input),
561cb0ef41Sopenharmony_ci      {
571cb0ef41Sopenharmony_ci        code: 'ERR_INVALID_CHAR',
581cb0ef41Sopenharmony_ci        name: 'TypeError',
591cb0ef41Sopenharmony_ci        message: 'Invalid character in alt'
601cb0ef41Sopenharmony_ci      }
611cb0ef41Sopenharmony_ci    );
621cb0ef41Sopenharmony_ci  });
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  [{}, [], true].forEach((input) => {
651cb0ef41Sopenharmony_ci    assert.throws(
661cb0ef41Sopenharmony_ci      () => session.altsvc('clear', input),
671cb0ef41Sopenharmony_ci      {
681cb0ef41Sopenharmony_ci        code: 'ERR_INVALID_ARG_TYPE',
691cb0ef41Sopenharmony_ci        name: 'TypeError'
701cb0ef41Sopenharmony_ci      }
711cb0ef41Sopenharmony_ci    );
721cb0ef41Sopenharmony_ci  });
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  [
751cb0ef41Sopenharmony_ci    'abc:',
761cb0ef41Sopenharmony_ci    new URL('abc:'),
771cb0ef41Sopenharmony_ci    { origin: 'null' },
781cb0ef41Sopenharmony_ci    { origin: '' },
791cb0ef41Sopenharmony_ci  ].forEach((input) => {
801cb0ef41Sopenharmony_ci    assert.throws(
811cb0ef41Sopenharmony_ci      () => session.altsvc('h2=":8000', input),
821cb0ef41Sopenharmony_ci      {
831cb0ef41Sopenharmony_ci        code: 'ERR_HTTP2_ALTSVC_INVALID_ORIGIN',
841cb0ef41Sopenharmony_ci        name: 'TypeError',
851cb0ef41Sopenharmony_ci        message: 'HTTP/2 ALTSVC frames require a valid origin'
861cb0ef41Sopenharmony_ci      }
871cb0ef41Sopenharmony_ci    );
881cb0ef41Sopenharmony_ci  });
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  // Arguments + origin are too long for an ALTSVC frame
911cb0ef41Sopenharmony_ci  assert.throws(
921cb0ef41Sopenharmony_ci    () => {
931cb0ef41Sopenharmony_ci      session.altsvc('h2=":8000"',
941cb0ef41Sopenharmony_ci                     `http://example.${'a'.repeat(17000)}.org:8000`);
951cb0ef41Sopenharmony_ci    },
961cb0ef41Sopenharmony_ci    {
971cb0ef41Sopenharmony_ci      code: 'ERR_HTTP2_ALTSVC_LENGTH',
981cb0ef41Sopenharmony_ci      name: 'TypeError',
991cb0ef41Sopenharmony_ci      message: 'HTTP/2 ALTSVC frames are limited to 16382 bytes'
1001cb0ef41Sopenharmony_ci    }
1011cb0ef41Sopenharmony_ci  );
1021cb0ef41Sopenharmony_ci}));
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ciserver.listen(0, common.mustCall(() => {
1051cb0ef41Sopenharmony_ci  const client = http2.connect(`http://localhost:${server.address().port}`);
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  const countdown = new Countdown(4, () => {
1081cb0ef41Sopenharmony_ci    client.close();
1091cb0ef41Sopenharmony_ci    server.close();
1101cb0ef41Sopenharmony_ci  });
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  client.on('altsvc', common.mustCall((alt, origin, stream) => {
1131cb0ef41Sopenharmony_ci    assert.strictEqual(alt, 'h2=":8000"');
1141cb0ef41Sopenharmony_ci    switch (stream) {
1151cb0ef41Sopenharmony_ci      case 0:
1161cb0ef41Sopenharmony_ci        assert.strictEqual(origin, 'https://example.org:8111');
1171cb0ef41Sopenharmony_ci        break;
1181cb0ef41Sopenharmony_ci      case 1:
1191cb0ef41Sopenharmony_ci        assert.strictEqual(origin, '');
1201cb0ef41Sopenharmony_ci        break;
1211cb0ef41Sopenharmony_ci      default:
1221cb0ef41Sopenharmony_ci        assert.fail('should not happen');
1231cb0ef41Sopenharmony_ci    }
1241cb0ef41Sopenharmony_ci    countdown.dec();
1251cb0ef41Sopenharmony_ci  }, 4));
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  const req = client.request();
1281cb0ef41Sopenharmony_ci  req.resume();
1291cb0ef41Sopenharmony_ci  req.on('close', common.mustCall());
1301cb0ef41Sopenharmony_ci}));
131