Files
noVNC/tests/playback.js
T

195 lines
5.6 KiB
JavaScript
Raw Normal View History

2010-09-08 10:11:11 -05:00
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2012 Joel Martin
* Licensed under MPL 2.0 (see LICENSE.txt)
2010-09-08 10:11:11 -05:00
*/
2017-03-01 21:10:09 -05:00
import RFB from '../core/rfb.js';
import * as Log from '../core/util/logging.js';
import Base64 from '../core/base64.js';
2016-10-24 17:37:21 +02:00
// Immediate polyfill
2017-03-01 21:10:09 -05:00
if (setImmediate === undefined) {
2016-10-24 17:37:21 +02:00
var _immediateIdCounter = 1;
var _immediateFuncs = {};
2017-03-01 21:10:09 -05:00
var setImmediate = function (func) {
var index = _immediateIdCounter++;
2016-10-24 17:37:21 +02:00
_immediateFuncs[index] = func;
window.postMessage("noVNC immediate trigger:" + index, "*");
return index;
};
window.clearImmediate = function (id) {
_immediateFuncs[id];
};
var _onMessage = function (event) {
if ((typeof event.data !== "string") ||
(event.data.indexOf("noVNC immediate trigger:") !== 0)) {
return;
}
var index = event.data.slice("noVNC immediate trigger:".length);
var callback = _immediateFuncs[index];
if (callback === undefined) {
return;
}
delete _immediateFuncs[index];
callback();
};
window.addEventListener("message", _onMessage);
}
2017-11-05 21:47:06 +01:00
export default function RecordingPlayer (frames, encoding, disconnected) {
2017-03-01 21:10:09 -05:00
this._frames = frames;
this._encoding = encoding;
2015-05-15 14:27:23 -04:00
2017-03-01 21:10:09 -05:00
this._disconnected = disconnected;
2015-05-15 14:27:23 -04:00
2017-03-01 21:10:09 -05:00
if (this._encoding === undefined) {
let frame = this._frames[0];
let start = frame.indexOf('{', 1) + 1;
2016-10-05 10:20:17 +02:00
if (frame.slice(start).startsWith('UkZC')) {
2017-03-01 21:10:09 -05:00
this._encoding = 'base64';
2016-10-05 10:20:17 +02:00
} else {
2017-03-01 21:10:09 -05:00
this._encoding = 'binary';
2016-10-05 10:20:17 +02:00
}
}
2017-03-01 21:10:09 -05:00
this._rfb = undefined;
this._frame_length = this._frames.length;
2017-03-01 21:10:09 -05:00
this._frame_index = 0;
this._start_time = undefined;
this._realtime = true;
this._trafficManagement = true;
2017-03-01 21:10:09 -05:00
this._running = false;
2017-03-01 21:10:09 -05:00
this.onfinish = function () {};
}
2017-03-01 21:10:09 -05:00
RecordingPlayer.prototype = {
run: function (realtime, trafficManagement) {
// initialize a new RFB
2017-10-20 16:46:36 +02:00
this._rfb = new RFB(document.getElementById('VNC_canvas'), 'wss://test');
2017-10-14 15:39:56 +02:00
this._rfb.viewOnly = true;
this._rfb.addEventListener("disconnect",
this._handleDisconnect.bind(this));
2017-03-01 21:10:09 -05:00
this._enablePlaybackMode();
// reset the frame index and timer
this._frame_index = 0;
this._start_time = (new Date()).getTime();
this._realtime = realtime;
this._trafficManagement = (trafficManagement === undefined) ? !realtime : trafficManagement;
this._running = true;
this._queueNextPacket();
},
// _enablePlaybackMode mocks out things not required for running playback
_enablePlaybackMode: function () {
this._rfb._sock.send = function (arr) {};
this._rfb._sock.close = function () {};
this._rfb._sock.flush = function () {};
this._rfb._checkEvents = function () {};
2017-10-20 16:46:36 +02:00
this._rfb._connect = function () {
2017-03-01 21:10:09 -05:00
this._sock.init('binary', 'ws');
};
},
_queueNextPacket: function () {
if (!this._running) { return; }
var frame = this._frames[this._frame_index];
// skip send frames
while (this._frame_index < this._frame_length && frame.charAt(0) === "}") {
this._frame_index++;
frame = this._frames[this._frame_index];
}
2017-03-01 21:10:09 -05:00
if (frame === 'EOF') {
Log.Debug('Finished, found EOF');
this._finish();
return;
}
2017-03-01 21:10:09 -05:00
if (this._frame_index >= this._frame_length) {
Log.Debug('Finished, no more frames');
this._finish();
return;
}
2017-03-01 21:10:09 -05:00
if (this._realtime) {
let foffset = frame.slice(1, frame.indexOf('{', 1));
let toffset = (new Date()).getTime() - this._start_time;
let delay = foffset - toffset;
if (delay < 1) delay = 1;
2017-03-01 21:10:09 -05:00
setTimeout(this._doPacket.bind(this), delay);
} else {
setImmediate(this._doPacket.bind(this));
}
},
_doPacket: function () {
// Avoid having excessive queue buildup in non-realtime mode
2017-06-01 12:50:00 +02:00
if (this._trafficManagement && this._rfb._flushing) {
2017-03-01 21:10:09 -05:00
let player = this;
2017-10-14 15:39:56 +02:00
let orig = this._rfb._display.onflush;
this._rfb._display.onflush = function () {
player._rfb._display.onflush = orig;
2017-06-01 12:50:00 +02:00
player._rfb._onFlush();
2017-03-01 21:10:09 -05:00
player._doPacket();
2017-10-14 15:39:56 +02:00
};
2017-03-01 21:10:09 -05:00
return;
}
2017-03-01 21:10:09 -05:00
const frame = this._frames[this._frame_index];
var start = frame.indexOf('{', 1) + 1;
if (this._encoding === 'base64') {
var u8 = Base64.decode(frame.slice(start));
start = 0;
} else {
var u8 = new Uint8Array(frame.length - start);
for (let i = 0; i < frame.length - start; i++) {
u8[i] = frame.charCodeAt(start + i);
}
}
2017-03-01 21:10:09 -05:00
this._rfb._sock._recv_message({'data': u8});
this._frame_index++;
this._queueNextPacket();
},
_finish() {
if (this._rfb._display.pending()) {
var player = this;
2017-10-14 15:39:56 +02:00
this._rfb._display.onflush = function () {
2017-03-01 21:10:09 -05:00
if (player._rfb._flushing) {
player._rfb._onFlush();
}
player._finish();
2017-10-14 15:39:56 +02:00
};
2017-03-01 21:10:09 -05:00
this._rfb._display.flush();
} else {
this._running = false;
this.onfinish((new Date()).getTime() - this._start_time);
}
2017-03-01 21:10:09 -05:00
},
_handleDisconnect(rfb, clean) {
2017-03-01 21:10:09 -05:00
this._running = false;
this._disconnected(rfb, clean, this._frame_index);
2017-03-01 21:10:09 -05:00
}
2010-09-08 10:11:11 -05:00
};