Integrate WebChannel into RFB

The main change is to the connect() method which now checks the urlOrChannel variable to determine which arguments to pass to WebChannel.open. The url case remains largely the same, we simply check that it is of type string. If a WebSocket or RTCDataChannel is passed, we use the object prototypes constructor name to determine the type of the instance variable provided is one which we expect and then forward it on to WebChannel.open, along with the name so we dont have to do the same work in WebChannel. We use Object.getPrototypeOf because accessing the __proto__ directly is not recommended.
This commit is contained in:
Ryan Castner 2020-01-31 10:34:14 -05:00
parent 1eff49d201
commit 1ab3479130
1 changed files with 24 additions and 13 deletions

View File

@ -15,7 +15,7 @@ import Display from "./display.js";
import Keyboard from "./input/keyboard.js"; import Keyboard from "./input/keyboard.js";
import Mouse from "./input/mouse.js"; import Mouse from "./input/mouse.js";
import Cursor from "./util/cursor.js"; import Cursor from "./util/cursor.js";
import Websock from "./websock.js"; import WebChannel from "./websock.js";
import DES from "./des.js"; import DES from "./des.js";
import KeyTable from "./input/keysym.js"; import KeyTable from "./input/keysym.js";
import XtScancode from "./input/xtscancodes.js"; import XtScancode from "./input/xtscancodes.js";
@ -34,18 +34,18 @@ const DISCONNECT_TIMEOUT = 3;
const DEFAULT_BACKGROUND = 'rgb(40, 40, 40)'; const DEFAULT_BACKGROUND = 'rgb(40, 40, 40)';
export default class RFB extends EventTargetMixin { export default class RFB extends EventTargetMixin {
constructor(target, url, options) { constructor(target, urlOrChannel, options) {
if (!target) { if (!target) {
throw new Error("Must specify target"); throw new Error("Must specify target");
} }
if (!url) { if (!urlOrChannel) {
throw new Error("Must specify URL"); throw new Error("Must specify URL or WebSocket / RTCDataChannel");
} }
super(); super();
this._target = target; this._target = target;
this._url = url; this._urlOrChannel = urlOrChannel;
// Connection details // Connection details
options = options || {}; options = options || {};
@ -85,7 +85,7 @@ export default class RFB extends EventTargetMixin {
this._qemuExtKeyEventSupported = false; this._qemuExtKeyEventSupported = false;
// Internal objects // Internal objects
this._sock = null; // Websock object this._sock = null; // WebSocket or RTCDataChannel object
this._display = null; // Display object this._display = null; // Display object
this._flushing = false; // Display flushing state this._flushing = false; // Display flushing state
this._keyboard = null; // Keyboard input handler object this._keyboard = null; // Keyboard input handler object
@ -180,7 +180,7 @@ export default class RFB extends EventTargetMixin {
this._mouse.onmousebutton = this._handleMouseButton.bind(this); this._mouse.onmousebutton = this._handleMouseButton.bind(this);
this._mouse.onmousemove = this._handleMouseMove.bind(this); this._mouse.onmousemove = this._handleMouseMove.bind(this);
this._sock = new Websock(); this._sock = new WebChannel();
this._sock.on('message', () => { this._sock.on('message', () => {
this._handle_message(); this._handle_message();
}); });
@ -195,7 +195,7 @@ export default class RFB extends EventTargetMixin {
} }
}); });
this._sock.on('close', (e) => { this._sock.on('close', (e) => {
Log.Debug("WebSocket on-close event"); Log.Debug("WebChannel on-close event");
let msg = ""; let msg = "";
if (e.code) { if (e.code) {
msg = "(code: " + e.code; msg = "(code: " + e.code;
@ -228,7 +228,7 @@ export default class RFB extends EventTargetMixin {
} }
this._sock.off('close'); this._sock.off('close');
}); });
this._sock.on('error', e => Log.Warn("WebSocket on-error event")); this._sock.on('error', e => Log.Warn("WebChannel on-error event"));
// Slight delay of the actual connection so that the caller has // Slight delay of the actual connection so that the caller has
// time to set up callbacks // time to set up callbacks
@ -398,11 +398,22 @@ export default class RFB extends EventTargetMixin {
_connect() { _connect() {
Log.Debug(">> RFB.connect"); Log.Debug(">> RFB.connect");
Log.Info("connecting to " + this._url);
try { try {
// WebSocket.onopen transitions to the RFB init states // WebChannel.onopen transitions to the RFB init states
this._sock.open(this._url, this._wsProtocols); if (typeof this._urlOrChannel === "string") {
Log.Info(`connecting to ${this._urlOrChannel}`);
this._sock.open({ uri: this._urlOrChannel, protocols: this._wsProtocols });
} else {
let proto = Object.getPrototypeOf(this._urlOrChannel);
let protoName = proto && proto.constructor && proto.constructor.name || "";
Log.Info(`connecting with established ${protoName}`);
if (protoName === "WebSocket" || protoName === "RTCDataChannel") {
this._sock.open({ webChannel: this._urlOrChannel, channelType: protoName });
} else {
throw new Error("Expected url and protocols or established WebSocket / RTCDataChannel object");
}
}
} catch (e) { } catch (e) {
if (e.name === 'SyntaxError') { if (e.name === 'SyntaxError') {
this._fail("Invalid host or port (" + e + ")"); this._fail("Invalid host or port (" + e + ")");