mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-23 21:55:52 -05:00
First pass at adding WebRTC support.
This commit is contained in:
parent
65d6775303
commit
92aaf754fb
Binary file not shown.
Binary file not shown.
BIN
agents/agent_debug/MeshService.exe
Normal file
BIN
agents/agent_debug/MeshService.exe
Normal file
Binary file not shown.
BIN
agents/agent_debug/MeshService64.exe
Normal file
BIN
agents/agent_debug/MeshService64.exe
Normal file
Binary file not shown.
@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@ -20,7 +20,6 @@ function createMeshCore(agent) {
|
||||
// MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent.
|
||||
obj.meshCoreInfo = "MeshCore v4";
|
||||
obj.meshCoreCapabilities = 14; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
|
||||
obj.useNativePipes = true; //(process.platform == 'win32');
|
||||
var meshServerConnectionState = 0;
|
||||
var tunnels = {};
|
||||
var lastSelfInfo = null;
|
||||
@ -54,6 +53,7 @@ function createMeshCore(agent) {
|
||||
scan.scan("10.2.55.128/25", 2000);
|
||||
*/
|
||||
|
||||
/*
|
||||
// Try to load up the network monitor
|
||||
try {
|
||||
networkMonitor = require('NetworkMonitor');
|
||||
@ -61,6 +61,7 @@ function createMeshCore(agent) {
|
||||
networkMonitor.on('add', function (addr) { sendNetworkUpdateNagle(); });
|
||||
networkMonitor.on('remove', function (addr) { sendNetworkUpdateNagle(); });
|
||||
} catch (e) { networkMonitor = null; }
|
||||
*/
|
||||
|
||||
// Try to load up the Intel AMT scanner
|
||||
try {
|
||||
@ -506,28 +507,7 @@ function createMeshCore(agent) {
|
||||
if (len > 0) { this.write(buf.slice(0, len)); } else { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; this.end(); }
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup remote desktop & terminal without using native pipes
|
||||
if ((this.httprequest.desktop) && (obj.useNativePipes == false)) {
|
||||
if (data.length > 21 && data.toString().startsWith('**********%%%%%%###**')) {
|
||||
var controlMsg = JSON.parse(data.toString().substring(21));
|
||||
if (controlMsg.type == 'offer') {
|
||||
this.webrtc = rtc.createConnection();
|
||||
this.webrtc.on('connected', function () { sendConsoleText('OnWebRTC_Connected'); });
|
||||
this.webrtc.on('dataChannel', function () { sendConsoleText('OnWebRTC_DataChannel'); });
|
||||
var counterOffer = this.webrtc.setOffer(controlMsg.sdp);
|
||||
this.write('**********%%%%%%###**' + JSON.stringify({ type: 'answer', sdp: counterOffer }));
|
||||
sendConsoleText('counterOfferSent');
|
||||
} else {
|
||||
sendConsoleText(JSON.stringify(controlMsg));
|
||||
}
|
||||
} else {
|
||||
this.httprequest.desktop.kvm.write(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((this.httprequest.terminal) && (obj.useNativePipes == false)) { this.httprequest.terminal.write(data); return; }
|
||||
|
||||
|
||||
if (this.httprequest.state == 0) {
|
||||
// Check if this is a relay connection
|
||||
if (data == 'c') { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); }
|
||||
@ -538,59 +518,39 @@ function createMeshCore(agent) {
|
||||
this.httprequest.protocol = parseInt(data);
|
||||
if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
|
||||
if (this.httprequest.protocol == 1) {
|
||||
if (obj.useNativePipes == false) {
|
||||
// Remote Terminal without using native pipes
|
||||
if (process.platform == "win32") {
|
||||
this.httprequest.terminal = childProcess.execFile("%windir%\\system32\\cmd.exe");
|
||||
} else {
|
||||
this.httprequest.terminal = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
|
||||
}
|
||||
this.httprequest.terminal.tunnel = this;
|
||||
this.httprequest.terminal.on('exit', function (ecode, sig) { this.tunnel.end(); });
|
||||
this.httprequest.terminal.stdout.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
|
||||
this.httprequest.terminal.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
|
||||
// Remote terminal using native pipes
|
||||
if (process.platform == "win32") {
|
||||
this.httprequest.process = childProcess.execFile("%windir%\\system32\\cmd.exe");
|
||||
} else {
|
||||
// Remote terminal using native pipes
|
||||
if (process.platform == "win32") {
|
||||
this.httprequest.process = childProcess.execFile("%windir%\\system32\\cmd.exe");
|
||||
} else {
|
||||
this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
|
||||
}
|
||||
this.httprequest.process.tunnel = this;
|
||||
this.httprequest.process.on('exit', function (ecode, sig) { this.tunnel.end(); });
|
||||
this.httprequest.process.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
|
||||
this.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
this.pipe(this.httprequest.process.stdin, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
|
||||
this.prependListener('end', function () { this.httprequest.process.kill(); });
|
||||
this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
|
||||
}
|
||||
this.httprequest.process.tunnel = this;
|
||||
this.httprequest.process.on('exit', function (ecode, sig) { this.tunnel.end(); });
|
||||
this.httprequest.process.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
|
||||
this.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
this.pipe(this.httprequest.process.stdin, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
|
||||
this.prependListener('end', function () { this.httprequest.process.kill(); });
|
||||
this.removeAllListeners('data');
|
||||
this.on('data', onTunnelControlData);
|
||||
//this.write('MeshCore Terminal Hello!1');
|
||||
}
|
||||
if (this.httprequest.protocol == 2) {
|
||||
if (obj.useNativePipes == false) {
|
||||
// Remote Desktop without using native pipes
|
||||
this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(), tunnel: this };
|
||||
this.httprequest.desktop.kvm.tunnel = this;
|
||||
this.httprequest.desktop.kvm.on('data', function (data) { this.tunnel.write(data); });
|
||||
this.desktop = this.httprequest.desktop;
|
||||
this.end = function () { if (--this.desktop.kvm.connectionCount == 0) { this.httprequest.desktop.kvm.end(); } };
|
||||
if (this.httprequest.desktop.kvm.hasOwnProperty("connectionCount")) { this.httprequest.desktop.kvm.connectionCount++; } else { this.httprequest.desktop.kvm.connectionCount = 1; }
|
||||
} else {
|
||||
// Remote desktop using native pipes
|
||||
this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(), tunnel: this };
|
||||
this.httprequest.desktop.kvm.parent = this.httprequest.desktop;
|
||||
this.desktop = this.httprequest.desktop;
|
||||
this.end = function () {
|
||||
--this.desktop.kvm.connectionCount;
|
||||
this.unpipe(this.httprequest.desktop.kvm);
|
||||
this.httprequest.desktop.kvm.unpipe(this);
|
||||
if (this.desktop.kvm.connectionCount == 0) { this.httprequest.desktop.kvm.end(); }
|
||||
};
|
||||
if (this.httprequest.desktop.kvm.hasOwnProperty("connectionCount")) { this.httprequest.desktop.kvm.connectionCount++; } else { this.httprequest.desktop.kvm.connectionCount = 1; }
|
||||
//this.write('Hello!');
|
||||
//sendConsoleText('KVM WriteHello');
|
||||
this.pipe(this.httprequest.desktop.kvm, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
this.httprequest.desktop.kvm.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
//this.on('data', function (data) { sendConsoleText('KVM: ' + data); });
|
||||
}
|
||||
// Remote desktop using native pipes
|
||||
this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(), tunnel: this };
|
||||
this.httprequest.desktop.kvm.parent = this.httprequest.desktop;
|
||||
this.desktop = this.httprequest.desktop;
|
||||
this.end = function () {
|
||||
--this.desktop.kvm.connectionCount;
|
||||
this.unpipe(this.httprequest.desktop.kvm);
|
||||
this.httprequest.desktop.kvm.unpipe(this);
|
||||
if (this.desktop.kvm.connectionCount == 0) { this.httprequest.desktop.kvm.end(); }
|
||||
};
|
||||
if (this.httprequest.desktop.kvm.hasOwnProperty("connectionCount")) { this.httprequest.desktop.kvm.connectionCount++; } else { this.httprequest.desktop.kvm.connectionCount = 1; }
|
||||
this.pipe(this.httprequest.desktop.kvm, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
this.httprequest.desktop.kvm.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
this.removeAllListeners('data');
|
||||
this.on('data', onTunnelControlData);
|
||||
//this.write('MeshCore KVM Hello!1');
|
||||
}
|
||||
else if (this.httprequest.protocol == 5) {
|
||||
// Setup files
|
||||
@ -700,7 +660,49 @@ function createMeshCore(agent) {
|
||||
//sendConsoleText("Got tunnel #" + this.httprequest.index + " data: " + data, this.httprequest.sessionid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Attempt to setup and switch the tunnel over to WebRTC
|
||||
function onTunnelControlData(data) {
|
||||
sendConsoleText('onTunnelControlData: ' + data);
|
||||
var obj = JSON.parse(data);
|
||||
if (obj.type == 'offer') {
|
||||
// This is a WebRTC offer.
|
||||
this.webrtc = rtc.createConnection();
|
||||
this.webrtc.websocket = this;
|
||||
this.webrtc.on('connected', function () { sendConsoleText('WebRTC connected'); });
|
||||
this.webrtc.on('dataChannel', function (rtcchannel) {
|
||||
sendConsoleText('WebRTC Datachannel open, protocol: ' + this.websocket.httprequest.protocol);
|
||||
this.rtcchannel = rtcchannel;
|
||||
if (this.websocket.httprequest.protocol == 1) { // Terminal
|
||||
// This is a terminal data stream, re-setup the pipes
|
||||
// Un-pipe
|
||||
this.websocket.unpipe(this.websocket.httprequest.process.stdin);
|
||||
//this.websocket.httprequest.process.stdout.unpipe(this.websocket);
|
||||
// Re-pipe
|
||||
rtcchannel.pipe(this.websocket.httprequest.process.stdin, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
//this.websocket.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text.
|
||||
} else if (this.websocket.httprequest.protocol == 2) { // Desktop
|
||||
// This is a KVM data stream, re-setup the pipes
|
||||
// Un-pipe
|
||||
this.websocket.unpipe(this.websocket.httprequest.desktop.kvm);
|
||||
//this.websocket.httprequest.desktop.kvm.unpipe(this.websocket);
|
||||
// Re-pipe
|
||||
rtcchannel.pipe(this.websocket.httprequest.desktop.kvm, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
//this.websocket.httprequest.desktop.kvm.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
|
||||
}
|
||||
/*
|
||||
else {
|
||||
// Debug, just display on agent console
|
||||
rtcchannel.on('data', function (buffer) { sendConsoleText("RTCReceived: " + buffer.length + " bytes"); });
|
||||
rtcchannel.on('end', function () { sendConsoleText("RTCChannel: " + this.name + " was closed"); });
|
||||
channel.write('WebRTC HELLO!');
|
||||
}
|
||||
*/
|
||||
});
|
||||
this.write({ type: "answer", sdp: this.webrtc.setOffer(obj.sdp) });
|
||||
}
|
||||
}
|
||||
|
||||
// Console state
|
||||
var consoleWebSockets = {};
|
||||
var consoleHttpRequest = null;
|
||||
@ -740,7 +742,7 @@ function createMeshCore(agent) {
|
||||
break;
|
||||
}
|
||||
case 'info': { // Return information about the agent and agent core module
|
||||
response = 'Current Core: ' + obj.meshCoreInfo + '.\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform Info: ' + process.platform + '.\r\nCapabilities: ' + obj.meshCoreCapabilities + '.\r\nNative Pipes: ' + obj.useNativePipes + '.\r\nServer URL: ' + mesh.ServerUrl + '.';
|
||||
response = 'Current Core: ' + obj.meshCoreInfo + '.\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform Info: ' + process.platform + '.\r\nCapabilities: ' + obj.meshCoreCapabilities + '.\r\nServer URL: ' + mesh.ServerUrl + '.';
|
||||
if (amtLmsState >= 0) { response += '\r\nBuilt -in LMS: ' + ['Disabled', 'Connecting..', 'Connected'][amtLmsState] + '.'; }
|
||||
response += '\r\nModules: ' + JSON.stringify(addedModules) + '';
|
||||
response += '\r\nServerConnected: ' + mesh.isControlChannelConnected + '';
|
||||
|
@ -203,17 +203,19 @@ module.exports.CertificateOperations = function () {
|
||||
}
|
||||
|
||||
// If CA certificates are present, load them
|
||||
var caok, caindex = 1, calist = [];
|
||||
do {
|
||||
caok = false;
|
||||
if (obj.fileExists(directory + '/webserver-cert-chain' + caindex + '.crt')) {
|
||||
var caCertificate = obj.fs.readFileSync(directory + '/webserver-cert-chain' + caindex + '.crt', 'utf8');
|
||||
calist.push(caCertificate);
|
||||
caok = true;
|
||||
}
|
||||
caindex++;
|
||||
} while (caok == true);
|
||||
r.web.ca = calist;
|
||||
if (r.web != null) {
|
||||
var caok, caindex = 1, calist = [];
|
||||
do {
|
||||
caok = false;
|
||||
if (obj.fileExists(directory + '/webserver-cert-chain' + caindex + '.crt')) {
|
||||
var caCertificate = obj.fs.readFileSync(directory + '/webserver-cert-chain' + caindex + '.crt', 'utf8');
|
||||
calist.push(caCertificate);
|
||||
caok = true;
|
||||
}
|
||||
caindex++;
|
||||
} while (caok == true);
|
||||
r.web.ca = calist;
|
||||
}
|
||||
|
||||
// Decode certificate arguments
|
||||
var commonName = 'un-configured', country, organization, forceWebCertGen = 0;
|
||||
@ -374,7 +376,7 @@ module.exports.CertificateOperations = function () {
|
||||
amtConsoleName = consoleCertAndKey.cert.subject.getField('CN').value;
|
||||
}
|
||||
|
||||
var r = { root: { cert: rootCertificate, key: rootPrivateKey }, web: { cert: webCertificate, key: webPrivateKey }, mps: { cert: mpsCertificate, key: mpsPrivateKey }, agent: { cert: agentCertificate, key: agentPrivateKey }, console: { cert: consoleCertificate, key: consolePrivateKey }, ca: calist, CommonName: commonName, RootName: rootName, AmtConsoleName: amtConsoleName, dns: {} };
|
||||
var r = { root: { cert: rootCertificate, key: rootPrivateKey }, web: { cert: webCertificate, key: webPrivateKey, ca: [] }, mps: { cert: mpsCertificate, key: mpsPrivateKey }, agent: { cert: agentCertificate, key: agentPrivateKey }, console: { cert: consoleCertificate, key: consolePrivateKey }, ca: calist, CommonName: commonName, RootName: rootName, AmtConsoleName: amtConsoleName, dns: {} };
|
||||
|
||||
// Look for domains with DNS names that have no certificates and generated them.
|
||||
for (var i in config.domains) {
|
||||
|
@ -183,21 +183,32 @@ module.exports.CreateHttpInterceptor = function (args) {
|
||||
obj.ws.count -= rl;
|
||||
if (obj.ws.count == 0) { obj.ws.mode = 0; }
|
||||
return r;
|
||||
} else if (obj.ws.mode == 2) { // Chunked Body Mode
|
||||
} else if (obj.amt.mode == 2) { // Chunked Body Mode
|
||||
// Send data one chunk at a time
|
||||
var headerend = obj.ws.acc.indexOf('\r\n');
|
||||
var headerend = obj.amt.acc.indexOf('\r\n');
|
||||
if (headerend < 0) return "";
|
||||
var chunksize = parseInt(obj.ws.acc.substring(0, headerend), 16);
|
||||
if (chunksize == 0 && obj.ws.acc.length >= headerend + 4) {
|
||||
// Send the ending chunk (NOTE: We do not support trailing headers)
|
||||
var r = obj.ws.acc.substring(0, headerend + 4);
|
||||
obj.ws.acc = obj.ws.acc.substring(headerend + 4);
|
||||
obj.ws.mode = 0;
|
||||
var chunksize = parseInt(obj.amt.acc.substring(0, headerend), 16);
|
||||
if (isNaN(chunksize)) { // TODO: Check this path
|
||||
// Chunk is not in this batch, move one
|
||||
var r = obj.amt.acc.substring(0, headerend + 2);
|
||||
obj.amt.acc = obj.amt.acc.substring(headerend + 2);
|
||||
// Peek if we next is the end of chunked transfer
|
||||
headerend = obj.amt.acc.indexOf('\r\n');
|
||||
if (headerend > 0) {
|
||||
chunksize = parseInt(obj.amt.acc.substring(0, headerend), 16);
|
||||
if (chunksize == 0) { obj.amt.mode = 0; }
|
||||
}
|
||||
return r;
|
||||
} else if (chunksize > 0 && obj.ws.acc.length >= headerend + 4) {
|
||||
} else if (chunksize == 0 && obj.amt.acc.length >= headerend + 4) {
|
||||
// Send the ending chunk (NOTE: We do not support trailing headers)
|
||||
var r = obj.amt.acc.substring(0, headerend + 4);
|
||||
obj.amt.acc = obj.amt.acc.substring(headerend + 4);
|
||||
obj.amt.mode = 0;
|
||||
return r;
|
||||
} else if (chunksize > 0 && obj.amt.acc.length >= headerend + 4) {
|
||||
// Send a chunk
|
||||
var r = obj.ws.acc.substring(0, headerend + chunksize + 4);
|
||||
obj.ws.acc = obj.ws.acc.substring(headerend + chunksize + 4);
|
||||
var r = obj.amt.acc.substring(0, headerend + chunksize + 4);
|
||||
obj.amt.acc = obj.amt.acc.substring(headerend + chunksize + 4);
|
||||
return r;
|
||||
}
|
||||
} else if (obj.ws.mode == 3) { // Until Close Mode
|
||||
|
12
meshrelay.js
12
meshrelay.js
@ -175,16 +175,16 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ws.flushSink = function () {
|
||||
try { ws.resume(); } catch (e) { }
|
||||
};
|
||||
|
||||
ws.flushSink = function () { try { ws.resume(); } catch (e) { } };
|
||||
|
||||
// When data is received from the mesh relay web socket
|
||||
ws.on('message', function (data) {
|
||||
//console.log(typeof data, data.length);
|
||||
//if (typeof data == 'string') console.log(data);
|
||||
if (this.peer != null) { try { this.pause(); this.peer.send(data, ws.flushSink); } catch (e) { } }
|
||||
if (this.peer != null) {
|
||||
//if (typeof data == 'string') { console.log('Relay: ' + data); }
|
||||
try { this.pause(); this.peer.send(data, ws.flushSink); } catch (e) { }
|
||||
}
|
||||
});
|
||||
|
||||
// If error, do nothing
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.1.2-s",
|
||||
"version": "0.1.2-t",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
@ -172,7 +172,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
|
||||
obj.ProcessData = function (str) {
|
||||
if (str.length < 4) return;
|
||||
var cmdmsg = null, X = 0, Y = 0, command = ReadShort(str, 0), cmdsize = ReadShort(str, 2);
|
||||
if (command >= 18) { console.error("Invalid KVM command " + command + " of size " + cmdsize); obj.parent.Stop(); return; }
|
||||
if (command >= 18) { console.error("Invalid KVM command " + command + " of size " + cmdsize); console.log("Invalid KVM data", str.length, str, rstr2hex(str)); return; }
|
||||
if (cmdsize > str.length) { console.error("KVM invalid command size", cmdsize, str.length); return; }
|
||||
//meshOnDebug("KVM Command: " + command + " Len:" + cmdsize);
|
||||
if (obj.debugmode == 1) { console.log("KVM Command: " + command + " Len:" + cmdsize); }
|
||||
|
@ -17,6 +17,7 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||
obj.tunnelid = Math.random().toString(36).substring(2); // Generate a random client tunnel id
|
||||
obj.protocol = module.protocol; // 1 = SOL, 2 = KVM, 3 = IDER, 4 = Files, 5 = FileTransfer
|
||||
obj.attemptWebRTC = false;
|
||||
obj.webRtcActive = false;
|
||||
obj.webrtc = null;
|
||||
obj.webchannel = null;
|
||||
obj.onStateChanged = null;
|
||||
@ -49,12 +50,10 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||
|
||||
// Called to pass websocket control messages
|
||||
obj.xxOnControlCommand = function (msg) {
|
||||
//console.log(msg);
|
||||
//obj.socket.send('hellobob');
|
||||
var controlMsg = JSON.parse(msg);
|
||||
if ((controlMsg.type == 'answer') && (obj.webrtc != null)) {
|
||||
console.log('gotAnswer', JSON.stringify(controlMsg));
|
||||
obj.webrtc.setRemoteDescription(new RTCSessionDescription(controlMsg), function () { console.log('WebRTC remote ok'); }, obj.xxCloseWebRTC);
|
||||
//console.log('gotAnswer', JSON.stringify(controlMsg));
|
||||
obj.webrtc.setRemoteDescription(new RTCSessionDescription(controlMsg), function () { /*console.log('WebRTC remote ok');*/ }, obj.xxCloseWebRTC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +64,7 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||
}
|
||||
|
||||
obj.xxOnMessage = function (e) {
|
||||
if (obj.debugmode == 1) { console.log('Recv', e.data); }
|
||||
//if (obj.debugmode == 1) { console.log('Recv', e.data); }
|
||||
if (obj.State < 3) {
|
||||
if (e.data == 'c') {
|
||||
obj.socket.send(obj.protocol);
|
||||
@ -79,28 +78,27 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||
|
||||
if (obj.webrtc != null) {
|
||||
obj.webchannel = obj.webrtc.createDataChannel("DataChannel", {}); // { ordered: false, maxRetransmits: 2 }
|
||||
obj.webchannel.onmessage = function (event) { console.log("DataChannel - onmessage", event.data); };
|
||||
obj.webchannel.onopen = function () { console.log("DataChannel - onopen"); };
|
||||
obj.webchannel.onclose = function (event) { console.log("DataChannel - onclose"); }
|
||||
obj.webrtc.ondatachannel = function (e) { console.log('ondatachannel'); } // TODO: Should not be needed
|
||||
obj.webchannel.onmessage = function (event) { console.log("DataChannel - onmessage", event.data); obj.xxOnMessage(event.data); };
|
||||
obj.webchannel.onopen = function () { obj.webRtcActive = true; if (obj.onStateChanged != null) { obj.onStateChanged(obj, obj.State); } /*obj.webchannel.send("Browser WebRTC Hello!!!");*/ };
|
||||
obj.webchannel.onclose = function (event) { obj.Stop(); }
|
||||
obj.webrtc.onicecandidate = function (e) {
|
||||
if (e.candidate == null) {
|
||||
console.log('createOffer', JSON.stringify(obj.webrtcoffer));
|
||||
obj.socket.send('**********%%%%%%###**' + JSON.stringify(obj.webrtcoffer)); // End of candidates, send the offer
|
||||
//console.log('createOffer', JSON.stringify(obj.webrtcoffer));
|
||||
obj.socket.send(JSON.stringify(obj.webrtcoffer)); // End of candidates, send the offer
|
||||
} else {
|
||||
obj.webrtcoffer.sdp += ("a=" + e.candidate.candidate + "\r\n"); // New candidate, add it to the SDP
|
||||
}
|
||||
}
|
||||
obj.webrtc.oniceconnectionstatechange = function () {
|
||||
if (obj.webrtc != null) {
|
||||
console.log('oniceconnectionstatechange', obj.webrtc.iceConnectionState);
|
||||
//console.log('WebRTC ICE', obj.webrtc.iceConnectionState);
|
||||
if ((obj.webrtc.iceConnectionState == 'disconnected') || (obj.webrtc.iceConnectionState == 'failed')) { obj.xxCloseWebRTC(); }
|
||||
}
|
||||
}
|
||||
obj.webrtc.createOffer(function (offer) {
|
||||
// Got the offer
|
||||
obj.webrtcoffer = offer;
|
||||
obj.webrtc.setLocalDescription(offer, function () { console.log('WebRTC local ok'); }, obj.xxCloseWebRTC);
|
||||
obj.webrtc.setLocalDescription(offer, function () { /*console.log('WebRTC local ok');*/ }, obj.xxCloseWebRTC);
|
||||
}, obj.xxCloseWebRTC, { mandatory: { OfferToReceiveAudio: false, OfferToReceiveVideo: false } });
|
||||
}
|
||||
}
|
||||
@ -108,10 +106,14 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof e.data == 'string') {
|
||||
// Control messages, most likely WebRTC setup
|
||||
obj.xxOnControlCommand(e.data);
|
||||
} else if (typeof e.data == 'object') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof e.data == 'object') {
|
||||
var f = new FileReader();
|
||||
if (f.readAsBinaryString) {
|
||||
// Chrome & Firefox (Draft)
|
||||
@ -138,7 +140,6 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||
|
||||
obj.xxOnSocketData = function (data) {
|
||||
if (!data || obj.connectstate == -1) return;
|
||||
|
||||
if (typeof data === 'object') {
|
||||
// This is an ArrayBuffer, convert it to a string array (used in IE)
|
||||
var binary = "", bytes = new Uint8Array(data), length = bytes.byteLength;
|
||||
@ -146,39 +147,35 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||
data = binary;
|
||||
}
|
||||
else if (typeof data !== 'string') return;
|
||||
|
||||
// TODO: Don't use a prefix anymore, use string encoding instead
|
||||
if (data.length > 21 && data.startsWith('**********%%%%%%###**')) { obj.xxOnControlCommand(data.substring(21)); return; }
|
||||
|
||||
//console.log("xxOnSocketData", rstr2hex(data));
|
||||
|
||||
return obj.m.ProcessData(data);
|
||||
}
|
||||
|
||||
obj.Send = function (x) {
|
||||
//obj.debug("Agent Redir Send(" + x.length + "): " + rstr2hex(x));
|
||||
//obj.debug("Agent Redir Send(" + obj.webRtcActive + ", " + x.length + "): " + rstr2hex(x));
|
||||
//console.log("Agent Redir Send(" + obj.webRtcActive + ", " + x.length + "): " + rstr2hex(x));
|
||||
if (obj.socket != null && obj.socket.readyState == WebSocket.OPEN) {
|
||||
if (typeof x == 'string') {
|
||||
if (obj.debugmode == 1) {
|
||||
var b = new Uint8Array(x.length), c = [];
|
||||
for (var i = 0; i < x.length; ++i) { b[i] = x.charCodeAt(i); c.push(x.charCodeAt(i)); }
|
||||
obj.socket.send(b.buffer);
|
||||
console.log('Send', c);
|
||||
if (obj.webRtcActive == true) { obj.webchannel.send(b.buffer); } else { obj.socket.send(b.buffer); }
|
||||
//console.log('Send', c);
|
||||
} else {
|
||||
var b = new Uint8Array(x.length);
|
||||
for (var i = 0; i < x.length; ++i) { b[i] = x.charCodeAt(i); }
|
||||
obj.socket.send(b.buffer);
|
||||
if (obj.webRtcActive == true) { obj.webchannel.send(b.buffer); } else { obj.socket.send(b.buffer); }
|
||||
}
|
||||
} else {
|
||||
if (obj.debugmode == 1) { console.log('Send', x); }
|
||||
obj.socket.send(x);
|
||||
//if (obj.debugmode == 1) { console.log('Send', x); }
|
||||
if (obj.webRtcActive == true) { obj.webchannel.send(x); } else { obj.socket.send(x); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obj.xxOnSocketClosed = function () {
|
||||
//obj.debug("Agent Redir Socket Closed");
|
||||
if (obj.debugmode == 1) { console.log('onSocketClosed'); }
|
||||
//if (obj.debugmode == 1) { console.log('onSocketClosed'); }
|
||||
obj.Stop(1);
|
||||
}
|
||||
|
||||
@ -192,6 +189,9 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
|
||||
obj.Stop = function (x) {
|
||||
if (obj.debugmode == 1) { console.log('stop', x); }
|
||||
//obj.debug("Agent Redir Socket Stopped");
|
||||
obj.webRtcActive = false;
|
||||
obj.webrtc = null;
|
||||
obj.webchannel = null;
|
||||
obj.xxStateChange(0);
|
||||
obj.connectstate = -1;
|
||||
obj.xxCloseWebRTC();
|
||||
|
@ -647,6 +647,7 @@
|
||||
var amtScanResults = null;
|
||||
var debugmode = false;
|
||||
var clickOnce = detectClickOnce();
|
||||
var attemptWebRTC = false;
|
||||
|
||||
function startup() {
|
||||
if ((features & 32) == 0) {
|
||||
@ -2934,7 +2935,7 @@
|
||||
desktop = CreateAgentRedirect(meshserver, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort);
|
||||
desktop.debugmode = debugmode;
|
||||
desktop.m.debugmode = debugmode;
|
||||
//desktop.attemptWebRTC = debugmode;
|
||||
desktop.attemptWebRTC = attemptWebRTC;
|
||||
desktop.onStateChanged = onDesktopStateChange;
|
||||
desktop.m.CompressionLevel = desktopsettings.quality; // Number from 1 to 100. 50 or less is best.
|
||||
desktop.m.ScalingLevel = desktopsettings.scaling;
|
||||
@ -2954,7 +2955,10 @@
|
||||
function onDesktopStateChange(xdesktop, state) {
|
||||
var xstate = state;
|
||||
if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
|
||||
QH('deskstatus', StatusStrs[xstate]);
|
||||
var str = StatusStrs[xstate];
|
||||
if (desktop.webRtcActive == true) { str += ', WebRTC'; }
|
||||
//if (desktop.m.stopInput == true) { str += ', Loopback'; }
|
||||
QH('deskstatus', str);
|
||||
QE('deskSaveBtn', state == 3);
|
||||
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (state != 0) && (desktopsettings.showfocus));
|
||||
QE('DeskCAD', state == 3);
|
||||
@ -3143,7 +3147,9 @@
|
||||
function onTerminalStateChange(xterminal, state) {
|
||||
var xstate = state;
|
||||
if ((xstate == 3) && (xterminal.contype == 2)) { xstate++; }
|
||||
QH('termstatus', StatusStrs[xstate]);
|
||||
var str = StatusStrs[xstate];
|
||||
if (terminal.webRtcActive == true) { str += ', WebRTC'; }
|
||||
QH('termstatus', str);
|
||||
switch (state) {
|
||||
case 0:
|
||||
// Disconnected, clear the terminal
|
||||
@ -3180,7 +3186,7 @@
|
||||
terminal = CreateAgentRedirect(meshserver, CreateAmtRemoteTerminal('Term'), serverPublicNamePort);
|
||||
terminal.debugmode = debugmode;
|
||||
terminal.m.debugmode = debugmode;
|
||||
//terminal.attemptWebRTC = debugmode;
|
||||
terminal.attemptWebRTC = attemptWebRTC;
|
||||
terminal.onStateChanged = onTerminalStateChange;
|
||||
terminal.Start(terminalNode._id);
|
||||
terminal.contype = 1;
|
||||
@ -3251,7 +3257,9 @@
|
||||
|
||||
function onFilesStateChange(xfiles, state) {
|
||||
p13Connect.value = (state == 0) ? 'Connect' : 'Disconnect';
|
||||
Q('p13Status').textContent = StatusStrs[state];
|
||||
var str = StatusStrs[state];
|
||||
if (files.webRtcActive == true) { str += ', WebRTC'; }
|
||||
Q('p13Status').textContent = str;
|
||||
switch (state) {
|
||||
case 0:
|
||||
// Disconnected, clear the files
|
||||
@ -3286,7 +3294,7 @@
|
||||
if (!files) {
|
||||
// Setup a mesh agent files
|
||||
files = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotFiles), serverPublicNamePort);
|
||||
files.attemptWebRTC = debugmode;
|
||||
files.attemptWebRTC = false;
|
||||
files.onStateChanged = onFilesStateChange;
|
||||
files.Start(filesNode._id);
|
||||
} else {
|
||||
@ -3492,7 +3500,7 @@
|
||||
// Called by the html page to start a download, arguments are: path, file name and file size.
|
||||
function p13downloadfile(x, y, z) {
|
||||
downloadFile = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotDownloadData), serverPublicNamePort); // Create our file transport
|
||||
downloadFile.attemptWebRTC = debugmode;
|
||||
downloadFile.attemptWebRTC = false;
|
||||
downloadFile.onStateChanged = onFileDownloadStateChange;
|
||||
downloadFile.xpath = decodeURIComponent(x);
|
||||
downloadFile.xfile = decodeURIComponent(y);
|
||||
@ -3571,7 +3579,7 @@
|
||||
// Connect again
|
||||
function p13uploadReconnect() {
|
||||
uploadFile.ws = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotUploadData), serverPublicNamePort);
|
||||
uploadFile.ws.attemptWebRTC = debugmode;
|
||||
uploadFile.ws.attemptWebRTC = false;
|
||||
uploadFile.ws.onStateChanged = onFileUploadStateChange;
|
||||
uploadFile.ws.Start(filesNode._id);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user