Source: lib/msf/drafts/draft18/dialect.js

/*! @license
 * Shaka Player
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

goog.provide('shaka.msf.draft18.Dialect');

goog.require('shaka.Player');
goog.require('shaka.config.MsfVersion');
goog.require('shaka.log');
goog.require('shaka.msf.DialectRegistry');
goog.require('shaka.msf.Utils');
goog.require('shaka.msf.Writer');
goog.require('shaka.msf.draft18.Codec');
goog.require('shaka.msf.draft18.MessageWriter');
goog.require('shaka.msf.draft18.Session');
goog.require('shaka.util.BufferUtils');
goog.require('shaka.util.DataViewWriter');
goog.require('shaka.util.StringUtils');


/**
 * The draft-18 dialect.
 *
 * @implements {shaka.extern.MsfDialect}
 * @final
 */
shaka.msf.draft18.Dialect = class {
  /** */
  constructor() {
    /** @private {!shaka.msf.draft18.Codec} */
    this.codec_ = new shaka.msf.draft18.Codec();
  }

  /** @override */
  getSubprotocol() {
    return 'moqt-18';
  }

  /** @override */
  getName() {
    return shaka.config.MsfVersion.DRAFT_18;
  }

  /** @override */
  getDraftNumber() {
    return 18;
  }

  /** @override */
  getCodec() {
    return this.codec_;
  }

  /** @override */
  async connect(webTransport, config, authorizationToken) {
    // We open our own unidirectional control stream and send SETUP on it
    // without waiting for the peer's; the session picks the peer's control
    // stream out of the incoming unidirectional streams by its SETUP.
    const controlStream =
        await webTransport.createUnidirectionalStream();
    const controlWriter = new shaka.msf.Writer(controlStream);

    const implementation = 'ShakaPlayer/' + shaka.Player.version;
    /** @type {!Array<shaka.msf.Utils.KeyValuePair>} */
    const options = [
      {
        type: BigInt(shaka.msf.Utils.SetupOption.IMPLEMENTATION),
        value: shaka.util.BufferUtils.toUint8(
            shaka.util.StringUtils.toUTF8(implementation)),
      },
    ];
    if (authorizationToken) {
      options.push({
        type: BigInt(shaka.msf.Utils.SetupOption.AUTHORIZATION_TOKEN),
        value: this.buildAuthToken_(authorizationToken),
      });
    }

    const writer = new shaka.msf.draft18.MessageWriter(this.codec_);
    writer.marshalSetup(options);
    await controlWriter.write(writer.getBytes());
    shaka.log.v1('Sent SETUP on our control stream (draft-18)');

    return new shaka.msf.draft18.Session(
        webTransport, controlWriter, this, config);
  }

  /**
   * @param {string} token
   * @return {!Uint8Array}
   * @private
   */
  buildAuthToken_(token) {
    const tokenBytes = shaka.util.BufferUtils.toUint8(
        shaka.util.StringUtils.toUTF8(token));

    const writer = new shaka.util.DataViewWriter(
        2 + tokenBytes.length,
        shaka.util.DataViewWriter.Endianness.BIG_ENDIAN);

    // Alias Type = USE_VALUE (0x03), Token Type = 0.
    this.codec_.encodeVarInt(writer, BigInt(0x03));
    this.codec_.encodeVarInt(writer, BigInt(0x00));
    writer.writeBytes(tokenBytes);

    return writer.getBytes();
  }
};


shaka.msf.DialectRegistry.registerDialect(
    shaka.config.MsfVersion.DRAFT_18,
    () => new shaka.msf.draft18.Dialect());