SPB Git forge

spb/admin-ka

Public
41commits 1branches 0releases
172.9 MBsize
maindefault branch
19 days agolast push
JavaScript 65.5% Python 17.8% CSS 13% HTML 3.7%
15.1 KB · 395 lines javascript
Raw Blame History
1"use strict";23Object.defineProperty(exports, "__esModule", {4  value: true5});6exports["default"] = void 0;7var Log = _interopRequireWildcard(require("./util/logging.js"));8function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }9function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }10function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }11function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }12function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }13function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }14function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }15function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }16function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }17function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }18function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }19function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }20function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }21function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /*22 * Websock: high-performance buffering wrapper23 * Copyright (C) 2019 The noVNC authors24 * Licensed under MPL 2.0 (see LICENSE.txt)25 *26 * Websock is similar to the standard WebSocket / RTCDataChannel object27 * but with extra buffer handling.28 *29 * Websock has built-in receive queue buffering; the message event30 * does not contain actual data but is simply a notification that31 * there is new data available. Several rQ* methods are available to32 * read binary data off of the receive queue.33 */34// this has performance issues in some versions Chromium, and35// doesn't gain a tremendous amount of performance increase in Firefox36// at the moment.  It may be valuable to turn it on in the future.37var MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB3839// Constants pulled from RTCDataChannelState enum40// https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/readyState#RTCDataChannelState_enum41var DataChannel = {42  CONNECTING: "connecting",43  OPEN: "open",44  CLOSING: "closing",45  CLOSED: "closed"46};47var ReadyStates = {48  CONNECTING: [WebSocket.CONNECTING, DataChannel.CONNECTING],49  OPEN: [WebSocket.OPEN, DataChannel.OPEN],50  CLOSING: [WebSocket.CLOSING, DataChannel.CLOSING],51  CLOSED: [WebSocket.CLOSED, DataChannel.CLOSED]52};5354// Properties a raw channel must have, WebSocket and RTCDataChannel are two examples55var rawChannelProps = ["send", "close", "binaryType", "onerror", "onmessage", "onopen", "protocol", "readyState"];56var Websock = exports["default"] = /*#__PURE__*/function () {57  function Websock() {58    _classCallCheck(this, Websock);59    this._websocket = null; // WebSocket or RTCDataChannel object6061    this._rQi = 0; // Receive queue index62    this._rQlen = 0; // Next write position in the receive queue63    this._rQbufferSize = 1024 * 1024 * 4; // Receive queue buffer size (4 MiB)64    // called in init: this._rQ = new Uint8Array(this._rQbufferSize);65    this._rQ = null; // Receive queue6667    this._sQbufferSize = 1024 * 10; // 10 KiB68    // called in init: this._sQ = new Uint8Array(this._sQbufferSize);69    this._sQlen = 0;70    this._sQ = null; // Send queue7172    this._eventHandlers = {73      message: function message() {},74      open: function open() {},75      close: function close() {},76      error: function error() {}77    };78  }7980  // Getters and setters81  return _createClass(Websock, [{82    key: "readyState",83    get: function get() {84      var subState;85      if (this._websocket === null) {86        return "unused";87      }88      subState = this._websocket.readyState;89      if (ReadyStates.CONNECTING.includes(subState)) {90        return "connecting";91      } else if (ReadyStates.OPEN.includes(subState)) {92        return "open";93      } else if (ReadyStates.CLOSING.includes(subState)) {94        return "closing";95      } else if (ReadyStates.CLOSED.includes(subState)) {96        return "closed";97      }98      return "unknown";99    }100101    // Receive queue102  }, {103    key: "rQpeek8",104    value: function rQpeek8() {105      return this._rQ[this._rQi];106    }107  }, {108    key: "rQskipBytes",109    value: function rQskipBytes(bytes) {110      this._rQi += bytes;111    }112  }, {113    key: "rQshift8",114    value: function rQshift8() {115      return this._rQshift(1);116    }117  }, {118    key: "rQshift16",119    value: function rQshift16() {120      return this._rQshift(2);121    }122  }, {123    key: "rQshift32",124    value: function rQshift32() {125      return this._rQshift(4);126    }127128    // TODO(directxman12): test performance with these vs a DataView129  }, {130    key: "_rQshift",131    value: function _rQshift(bytes) {132      var res = 0;133      for (var _byte = bytes - 1; _byte >= 0; _byte--) {134        res += this._rQ[this._rQi++] << _byte * 8;135      }136      return res >>> 0;137    }138  }, {139    key: "rQshiftStr",140    value: function rQshiftStr(len) {141      var str = "";142      // Handle large arrays in steps to avoid long strings on the stack143      for (var i = 0; i < len; i += 4096) {144        var part = this.rQshiftBytes(Math.min(4096, len - i), false);145        str += String.fromCharCode.apply(null, part);146      }147      return str;148    }149  }, {150    key: "rQshiftBytes",151    value: function rQshiftBytes(len) {152      var copy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;153      this._rQi += len;154      if (copy) {155        return this._rQ.slice(this._rQi - len, this._rQi);156      } else {157        return this._rQ.subarray(this._rQi - len, this._rQi);158      }159    }160  }, {161    key: "rQshiftTo",162    value: function rQshiftTo(target, len) {163      // TODO: make this just use set with views when using a ArrayBuffer to store the rQ164      target.set(new Uint8Array(this._rQ.buffer, this._rQi, len));165      this._rQi += len;166    }167  }, {168    key: "rQpeekBytes",169    value: function rQpeekBytes(len) {170      var copy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;171      if (copy) {172        return this._rQ.slice(this._rQi, this._rQi + len);173      } else {174        return this._rQ.subarray(this._rQi, this._rQi + len);175      }176    }177178    // Check to see if we must wait for 'num' bytes (default to FBU.bytes)179    // to be available in the receive queue. Return true if we need to180    // wait (and possibly print a debug message), otherwise false.181  }, {182    key: "rQwait",183    value: function rQwait(msg, num, goback) {184      if (this._rQlen - this._rQi < num) {185        if (goback) {186          if (this._rQi < goback) {187            throw new Error("rQwait cannot backup " + goback + " bytes");188          }189          this._rQi -= goback;190        }191        return true; // true means need more data192      }193      return false;194    }195196    // Send queue197  }, {198    key: "sQpush8",199    value: function sQpush8(num) {200      this._sQensureSpace(1);201      this._sQ[this._sQlen++] = num;202    }203  }, {204    key: "sQpush16",205    value: function sQpush16(num) {206      this._sQensureSpace(2);207      this._sQ[this._sQlen++] = num >> 8 & 0xff;208      this._sQ[this._sQlen++] = num >> 0 & 0xff;209    }210  }, {211    key: "sQpush32",212    value: function sQpush32(num) {213      this._sQensureSpace(4);214      this._sQ[this._sQlen++] = num >> 24 & 0xff;215      this._sQ[this._sQlen++] = num >> 16 & 0xff;216      this._sQ[this._sQlen++] = num >> 8 & 0xff;217      this._sQ[this._sQlen++] = num >> 0 & 0xff;218    }219  }, {220    key: "sQpushString",221    value: function sQpushString(str) {222      var bytes = str.split('').map(function (chr) {223        return chr.charCodeAt(0);224      });225      this.sQpushBytes(new Uint8Array(bytes));226    }227  }, {228    key: "sQpushBytes",229    value: function sQpushBytes(bytes) {230      for (var offset = 0; offset < bytes.length;) {231        this._sQensureSpace(1);232        var chunkSize = this._sQbufferSize - this._sQlen;233        if (chunkSize > bytes.length - offset) {234          chunkSize = bytes.length - offset;235        }236        this._sQ.set(bytes.subarray(offset, offset + chunkSize), this._sQlen);237        this._sQlen += chunkSize;238        offset += chunkSize;239      }240    }241  }, {242    key: "flush",243    value: function flush() {244      if (this._sQlen > 0 && this.readyState === 'open') {245        this._websocket.send(new Uint8Array(this._sQ.buffer, 0, this._sQlen));246        this._sQlen = 0;247      }248    }249  }, {250    key: "_sQensureSpace",251    value: function _sQensureSpace(bytes) {252      if (this._sQbufferSize - this._sQlen < bytes) {253        this.flush();254      }255    }256257    // Event handlers258  }, {259    key: "off",260    value: function off(evt) {261      this._eventHandlers[evt] = function () {};262    }263  }, {264    key: "on",265    value: function on(evt, handler) {266      this._eventHandlers[evt] = handler;267    }268  }, {269    key: "_allocateBuffers",270    value: function _allocateBuffers() {271      this._rQ = new Uint8Array(this._rQbufferSize);272      this._sQ = new Uint8Array(this._sQbufferSize);273    }274  }, {275    key: "init",276    value: function init() {277      this._allocateBuffers();278      this._rQi = 0;279      this._websocket = null;280    }281  }, {282    key: "open",283    value: function open(uri, protocols) {284      this.attach(new WebSocket(uri, protocols));285    }286  }, {287    key: "attach",288    value: function attach(rawChannel) {289      var _this = this;290      this.init();291292      // Must get object and class methods to be compatible with the tests.293      var channelProps = [].concat(_toConsumableArray(Object.keys(rawChannel)), _toConsumableArray(Object.getOwnPropertyNames(Object.getPrototypeOf(rawChannel))));294      for (var i = 0; i < rawChannelProps.length; i++) {295        var prop = rawChannelProps[i];296        if (channelProps.indexOf(prop) < 0) {297          throw new Error('Raw channel missing property: ' + prop);298        }299      }300      this._websocket = rawChannel;301      this._websocket.binaryType = "arraybuffer";302      this._websocket.onmessage = this._recvMessage.bind(this);303      this._websocket.onopen = function () {304        Log.Debug('>> WebSock.onopen');305        if (_this._websocket.protocol) {306          Log.Info("Server choose sub-protocol: " + _this._websocket.protocol);307        }308        _this._eventHandlers.open();309        Log.Debug("<< WebSock.onopen");310      };311      this._websocket.onclose = function (e) {312        Log.Debug(">> WebSock.onclose");313        _this._eventHandlers.close(e);314        Log.Debug("<< WebSock.onclose");315      };316      this._websocket.onerror = function (e) {317        Log.Debug(">> WebSock.onerror: " + e);318        _this._eventHandlers.error(e);319        Log.Debug("<< WebSock.onerror: " + e);320      };321    }322  }, {323    key: "close",324    value: function close() {325      if (this._websocket) {326        if (this.readyState === 'connecting' || this.readyState === 'open') {327          Log.Info("Closing WebSocket connection");328          this._websocket.close();329        }330        this._websocket.onmessage = function () {};331      }332    }333334    // private methods335336    // We want to move all the unread data to the start of the queue,337    // e.g. compacting.338    // The function also expands the receive que if needed, and for339    // performance reasons we combine these two actions to avoid340    // unnecessary copying.341  }, {342    key: "_expandCompactRQ",343    value: function _expandCompactRQ(minFit) {344      // if we're using less than 1/8th of the buffer even with the incoming bytes, compact in place345      // instead of resizing346      var requiredBufferSize = (this._rQlen - this._rQi + minFit) * 8;347      var resizeNeeded = this._rQbufferSize < requiredBufferSize;348      if (resizeNeeded) {349        // Make sure we always *at least* double the buffer size, and have at least space for 8x350        // the current amount of data351        this._rQbufferSize = Math.max(this._rQbufferSize * 2, requiredBufferSize);352      }353354      // we don't want to grow unboundedly355      if (this._rQbufferSize > MAX_RQ_GROW_SIZE) {356        this._rQbufferSize = MAX_RQ_GROW_SIZE;357        if (this._rQbufferSize - (this._rQlen - this._rQi) < minFit) {358          throw new Error("Receive queue buffer exceeded " + MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit");359        }360      }361      if (resizeNeeded) {362        var oldRQbuffer = this._rQ.buffer;363        this._rQ = new Uint8Array(this._rQbufferSize);364        this._rQ.set(new Uint8Array(oldRQbuffer, this._rQi, this._rQlen - this._rQi));365      } else {366        this._rQ.copyWithin(0, this._rQi, this._rQlen);367      }368      this._rQlen = this._rQlen - this._rQi;369      this._rQi = 0;370    }371372    // push arraybuffer values onto the end of the receive que373  }, {374    key: "_recvMessage",375    value: function _recvMessage(e) {376      if (this._rQlen == this._rQi) {377        // All data has now been processed, this means we378        // can reset the receive queue.379        this._rQlen = 0;380        this._rQi = 0;381      }382      var u8 = new Uint8Array(e.data);383      if (u8.length > this._rQbufferSize - this._rQlen) {384        this._expandCompactRQ(u8.length);385      }386      this._rQ.set(u8, this._rQlen);387      this._rQlen += u8.length;388      if (this._rQlen - this._rQi > 0) {389        this._eventHandlers.message();390      } else {391        Log.Debug("Ignoring empty message");392      }393    }394  }]);395}();