mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-14 23:33:38 +00:00
271 lines
7.9 KiB
JavaScript
271 lines
7.9 KiB
JavaScript
console.enableWebLog(9595);
|
|
var mesh = null;
|
|
var kvmStream = null;
|
|
var Readable = require('stream').Readable;
|
|
var RS = new Readable({
|
|
read: function (options)
|
|
{
|
|
var min = 62000;
|
|
var max = 65535;
|
|
var size = Math.floor(Math.random() * (max - min)) + min;
|
|
var retVal = Buffer.alloc(size).fill(this.val++);
|
|
retVal.writeUInt32BE(size, 0);
|
|
if (this.val == 10) { this.val = 0; }
|
|
return (retVal);
|
|
}
|
|
});
|
|
RS.val = 0;
|
|
|
|
var http = require('http');
|
|
var rtc = require('ILibWebRTC');
|
|
var peerConnection;
|
|
var signalingChannel;
|
|
var dc;
|
|
|
|
var webServer = http.createServer(OnLocalWebRequest);
|
|
|
|
var childprocess = require('child_process');
|
|
var p;
|
|
|
|
webServer.on('upgrade', OnUpgrade);
|
|
webServer.listen(8585);
|
|
|
|
if (process.platform == 'win32') {
|
|
p = childprocess.execFile("c:\\windows\\system32\\cmd.exe", ["/c", "start", "http://localhost:8585/start.html"]);
|
|
}
|
|
else {
|
|
console.log('Manually point your browser to http://localhost:8585/start.html');
|
|
}
|
|
|
|
|
|
try
|
|
{
|
|
mesh = require('MeshAgent');
|
|
}
|
|
catch(e)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
function OnUpgrade(imsg, sck, head)
|
|
{
|
|
console.log("WebSocket Connected");
|
|
signalingChannel = sck.upgradeWebSocket();
|
|
signalingChannel.on('data', OnSignalData);
|
|
|
|
peerConnection = rtc.createConnection();
|
|
peerConnection.on('disconnected', function () { console.log('SCTP was disconnected'); });
|
|
peerConnection.on('connected', OnWebRTC_Connected);
|
|
peerConnection.on('dataChannel', OnWebRTC_DataChannel);
|
|
|
|
try
|
|
{
|
|
// peerConnection.on('_hold', function (val) { console.log('Holding Count: ' + val);});
|
|
peerConnection.on('_congestionWindowSizeChange', function (val) { console.log('Congestion Window: ' + val); });
|
|
// peerConnection.on('_receiverCredits', function (val) { console.log('Receiver Credits: ' + val); });
|
|
peerConnection.on('_t3tx', function (val) { console.log('T3TX: ' + val); });
|
|
//peerConnection.on('_fastRecovery', function (val) { console.log('Fast Recovery: ' + val);});
|
|
//peerConnection.on('_rttCalculated', function (val) { console.log('Calculated RTT Value = ' + val); });
|
|
peerConnection.on('_lastSackTime', function (val) { console.log('Last SACK Time = ' + val); });
|
|
peerConnection.on('_retransmit', function (val) { console.log('Retransmit: ' + (new Uint32Array([val]))[0]); });
|
|
//peerConnection.on('_retransmitPacket', function (val) { DebugPacket(val); console.log('RetransmitPacket: ' + val.toString('hex')); });
|
|
//peerConnection.on('_lastSentTime', function (val) { console.log('Last Sent Time = ' + val); });
|
|
peerConnection.on('_sackReceived', function (val) { console.log('SACK: ' + (new Uint32Array([val]))[0]); });
|
|
}
|
|
catch(e)
|
|
{
|
|
}
|
|
|
|
console.log("Generating WebRTC Offer...");
|
|
signalingChannel.write({ cmd: "offer", data: peerConnection.generateOffer() });
|
|
}
|
|
|
|
|
|
function FOURBYTEBOUNDARY(a)
|
|
{
|
|
return ((a) + ((4 - ((a) % 4)) % 4));
|
|
}
|
|
function crc32c(crc, bytes)
|
|
{
|
|
var POLY = 0x82f63b78;
|
|
var n;
|
|
|
|
crc ^= 0xffffffff;
|
|
for (n = 0; n < bytes.length; n++) {
|
|
crc ^= bytes[n];
|
|
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
|
|
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
|
|
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
|
|
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
|
|
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
|
|
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
|
|
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
|
|
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
|
|
}
|
|
return crc ^ 0xffffffff;
|
|
}
|
|
|
|
function DebugPacket(val)
|
|
{
|
|
console.log('BufferLen: ' + val.length);
|
|
console.log('CRC32C: ' + val.readInt32LE(8))
|
|
val.writeUInt32BE(0, 8);
|
|
console.log('CRC32C/Calc: ' + crc32c(0, val));
|
|
console.log('VTAG: ' + val.readUInt32LE(4));
|
|
var ptr = 12;
|
|
|
|
while (ptr + 4 <= val.length)
|
|
{
|
|
var hdr = val.slice(ptr);
|
|
|
|
var chunkType = hdr[0];
|
|
var chunkFlags = hdr[1];
|
|
var chunkSize = hdr.readUInt16BE(2);
|
|
|
|
switch (chunkType) {
|
|
case 0:
|
|
console.log('DATA Chunk');
|
|
console.log('...chunkFlags: ' + chunkFlags);
|
|
console.log('...chunkLength: ' + chunkSize);
|
|
console.log('...TSN: ' + hdr.readUInt32BE(4));
|
|
console.log('...StreamID: ' + hdr.readUInt16BE(8));
|
|
console.log('...Seq: ' + hdr.readUInt16BE(10));
|
|
console.log('...ProtocolID: ' + hdr.readUInt32BE(12));
|
|
break;
|
|
default:
|
|
console.log('UNKNOWN Chunk');
|
|
console.log('...chunkFlags: ' + chunkFlags);
|
|
console.log('...chunkLength: ' + chunkSize);
|
|
break;
|
|
}
|
|
|
|
ptr += FOURBYTEBOUNDARY(chunkSize);
|
|
}
|
|
}
|
|
function OnSignalData(chunk)
|
|
{
|
|
var j = JSON.parse(chunk);
|
|
if (j.cmd == 'offer')
|
|
{
|
|
console.log("Received Offer");
|
|
//signalingChannel.write({ cmd: "offer", data: peerConnection.setOffer(j.data) });
|
|
peerConnection.setOffer(j.data);
|
|
}
|
|
}
|
|
function OnLocalWebRequest(request, response)
|
|
{
|
|
if(request.method == 'GET' && request.url == '/start.html')
|
|
{
|
|
var fs = require('fs');
|
|
try
|
|
{
|
|
var stream = fs.createReadStream('WebRTC_Test2.html');
|
|
response.statusCode = 200;
|
|
response.statusMessage = "OK";
|
|
stream.pipe(response);
|
|
}
|
|
catch(e)
|
|
{
|
|
response.statusCode = 404;
|
|
response.statusMessage = "Not Found";
|
|
response.end();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
response.statusCode = 404;
|
|
response.statusMessage = "Not Found";
|
|
response.end();
|
|
}
|
|
}
|
|
|
|
function OnWebRTC_Connected()
|
|
{
|
|
console.log("WebRTC Session Established");
|
|
|
|
this.jsdc = this.createDataChannel("testChannel", OnTestChannel);
|
|
}
|
|
function OnTestChannel()
|
|
{
|
|
console.log("Successfully established JavaScript Data Channel");
|
|
|
|
if (mesh == null) {
|
|
RS.pipe(this);
|
|
}
|
|
else {
|
|
kvmStream = mesh.getRemoteDesktopStream();
|
|
kvmStream.pipe(this);
|
|
}
|
|
}
|
|
function OnKVMChannel()
|
|
{
|
|
console.log("Successfully established Data Channel to test Data throughput");
|
|
dc = this;
|
|
dc.kvm = mesh.getRemoteDesktopStream();
|
|
dc.on('data', function (buffer)
|
|
{
|
|
console.log("Peer Received: " + buffer.toString() + " bytes");
|
|
});
|
|
dc.on('end', function () { this.kvm.end(); console.log("Closing KVM Session"); });
|
|
dc.kvm.pipe(dc);
|
|
}
|
|
function OnWebRTC_DataChannel(dataChannel)
|
|
{
|
|
console.log("Data Channel (" + dataChannel.name + ") was created");
|
|
dc = dataChannel;
|
|
dc.on('data', function (buffer)
|
|
{
|
|
//console.log("Received: " + buffer);
|
|
});
|
|
dc.on('end', function () { console.log("Data Channel: " + this.name + " was closed"); });
|
|
|
|
//if (mesh == null)
|
|
//{
|
|
// RS.pipe(dc);
|
|
//}
|
|
//else
|
|
//{
|
|
// kvmStream = mesh.getRemoteDesktopStream();
|
|
// kvmStream.pipe(dc);
|
|
//}
|
|
}
|
|
function OnTunnelData(buffer)
|
|
{
|
|
if (buffer == 'c')
|
|
{
|
|
console.log("Tunnel Established");
|
|
peerConnection = rtc.createConnection();
|
|
peerConnection.on('connected', OnWebRTC_Connected);
|
|
peerConnection.on('dataChannel', OnWebRTC_DataChannel);
|
|
if(mesh!=null)
|
|
{
|
|
console.log("Generating WebRTC Offer...");
|
|
this.write({ cmd: "offer", data: peerConnection.generateOffer() });
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ProcessCommand(JSON.parse(buffer.toString()));
|
|
}
|
|
}
|
|
function ProcessCommand(cmd)
|
|
{
|
|
console.log("Received Command: " + cmd.cmd);
|
|
if(cmd.cmd == 'offer')
|
|
{
|
|
console.log("setting offer...");
|
|
console.log(cmd.data);
|
|
var counter = peerConnection.setOffer(cmd.data);
|
|
if(mesh == null)
|
|
{
|
|
signalingChannel.write({ cmd: "offer", data: counter });
|
|
}
|
|
}
|
|
if(cmd.cmd == 'candidate')
|
|
{
|
|
console.log("Received Candidate: " + cmd.data);
|
|
}
|
|
}
|
|
|