| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- /*
- * noVNC: HTML5 VNC client
- * Copyright (C) 2018 The noVNC Authors
- * Licensed under MPL 2.0 (see LICENSE.txt)
- */
- import RFB from '../core/rfb.js';
- import * as Log from '../core/util/logging.js';
- // Immediate polyfill
- if (window.setImmediate === undefined) {
- let _immediateIdCounter = 1;
- const _immediateFuncs = {};
- window.setImmediate = (func) => {
- const index = _immediateIdCounter++;
- _immediateFuncs[index] = func;
- window.postMessage("noVNC immediate trigger:" + index, "*");
- return index;
- };
- window.clearImmediate = (id) => {
- _immediateFuncs[id];
- };
- window.addEventListener("message", (event) => {
- if ((typeof event.data !== "string") ||
- (event.data.indexOf("noVNC immediate trigger:") !== 0)) {
- return;
- }
- const index = event.data.slice("noVNC immediate trigger:".length);
- const callback = _immediateFuncs[index];
- if (callback === undefined) {
- return;
- }
- delete _immediateFuncs[index];
- callback();
- });
- }
- class FakeWebSocket {
- constructor() {
- this.binaryType = "arraybuffer";
- this.protocol = "";
- this.readyState = "open";
- this.onerror = () => {};
- this.onmessage = () => {};
- this.onopen = () => {};
- }
- send() {
- }
- close() {
- }
- }
- export default class RecordingPlayer {
- constructor(frames, disconnected) {
- this._frames = frames;
- this._disconnected = disconnected;
- this._rfb = undefined;
- this._frameLength = this._frames.length;
- this._frameIndex = 0;
- this._startTime = undefined;
- this._realtime = true;
- this._trafficManagement = true;
- this._running = false;
- this.onfinish = () => {};
- }
- run(realtime, trafficManagement) {
- // initialize a new RFB
- this._ws = new FakeWebSocket();
- this._rfb = new RFB(document.getElementById('VNC_screen'), this._ws);
- this._rfb.viewOnly = true;
- this._rfb.addEventListener("disconnect",
- this._handleDisconnect.bind(this));
- this._rfb.addEventListener("credentialsrequired",
- this._handleCredentials.bind(this));
- // reset the frame index and timer
- this._frameIndex = 0;
- this._startTime = (new Date()).getTime();
- this._realtime = realtime;
- this._trafficManagement = (trafficManagement === undefined) ? !realtime : trafficManagement;
- this._running = true;
- this._queueNextPacket();
- }
- _queueNextPacket() {
- if (!this._running) { return; }
- let frame = this._frames[this._frameIndex];
- // skip send frames
- while (this._frameIndex < this._frameLength && frame.fromClient) {
- this._frameIndex++;
- frame = this._frames[this._frameIndex];
- }
- if (this._frameIndex >= this._frameLength) {
- Log.Debug('Finished, no more frames');
- this._finish();
- return;
- }
- if (this._realtime) {
- const toffset = (new Date()).getTime() - this._startTime;
- let delay = frame.timestamp - toffset;
- if (delay < 1) delay = 1;
- setTimeout(this._doPacket.bind(this), delay);
- } else {
- setImmediate(this._doPacket.bind(this));
- }
- }
- _doPacket() {
- // Avoid having excessive queue buildup in non-realtime mode
- if (this._trafficManagement && this._rfb._flushing) {
- const orig = this._rfb._display.onflush;
- this._rfb._display.onflush = () => {
- this._rfb._display.onflush = orig;
- this._rfb._onFlush();
- this._doPacket();
- };
- return;
- }
- const frame = this._frames[this._frameIndex];
- this._ws.onmessage({'data': frame.data});
- this._frameIndex++;
- this._queueNextPacket();
- }
- _finish() {
- if (this._rfb._display.pending()) {
- this._rfb._display.onflush = () => {
- if (this._rfb._flushing) {
- this._rfb._onFlush();
- }
- this._finish();
- };
- this._rfb._display.flush();
- } else {
- this._running = false;
- this._ws.onclose({code: 1000, reason: ""});
- delete this._rfb;
- this.onfinish((new Date()).getTime() - this._startTime);
- }
- }
- _handleDisconnect(evt) {
- this._running = false;
- this._disconnected(evt.detail.clean, this._frameIndex);
- }
- _handleCredentials(evt) {
- this._rfb.sendCredentials({"username": "Foo",
- "password": "Bar",
- "target": "Baz"});
- }
- }
|