mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-03-09 15:40:18 +00:00
Merged APF and MPS servers, improved APF client.
This commit is contained in:
parent
3ff007c8d8
commit
bc4e07b5fe
8 changed files with 495 additions and 1242 deletions
800
mpsserver.js
800
mpsserver.js
|
@ -144,11 +144,13 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
|
||||
// Delay setting the connectivity state by 300ms to allow time for CIRA port mappings to be established
|
||||
// Report power state as "present" (7) until Intel AMT manager starts polling for power state.
|
||||
function delayedSetConnectivityState(meshid, nodeid, connectTime) {
|
||||
var f = function setConnFunc() { if (obj.ciraConnections[setConnFunc.nodeid] != null) { obj.parent.SetConnectivityState(setConnFunc.meshid, setConnFunc.nodeid, setConnFunc.connectTime, 2, 7); } }
|
||||
function delayedSetConnectivityState(meshid, nodeid, connectTime, connType) {
|
||||
if (nodeid.startsWith('*')) return; // Don't set connectivity state for Intel AMT self agent relay
|
||||
var f = function setConnFunc() { if (obj.ciraConnections[setConnFunc.nodeid] != null) { obj.parent.SetConnectivityState(setConnFunc.meshid, setConnFunc.nodeid, setConnFunc.connectTime, setConnFunc.connType, 7); } }
|
||||
f.nodeid = nodeid;
|
||||
f.meshid = meshid;
|
||||
f.connectTime = connectTime;
|
||||
f.connType = connType;
|
||||
setTimeout(f, 300);
|
||||
}
|
||||
|
||||
|
@ -220,13 +222,47 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
return packet_len;
|
||||
}
|
||||
|
||||
obj.onWebSocketConnection = function (socket) {
|
||||
connectionCount++;
|
||||
// connType: 2 = CIRA, 8 = Relay
|
||||
socket.tag = { first: true, connType: 2, clientCert: null, accumulator: '', activetunnels: 0, boundPorts: [], websocket: true, socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
|
||||
socket.websocket = 1;
|
||||
parent.debug('mps', "New CIRA websocket connection");
|
||||
|
||||
socket.on('message', function (data) {
|
||||
if (args.mpsdebug) { var buf = Buffer.from(data, 'binary'); console.log("MPS <-- (" + buf.length + "):" + buf.toString('hex')); } // Print out received bytes
|
||||
this.tag.accumulator += data.toString('binary'); // Append as binary string
|
||||
try {
|
||||
// Parse all of the APF data we can
|
||||
var l = 0;
|
||||
do { l = ProcessCommand(this); if (l > 0) { this.tag.accumulator = this.tag.accumulator.substring(l); } } while (l > 0);
|
||||
if (l < 0) { this.terminate(); }
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
socket.addListener('close', function () {
|
||||
socketClosedCount++;
|
||||
parent.debug('mps', "CIRA websocket closed", this.tag.meshid, this.tag.nodeid);
|
||||
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
|
||||
if (!this.tag.nodeid.startsWith('*')) { obj.parent.ClearConnectivityState(this.tag.meshid, this.tag.nodeid, this.tag.connType); }
|
||||
});
|
||||
|
||||
socket.addListener('error', function (e) {
|
||||
socketErrorCount++;
|
||||
parent.debug('mps', "CIRA websocket connection error", e);
|
||||
});
|
||||
}
|
||||
|
||||
// Called when a new TLS/TCP connection is accepted
|
||||
function onConnection(socket) {
|
||||
connectionCount++;
|
||||
// connType: 2 = CIRA, 8 = Relay
|
||||
if (obj.args.mpstlsoffload) {
|
||||
socket.tag = { first: true, clientCert: null, accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
|
||||
socket.tag = { first: true, connType: 2, clientCert: null, accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
|
||||
} else {
|
||||
socket.tag = { first: true, clientCert: socket.getPeerCertificate(true), accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
|
||||
socket.tag = { first: true, connType: 2, clientCert: socket.getPeerCertificate(true), accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
|
||||
}
|
||||
socket.setEncoding('binary');
|
||||
parent.debug('mps', "New CIRA connection");
|
||||
|
@ -235,6 +271,19 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
socket.setTimeout(MAX_IDLE);
|
||||
socket.on('timeout', () => { ciraTimeoutCount++; parent.debug('mps', "CIRA timeout, disconnecting."); try { socket.end(); } catch (e) { } });
|
||||
|
||||
socket.addListener('close', function () {
|
||||
socketClosedCount++;
|
||||
parent.debug('mps', 'CIRA connection closed');
|
||||
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
|
||||
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connType);
|
||||
});
|
||||
|
||||
socket.addListener('error', function (e) {
|
||||
socketErrorCount++;
|
||||
parent.debug('mps', 'CIRA connection error', e);
|
||||
//console.log("MPS Error: " + socket.remoteAddress);
|
||||
});
|
||||
|
||||
socket.addListener('data', function (data) {
|
||||
if (args.mpsdebug) { var buf = Buffer.from(data, 'binary'); console.log("MPS --> (" + buf.length + "):" + buf.toString('hex')); } // Print out received bytes
|
||||
socket.tag.accumulator += data;
|
||||
|
@ -334,8 +383,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
|
||||
// Add the connection to the MPS connection list
|
||||
obj.ciraConnections[socket.tag.nodeid] = socket;
|
||||
//obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll.
|
||||
delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
|
||||
delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, socket.tag.connType);
|
||||
}
|
||||
});
|
||||
return;
|
||||
|
@ -365,7 +413,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
|
||||
// Add the connection to the MPS connection list
|
||||
obj.ciraConnections[socket.tag.nodeid] = socket;
|
||||
delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
|
||||
delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, socket.tag.connType);
|
||||
});
|
||||
} else {
|
||||
// This node connected without certificate authentication, use password auth
|
||||
|
@ -382,355 +430,294 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
console.log(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Process one APF command
|
||||
function ProcessCommand(socket) {
|
||||
var cmd = socket.tag.accumulator.charCodeAt(0);
|
||||
var len = socket.tag.accumulator.length;
|
||||
var data = socket.tag.accumulator;
|
||||
if (len == 0) { return 0; }
|
||||
// Process one APF command
|
||||
function ProcessCommand(socket) {
|
||||
var cmd = socket.tag.accumulator.charCodeAt(0);
|
||||
var len = socket.tag.accumulator.length;
|
||||
var data = socket.tag.accumulator;
|
||||
if (len == 0) { return 0; }
|
||||
|
||||
switch (cmd) {
|
||||
case APFProtocol.KEEPALIVE_REQUEST: {
|
||||
if (len < 5) return 0;
|
||||
parent.debug('mpscmd', '--> KEEPALIVE_REQUEST');
|
||||
SendKeepAliveReply(socket, common.ReadInt(data, 1));
|
||||
return 5;
|
||||
switch (cmd) {
|
||||
case APFProtocol.KEEPALIVE_REQUEST: {
|
||||
if (len < 5) return 0;
|
||||
parent.debug('mpscmd', '--> KEEPALIVE_REQUEST');
|
||||
SendKeepAliveReply(socket, common.ReadInt(data, 1));
|
||||
return 5;
|
||||
}
|
||||
case APFProtocol.KEEPALIVE_REPLY: {
|
||||
if (len < 5) return 0;
|
||||
parent.debug('mpscmd', '--> KEEPALIVE_REPLY');
|
||||
return 5;
|
||||
}
|
||||
case APFProtocol.PROTOCOLVERSION: {
|
||||
if (len < 93) return 0;
|
||||
protocolVersionCount++;
|
||||
socket.tag.MajorVersion = common.ReadInt(data, 1);
|
||||
socket.tag.MinorVersion = common.ReadInt(data, 5);
|
||||
socket.tag.SystemId = guidToStr(common.rstr2hex(data.substring(13, 29))).toLowerCase();
|
||||
parent.debug('mpscmd', '--> PROTOCOLVERSION', socket.tag.MajorVersion, socket.tag.MinorVersion, socket.tag.SystemId);
|
||||
return 93;
|
||||
}
|
||||
case APFProtocol.USERAUTH_REQUEST: {
|
||||
if (len < 13) return 0;
|
||||
userAuthRequestCount++;
|
||||
var usernameLen = common.ReadInt(data, 1);
|
||||
var username = data.substring(5, 5 + usernameLen);
|
||||
var serviceNameLen = common.ReadInt(data, 5 + usernameLen);
|
||||
var serviceName = data.substring(9 + usernameLen, 9 + usernameLen + serviceNameLen);
|
||||
var methodNameLen = common.ReadInt(data, 9 + usernameLen + serviceNameLen);
|
||||
var methodName = data.substring(13 + usernameLen + serviceNameLen, 13 + usernameLen + serviceNameLen + methodNameLen);
|
||||
var passwordLen = 0, password = null;
|
||||
if (methodName == 'password') {
|
||||
passwordLen = common.ReadInt(data, 14 + usernameLen + serviceNameLen + methodNameLen);
|
||||
password = data.substring(18 + usernameLen + serviceNameLen + methodNameLen, 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen);
|
||||
}
|
||||
case APFProtocol.KEEPALIVE_REPLY: {
|
||||
if (len < 5) return 0;
|
||||
parent.debug('mpscmd', '--> KEEPALIVE_REPLY');
|
||||
return 5;
|
||||
}
|
||||
case APFProtocol.PROTOCOLVERSION: {
|
||||
if (len < 93) return 0;
|
||||
protocolVersionCount++;
|
||||
socket.tag.MajorVersion = common.ReadInt(data, 1);
|
||||
socket.tag.MinorVersion = common.ReadInt(data, 5);
|
||||
socket.tag.SystemId = guidToStr(common.rstr2hex(data.substring(13, 29))).toLowerCase();
|
||||
parent.debug('mpscmd', '--> PROTOCOLVERSION', socket.tag.MajorVersion, socket.tag.MinorVersion, socket.tag.SystemId);
|
||||
return 93;
|
||||
}
|
||||
case APFProtocol.USERAUTH_REQUEST: {
|
||||
if (len < 13) return 0;
|
||||
userAuthRequestCount++;
|
||||
var usernameLen = common.ReadInt(data, 1);
|
||||
var username = data.substring(5, 5 + usernameLen);
|
||||
var serviceNameLen = common.ReadInt(data, 5 + usernameLen);
|
||||
var serviceName = data.substring(9 + usernameLen, 9 + usernameLen + serviceNameLen);
|
||||
var methodNameLen = common.ReadInt(data, 9 + usernameLen + serviceNameLen);
|
||||
var methodName = data.substring(13 + usernameLen + serviceNameLen, 13 + usernameLen + serviceNameLen + methodNameLen);
|
||||
var passwordLen = 0, password = null;
|
||||
if (methodName == 'password') {
|
||||
passwordLen = common.ReadInt(data, 14 + usernameLen + serviceNameLen + methodNameLen);
|
||||
password = data.substring(18 + usernameLen + serviceNameLen + methodNameLen, 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen);
|
||||
}
|
||||
//console.log('MPS:USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
|
||||
parent.debug('mpscmd', '--> USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
|
||||
//console.log('MPS:USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
|
||||
parent.debug('mpscmd', '--> USERAUTH_REQUEST user=' + username + ', service=' + serviceName + ', method=' + methodName + ', password=' + password);
|
||||
|
||||
// Check the CIRA password
|
||||
if ((args.mpspass != null) && (password != args.mpspass)) { incorrectPasswordCount++; parent.debug('mps', 'Incorrect password', username, password); SendUserAuthFail(socket); return -1; }
|
||||
// Check the CIRA password
|
||||
if ((args.mpspass != null) && (password != args.mpspass)) { incorrectPasswordCount++; parent.debug('mps', 'Incorrect password', username, password); SendUserAuthFail(socket); return -1; }
|
||||
|
||||
// Check the CIRA username, which should be the start of the MeshID.
|
||||
if (usernameLen != 16) { badUserNameLengthCount++; parent.debug('mps', 'Username length not 16', username, password); SendUserAuthFail(socket); return -1; }
|
||||
var meshIdStart = '/' + username, mesh = null;
|
||||
if (obj.parent.webserver.meshes) { for (var i in obj.parent.webserver.meshes) { if (obj.parent.webserver.meshes[i]._id.replace(/\@/g, 'X').replace(/\$/g, 'X').indexOf(meshIdStart) > 0) { mesh = obj.parent.webserver.meshes[i]; break; } } }
|
||||
if (mesh == null) { meshNotFoundCount++; parent.debug('mps', 'Device group not found', username, password); SendUserAuthFail(socket); return -1; }
|
||||
// Check the CIRA username, which should be the start of the MeshID.
|
||||
if (usernameLen != 16) { badUserNameLengthCount++; parent.debug('mps', 'Username length not 16', username, password); SendUserAuthFail(socket); return -1; }
|
||||
var meshIdStart = '/' + username, mesh = null;
|
||||
if (obj.parent.webserver.meshes) { for (var i in obj.parent.webserver.meshes) { if (obj.parent.webserver.meshes[i]._id.replace(/\@/g, 'X').replace(/\$/g, 'X').indexOf(meshIdStart) > 0) { mesh = obj.parent.webserver.meshes[i]; break; } } }
|
||||
if (mesh == null) { meshNotFoundCount++; parent.debug('mps', 'Device group not found', username, password); SendUserAuthFail(socket); return -1; }
|
||||
|
||||
// If this is a agent-less mesh, use the device guid 3 times as ID.
|
||||
if (mesh.mtype == 1) {
|
||||
// Intel AMT GUID (socket.tag.SystemId) will be used as NodeID
|
||||
var systemid = socket.tag.SystemId.split('-').join('');
|
||||
var nodeid = Buffer.from(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||
var domain = obj.parent.config.domains[mesh.domain];
|
||||
socket.tag.domain = domain;
|
||||
socket.tag.domainid = mesh.domain;
|
||||
socket.tag.name = '';
|
||||
socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded
|
||||
socket.tag.meshid = mesh._id;
|
||||
// If this is a agent-less mesh, use the device guid 3 times as ID.
|
||||
if (mesh.mtype == 1) {
|
||||
// Intel AMT GUID (socket.tag.SystemId) will be used as NodeID
|
||||
var systemid = socket.tag.SystemId.split('-').join('');
|
||||
var nodeid = Buffer.from(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
|
||||
var domain = obj.parent.config.domains[mesh.domain];
|
||||
socket.tag.domain = domain;
|
||||
socket.tag.domainid = mesh.domain;
|
||||
socket.tag.name = '';
|
||||
socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded
|
||||
socket.tag.meshid = mesh._id;
|
||||
socket.tag.connectTime = Date.now();
|
||||
|
||||
obj.db.Get(socket.tag.nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length !== 1)) {
|
||||
// Check if we already have too many devices for this domain
|
||||
if (domain.limits && (typeof domain.limits.maxdevices == 'number')) {
|
||||
db.isMaxType(domain.limits.maxdevices, 'node', mesh.domain, function (ismax, count) {
|
||||
if (ismax == true) {
|
||||
// Too many devices in this domain.
|
||||
maxDomainDevicesReached++;
|
||||
console.log('Too many devices on this domain to accept the CIRA connection. meshid: ' + socket.tag.meshid);
|
||||
socket.end();
|
||||
} else {
|
||||
// We are under the limit, create the new device.
|
||||
// Node is not in the database, add it. Credentials will be empty until added by the user.
|
||||
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
|
||||
obj.db.Set(device);
|
||||
|
||||
// Event the new node
|
||||
addedDeviceCount++;
|
||||
var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name;
|
||||
obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain });
|
||||
|
||||
// Add the connection to the MPS connection list
|
||||
obj.ciraConnections[socket.tag.nodeid] = socket;
|
||||
delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, socket.tag.connType);
|
||||
SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
|
||||
}
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
// Node is not in the database, add it. Credentials will be empty until added by the user.
|
||||
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
|
||||
obj.db.Set(device);
|
||||
|
||||
// Event the new node
|
||||
addedDeviceCount++;
|
||||
var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name;
|
||||
obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain });
|
||||
}
|
||||
} else {
|
||||
// Node is already present
|
||||
var node = nodes[0];
|
||||
socket.tag.meshid = node.meshid; // Correct the MeshID if the node has moved.
|
||||
if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
|
||||
}
|
||||
|
||||
// Add the connection to the MPS connection list
|
||||
obj.ciraConnections[socket.tag.nodeid] = socket;
|
||||
delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, socket.tag.connType);
|
||||
SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
|
||||
});
|
||||
} else if (mesh.mtype == 2) { // If this is a agent mesh, search the mesh for this device UUID
|
||||
// Intel AMT GUID (socket.tag.SystemId) will be used to search the node
|
||||
obj.db.getAmtUuidNode(socket.tag.SystemId, function (err, nodes) { // TODO: May need to optimize this request with indexes
|
||||
if ((nodes == null) || (nodes.length === 0) || (obj.parent.webserver.meshes == null)) {
|
||||
// New CIRA connection for unknown node, disconnect.
|
||||
unknownNodeCount++;
|
||||
console.log('CIRA connection for unknown node. groupid: ' + mesh._id + ', uuid: ' + socket.tag.SystemId);
|
||||
socket.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Looking at nodes that match this UUID, select one in the same domain and mesh type.
|
||||
var node = null;
|
||||
for (var i in nodes) {
|
||||
if (mesh.domain == nodes[i].domain) {
|
||||
var nodemesh = obj.parent.webserver.meshes[nodes[i].meshid];
|
||||
if ((nodemesh != null) && (nodemesh.mtype == 2)) { node = nodes[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
if (node == null) {
|
||||
// New CIRA connection for unknown node, disconnect.
|
||||
unknownNodeCount++;
|
||||
console.log('CIRA connection for unknown node. candidate(s): ' + nodes.length + ', groupid: ' + mesh._id + ', uuid: ' + socket.tag.SystemId);
|
||||
socket.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Node is present
|
||||
if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
|
||||
socket.tag.nodeid = node._id;
|
||||
socket.tag.meshid = node.meshid; // Correct the MeshID if the node has moved.
|
||||
socket.tag.connectTime = Date.now();
|
||||
|
||||
obj.db.Get(socket.tag.nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length !== 1)) {
|
||||
// Check if we already have too many devices for this domain
|
||||
if (domain.limits && (typeof domain.limits.maxdevices == 'number')) {
|
||||
db.isMaxType(domain.limits.maxdevices, 'node', mesh.domain, function (ismax, count) {
|
||||
if (ismax == true) {
|
||||
// Too many devices in this domain.
|
||||
maxDomainDevicesReached++;
|
||||
console.log('Too many devices on this domain to accept the CIRA connection. meshid: ' + socket.tag.meshid);
|
||||
socket.end();
|
||||
} else {
|
||||
// We are under the limit, create the new device.
|
||||
// Node is not in the database, add it. Credentials will be empty until added by the user.
|
||||
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
|
||||
obj.db.Set(device);
|
||||
|
||||
// Event the new node
|
||||
addedDeviceCount++;
|
||||
var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name;
|
||||
obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain });
|
||||
|
||||
// Add the connection to the MPS connection list
|
||||
obj.ciraConnections[socket.tag.nodeid] = socket;
|
||||
delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
|
||||
SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
|
||||
}
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
// Node is not in the database, add it. Credentials will be empty until added by the user.
|
||||
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
|
||||
obj.db.Set(device);
|
||||
|
||||
// Event the new node
|
||||
addedDeviceCount++;
|
||||
var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name;
|
||||
obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: parent.webserver.CloneSafeNode(device), msg: change, domain: mesh.domain });
|
||||
}
|
||||
} else {
|
||||
// Node is already present
|
||||
var node = nodes[0];
|
||||
socket.tag.meshid = node.meshid; // Correct the MeshID if the node has moved.
|
||||
if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
|
||||
}
|
||||
|
||||
// Add the connection to the MPS connection list
|
||||
obj.ciraConnections[socket.tag.nodeid] = socket;
|
||||
delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
|
||||
SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
|
||||
});
|
||||
} else if (mesh.mtype == 2) { // If this is a agent mesh, search the mesh for this device UUID
|
||||
// Intel AMT GUID (socket.tag.SystemId) will be used to search the node
|
||||
obj.db.getAmtUuidNode(socket.tag.SystemId, function (err, nodes) { // TODO: May need to optimize this request with indexes
|
||||
if ((nodes == null) || (nodes.length === 0) || (obj.parent.webserver.meshes == null)) {
|
||||
// New CIRA connection for unknown node, disconnect.
|
||||
unknownNodeCount++;
|
||||
console.log('CIRA connection for unknown node. groupid: ' + mesh._id + ', uuid: ' + socket.tag.SystemId);
|
||||
socket.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Looking at nodes that match this UUID, select one in the same domain and mesh type.
|
||||
var node = null;
|
||||
for (var i in nodes) {
|
||||
if (mesh.domain == nodes[i].domain) {
|
||||
var nodemesh = obj.parent.webserver.meshes[nodes[i].meshid];
|
||||
if ((nodemesh != null) && (nodemesh.mtype == 2)) { node = nodes[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
if (node == null) {
|
||||
// New CIRA connection for unknown node, disconnect.
|
||||
unknownNodeCount++;
|
||||
console.log('CIRA connection for unknown node. candidate(s): ' + nodes.length + ', groupid: ' + mesh._id + ', uuid: ' + socket.tag.SystemId);
|
||||
socket.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Node is present
|
||||
if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
|
||||
socket.tag.nodeid = node._id;
|
||||
socket.tag.meshid = node.meshid; // Correct the MeshID if the node has moved.
|
||||
socket.tag.connectTime = Date.now();
|
||||
|
||||
// Add the connection to the MPS connection list
|
||||
obj.ciraConnections[socket.tag.nodeid] = socket;
|
||||
delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime);
|
||||
SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
|
||||
});
|
||||
} else { // Unknown mesh type
|
||||
// New CIRA connection for unknown node, disconnect.
|
||||
unknownMeshIdCount++;
|
||||
console.log('CIRA connection to a unknown group type. groupid: ' + socket.tag.meshid);
|
||||
socket.end();
|
||||
return;
|
||||
}
|
||||
return 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen;
|
||||
// Add the connection to the MPS connection list
|
||||
obj.ciraConnections[socket.tag.nodeid] = socket;
|
||||
delayedSetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, socket.tag.connType);
|
||||
SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
|
||||
});
|
||||
} else { // Unknown mesh type
|
||||
// New CIRA connection for unknown node, disconnect.
|
||||
unknownMeshIdCount++;
|
||||
console.log('CIRA connection to a unknown group type. groupid: ' + socket.tag.meshid);
|
||||
socket.end();
|
||||
return;
|
||||
}
|
||||
case APFProtocol.SERVICE_REQUEST: {
|
||||
if (len < 5) return 0;
|
||||
var xserviceNameLen = common.ReadInt(data, 1);
|
||||
if (len < 5 + xserviceNameLen) return 0;
|
||||
var xserviceName = data.substring(5, 5 + xserviceNameLen);
|
||||
parent.debug('mpscmd', '--> SERVICE_REQUEST', xserviceName);
|
||||
if (xserviceName == "pfwd@amt.intel.com") { SendServiceAccept(socket, "pfwd@amt.intel.com"); }
|
||||
if (xserviceName == "auth@amt.intel.com") { SendServiceAccept(socket, "auth@amt.intel.com"); }
|
||||
return 5 + xserviceNameLen;
|
||||
return 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen;
|
||||
}
|
||||
case APFProtocol.SERVICE_REQUEST: {
|
||||
if (len < 5) return 0;
|
||||
var xserviceNameLen = common.ReadInt(data, 1);
|
||||
if (len < 5 + xserviceNameLen) return 0;
|
||||
var xserviceName = data.substring(5, 5 + xserviceNameLen);
|
||||
parent.debug('mpscmd', '--> SERVICE_REQUEST', xserviceName);
|
||||
if (xserviceName == "pfwd@amt.intel.com") { SendServiceAccept(socket, "pfwd@amt.intel.com"); }
|
||||
if (xserviceName == "auth@amt.intel.com") { SendServiceAccept(socket, "auth@amt.intel.com"); }
|
||||
return 5 + xserviceNameLen;
|
||||
}
|
||||
case APFProtocol.GLOBAL_REQUEST: {
|
||||
if (len < 14) return 0;
|
||||
var requestLen = common.ReadInt(data, 1);
|
||||
if (len < 14 + requestLen) return 0;
|
||||
var request = data.substring(5, 5 + requestLen);
|
||||
//var wantResponse = data.charCodeAt(5 + requestLen);
|
||||
|
||||
if (request == 'tcpip-forward') {
|
||||
var addrLen = common.ReadInt(data, 6 + requestLen);
|
||||
if (len < 14 + requestLen + addrLen) return 0;
|
||||
var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
|
||||
var port = common.ReadInt(data, 10 + requestLen + addrLen);
|
||||
parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port);
|
||||
ChangeHostname(socket, addr, socket.tag.SystemId);
|
||||
if (socket.tag.boundPorts.indexOf(port) == -1) { socket.tag.boundPorts.push(port); }
|
||||
SendTcpForwardSuccessReply(socket, port);
|
||||
return 14 + requestLen + addrLen;
|
||||
}
|
||||
case APFProtocol.GLOBAL_REQUEST: {
|
||||
if (len < 14) return 0;
|
||||
var requestLen = common.ReadInt(data, 1);
|
||||
if (len < 14 + requestLen) return 0;
|
||||
var request = data.substring(5, 5 + requestLen);
|
||||
//var wantResponse = data.charCodeAt(5 + requestLen);
|
||||
|
||||
if (request == 'tcpip-forward') {
|
||||
var addrLen = common.ReadInt(data, 6 + requestLen);
|
||||
if (len < 14 + requestLen + addrLen) return 0;
|
||||
var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
|
||||
var port = common.ReadInt(data, 10 + requestLen + addrLen);
|
||||
parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port);
|
||||
ChangeHostname(socket, addr, socket.tag.SystemId);
|
||||
if (socket.tag.boundPorts.indexOf(port) == -1) { socket.tag.boundPorts.push(port); }
|
||||
SendTcpForwardSuccessReply(socket, port);
|
||||
return 14 + requestLen + addrLen;
|
||||
}
|
||||
|
||||
if (request == 'cancel-tcpip-forward') {
|
||||
var addrLen = common.ReadInt(data, 6 + requestLen);
|
||||
if (len < 14 + requestLen + addrLen) return 0;
|
||||
var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
|
||||
var port = common.ReadInt(data, 10 + requestLen + addrLen);
|
||||
parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port);
|
||||
var portindex = socket.tag.boundPorts.indexOf(port);
|
||||
if (portindex >= 0) { socket.tag.boundPorts.splice(portindex, 1); }
|
||||
SendTcpForwardCancelReply(socket);
|
||||
return 14 + requestLen + addrLen;
|
||||
}
|
||||
|
||||
if (request == 'udp-send-to@amt.intel.com') {
|
||||
var addrLen = common.ReadInt(data, 6 + requestLen);
|
||||
if (len < 26 + requestLen + addrLen) return 0;
|
||||
var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
|
||||
var port = common.ReadInt(data, 10 + requestLen + addrLen);
|
||||
var oaddrLen = common.ReadInt(data, 14 + requestLen + addrLen);
|
||||
if (len < 26 + requestLen + addrLen + oaddrLen) return 0;
|
||||
var oaddr = data.substring(18 + requestLen, 18 + requestLen + addrLen);
|
||||
var oport = common.ReadInt(data, 18 + requestLen + addrLen + oaddrLen);
|
||||
var datalen = common.ReadInt(data, 22 + requestLen + addrLen + oaddrLen);
|
||||
if (len < 26 + requestLen + addrLen + oaddrLen + datalen) return 0;
|
||||
parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port, oaddr + ':' + oport, datalen);
|
||||
// TODO
|
||||
return 26 + requestLen + addrLen + oaddrLen + datalen;
|
||||
}
|
||||
|
||||
return 6 + requestLen;
|
||||
if (request == 'cancel-tcpip-forward') {
|
||||
var addrLen = common.ReadInt(data, 6 + requestLen);
|
||||
if (len < 14 + requestLen + addrLen) return 0;
|
||||
var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
|
||||
var port = common.ReadInt(data, 10 + requestLen + addrLen);
|
||||
parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port);
|
||||
var portindex = socket.tag.boundPorts.indexOf(port);
|
||||
if (portindex >= 0) { socket.tag.boundPorts.splice(portindex, 1); }
|
||||
SendTcpForwardCancelReply(socket);
|
||||
return 14 + requestLen + addrLen;
|
||||
}
|
||||
case APFProtocol.CHANNEL_OPEN: {
|
||||
if (len < 33) return 0;
|
||||
var ChannelTypeLength = common.ReadInt(data, 1);
|
||||
if (len < (33 + ChannelTypeLength)) return 0;
|
||||
|
||||
// Decode channel identifiers and window size
|
||||
var ChannelType = data.substring(5, 5 + ChannelTypeLength);
|
||||
var SenderChannel = common.ReadInt(data, 5 + ChannelTypeLength);
|
||||
var WindowSize = common.ReadInt(data, 9 + ChannelTypeLength);
|
||||
if (request == 'udp-send-to@amt.intel.com') {
|
||||
var addrLen = common.ReadInt(data, 6 + requestLen);
|
||||
if (len < 26 + requestLen + addrLen) return 0;
|
||||
var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
|
||||
var port = common.ReadInt(data, 10 + requestLen + addrLen);
|
||||
var oaddrLen = common.ReadInt(data, 14 + requestLen + addrLen);
|
||||
if (len < 26 + requestLen + addrLen + oaddrLen) return 0;
|
||||
var oaddr = data.substring(18 + requestLen, 18 + requestLen + addrLen);
|
||||
var oport = common.ReadInt(data, 18 + requestLen + addrLen + oaddrLen);
|
||||
var datalen = common.ReadInt(data, 22 + requestLen + addrLen + oaddrLen);
|
||||
if (len < 26 + requestLen + addrLen + oaddrLen + datalen) return 0;
|
||||
parent.debug('mpscmd', '--> GLOBAL_REQUEST', request, addr + ':' + port, oaddr + ':' + oport, datalen);
|
||||
// TODO
|
||||
return 26 + requestLen + addrLen + oaddrLen + datalen;
|
||||
}
|
||||
|
||||
// Decode the target
|
||||
var TargetLen = common.ReadInt(data, 17 + ChannelTypeLength);
|
||||
if (len < (33 + ChannelTypeLength + TargetLen)) return 0;
|
||||
var Target = data.substring(21 + ChannelTypeLength, 21 + ChannelTypeLength + TargetLen);
|
||||
var TargetPort = common.ReadInt(data, 21 + ChannelTypeLength + TargetLen);
|
||||
return 6 + requestLen;
|
||||
}
|
||||
case APFProtocol.CHANNEL_OPEN: {
|
||||
if (len < 33) return 0;
|
||||
var ChannelTypeLength = common.ReadInt(data, 1);
|
||||
if (len < (33 + ChannelTypeLength)) return 0;
|
||||
|
||||
// Decode the source
|
||||
var SourceLen = common.ReadInt(data, 25 + ChannelTypeLength + TargetLen);
|
||||
if (len < (33 + ChannelTypeLength + TargetLen + SourceLen)) return 0;
|
||||
var Source = data.substring(29 + ChannelTypeLength + TargetLen, 29 + ChannelTypeLength + TargetLen + SourceLen);
|
||||
var SourcePort = common.ReadInt(data, 29 + ChannelTypeLength + TargetLen + SourceLen);
|
||||
// Decode channel identifiers and window size
|
||||
var ChannelType = data.substring(5, 5 + ChannelTypeLength);
|
||||
var SenderChannel = common.ReadInt(data, 5 + ChannelTypeLength);
|
||||
var WindowSize = common.ReadInt(data, 9 + ChannelTypeLength);
|
||||
|
||||
channelOpenCount++;
|
||||
parent.debug('mpscmd', '--> CHANNEL_OPEN', ChannelType, SenderChannel, WindowSize, Target + ':' + TargetPort, Source + ':' + SourcePort);
|
||||
// Decode the target
|
||||
var TargetLen = common.ReadInt(data, 17 + ChannelTypeLength);
|
||||
if (len < (33 + ChannelTypeLength + TargetLen)) return 0;
|
||||
var Target = data.substring(21 + ChannelTypeLength, 21 + ChannelTypeLength + TargetLen);
|
||||
var TargetPort = common.ReadInt(data, 21 + ChannelTypeLength + TargetLen);
|
||||
|
||||
// Check if we understand this channel type
|
||||
//if (ChannelType.toLowerCase() == "direct-tcpip")
|
||||
{
|
||||
// We don't understand this channel type, send an error back
|
||||
SendChannelOpenFailure(socket, SenderChannel, APFChannelOpenFailureReasonCode.UnknownChannelType);
|
||||
return 33 + ChannelTypeLength + TargetLen + SourceLen;
|
||||
}
|
||||
// Decode the source
|
||||
var SourceLen = common.ReadInt(data, 25 + ChannelTypeLength + TargetLen);
|
||||
if (len < (33 + ChannelTypeLength + TargetLen + SourceLen)) return 0;
|
||||
var Source = data.substring(29 + ChannelTypeLength + TargetLen, 29 + ChannelTypeLength + TargetLen + SourceLen);
|
||||
var SourcePort = common.ReadInt(data, 29 + ChannelTypeLength + TargetLen + SourceLen);
|
||||
|
||||
/*
|
||||
// This is a correct connection. Lets get it setup
|
||||
var MeshAmtEventEndpoint = { ServerChannel: GetNextBindId(), AmtChannel: SenderChannel, MaxWindowSize: 2048, CurrentWindowSize:2048, SendWindow: WindowSize, InfoHeader: "Target: " + Target + ":" + TargetPort + ", Source: " + Source + ":" + SourcePort};
|
||||
// TODO: Connect this socket for a WSMAN event
|
||||
SendChannelOpenConfirmation(socket, SenderChannel, MeshAmtEventEndpoint.ServerChannel, MeshAmtEventEndpoint.MaxWindowSize);
|
||||
*/
|
||||
channelOpenCount++;
|
||||
parent.debug('mpscmd', '--> CHANNEL_OPEN', ChannelType, SenderChannel, WindowSize, Target + ':' + TargetPort, Source + ':' + SourcePort);
|
||||
|
||||
// Check if we understand this channel type
|
||||
//if (ChannelType.toLowerCase() == "direct-tcpip")
|
||||
{
|
||||
// We don't understand this channel type, send an error back
|
||||
SendChannelOpenFailure(socket, SenderChannel, APFChannelOpenFailureReasonCode.UnknownChannelType);
|
||||
return 33 + ChannelTypeLength + TargetLen + SourceLen;
|
||||
}
|
||||
case APFProtocol.CHANNEL_OPEN_CONFIRMATION:
|
||||
{
|
||||
if (len < 17) return 0;
|
||||
var RecipientChannel = common.ReadInt(data, 1);
|
||||
var SenderChannel = common.ReadInt(data, 5);
|
||||
var WindowSize = common.ReadInt(data, 9);
|
||||
socket.tag.activetunnels++;
|
||||
var cirachannel = socket.tag.channels[RecipientChannel];
|
||||
if (cirachannel == null) { /*console.log("MPS Error in CHANNEL_OPEN_CONFIRMATION: Unable to find channelid " + RecipientChannel);*/ return 17; }
|
||||
cirachannel.amtchannelid = SenderChannel;
|
||||
cirachannel.sendcredits = cirachannel.amtCiraWindow = WindowSize;
|
||||
channelOpenConfirmCount++;
|
||||
parent.debug('mpscmd', '--> CHANNEL_OPEN_CONFIRMATION', RecipientChannel, SenderChannel, WindowSize);
|
||||
if (cirachannel.closing == 1) {
|
||||
// Close this channel
|
||||
SendChannelClose(cirachannel.socket, cirachannel.amtchannelid);
|
||||
} else {
|
||||
cirachannel.state = 2;
|
||||
// Send any pending data
|
||||
if (cirachannel.sendBuffer != null) {
|
||||
if (cirachannel.sendBuffer.length <= cirachannel.sendcredits) {
|
||||
// Send the entire pending buffer
|
||||
SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer);
|
||||
cirachannel.sendcredits -= cirachannel.sendBuffer.length;
|
||||
delete cirachannel.sendBuffer;
|
||||
if (cirachannel.onSendOk) { cirachannel.onSendOk(cirachannel); }
|
||||
} else {
|
||||
// Send a part of the pending buffer
|
||||
SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer.substring(0, cirachannel.sendcredits));
|
||||
cirachannel.sendBuffer = cirachannel.sendBuffer.substring(cirachannel.sendcredits);
|
||||
cirachannel.sendcredits = 0;
|
||||
}
|
||||
}
|
||||
// Indicate the channel is open
|
||||
if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
|
||||
}
|
||||
return 17;
|
||||
}
|
||||
case APFProtocol.CHANNEL_OPEN_FAILURE:
|
||||
{
|
||||
if (len < 17) return 0;
|
||||
var RecipientChannel = common.ReadInt(data, 1);
|
||||
var ReasonCode = common.ReadInt(data, 5);
|
||||
channelOpenFailCount++;
|
||||
parent.debug('mpscmd', '--> CHANNEL_OPEN_FAILURE', RecipientChannel, ReasonCode);
|
||||
var cirachannel = socket.tag.channels[RecipientChannel];
|
||||
if (cirachannel == null) { console.log("MPS Error in CHANNEL_OPEN_FAILURE: Unable to find channelid " + RecipientChannel); return 17; }
|
||||
if (cirachannel.state > 0) {
|
||||
cirachannel.state = 0;
|
||||
if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
|
||||
delete socket.tag.channels[RecipientChannel];
|
||||
}
|
||||
return 17;
|
||||
}
|
||||
case APFProtocol.CHANNEL_CLOSE:
|
||||
{
|
||||
if (len < 5) return 0;
|
||||
var RecipientChannel = common.ReadInt(data, 1);
|
||||
channelCloseCount++;
|
||||
parent.debug('mpscmd', '--> CHANNEL_CLOSE', RecipientChannel);
|
||||
var cirachannel = socket.tag.channels[RecipientChannel];
|
||||
if (cirachannel == null) { console.log("MPS Error in CHANNEL_CLOSE: Unable to find channelid " + RecipientChannel); return 5; }
|
||||
socket.tag.activetunnels--;
|
||||
if (cirachannel.state > 0) {
|
||||
cirachannel.state = 0;
|
||||
if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
|
||||
SendChannelClose(cirachannel.socket, cirachannel.amtchannelid);
|
||||
delete socket.tag.channels[RecipientChannel];
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
case APFProtocol.CHANNEL_WINDOW_ADJUST:
|
||||
{
|
||||
if (len < 9) return 0;
|
||||
var RecipientChannel = common.ReadInt(data, 1);
|
||||
var ByteToAdd = common.ReadInt(data, 5);
|
||||
var cirachannel = socket.tag.channels[RecipientChannel];
|
||||
if (cirachannel == null) { console.log("MPS Error in CHANNEL_WINDOW_ADJUST: Unable to find channelid " + RecipientChannel); return 9; }
|
||||
cirachannel.sendcredits += ByteToAdd;
|
||||
parent.debug('mpscmd', '--> CHANNEL_WINDOW_ADJUST', RecipientChannel, ByteToAdd, cirachannel.sendcredits);
|
||||
if (cirachannel.state == 2 && cirachannel.sendBuffer != null) {
|
||||
// Compute how much data we can send
|
||||
|
||||
/*
|
||||
// This is a correct connection. Lets get it setup
|
||||
var MeshAmtEventEndpoint = { ServerChannel: GetNextBindId(), AmtChannel: SenderChannel, MaxWindowSize: 2048, CurrentWindowSize:2048, SendWindow: WindowSize, InfoHeader: "Target: " + Target + ":" + TargetPort + ", Source: " + Source + ":" + SourcePort};
|
||||
// TODO: Connect this socket for a WSMAN event
|
||||
SendChannelOpenConfirmation(socket, SenderChannel, MeshAmtEventEndpoint.ServerChannel, MeshAmtEventEndpoint.MaxWindowSize);
|
||||
*/
|
||||
|
||||
return 33 + ChannelTypeLength + TargetLen + SourceLen;
|
||||
}
|
||||
case APFProtocol.CHANNEL_OPEN_CONFIRMATION:
|
||||
{
|
||||
if (len < 17) return 0;
|
||||
var RecipientChannel = common.ReadInt(data, 1);
|
||||
var SenderChannel = common.ReadInt(data, 5);
|
||||
var WindowSize = common.ReadInt(data, 9);
|
||||
socket.tag.activetunnels++;
|
||||
var cirachannel = socket.tag.channels[RecipientChannel];
|
||||
if (cirachannel == null) { /*console.log("MPS Error in CHANNEL_OPEN_CONFIRMATION: Unable to find channelid " + RecipientChannel);*/ return 17; }
|
||||
cirachannel.amtchannelid = SenderChannel;
|
||||
cirachannel.sendcredits = cirachannel.amtCiraWindow = WindowSize;
|
||||
channelOpenConfirmCount++;
|
||||
parent.debug('mpscmd', '--> CHANNEL_OPEN_CONFIRMATION', RecipientChannel, SenderChannel, WindowSize);
|
||||
if (cirachannel.closing == 1) {
|
||||
// Close this channel
|
||||
SendChannelClose(cirachannel.socket, cirachannel.amtchannelid);
|
||||
} else {
|
||||
cirachannel.state = 2;
|
||||
// Send any pending data
|
||||
if (cirachannel.sendBuffer != null) {
|
||||
if (cirachannel.sendBuffer.length <= cirachannel.sendcredits) {
|
||||
// Send the entire pending buffer
|
||||
SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer);
|
||||
|
@ -744,63 +731,110 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
cirachannel.sendcredits = 0;
|
||||
}
|
||||
}
|
||||
return 9;
|
||||
// Indicate the channel is open
|
||||
if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
|
||||
}
|
||||
case APFProtocol.CHANNEL_DATA:
|
||||
{
|
||||
if (len < 9) return 0;
|
||||
var RecipientChannel = common.ReadInt(data, 1);
|
||||
var LengthOfData = common.ReadInt(data, 5);
|
||||
if (len < (9 + LengthOfData)) return 0;
|
||||
parent.debug('mpscmddata', '--> CHANNEL_DATA', RecipientChannel, LengthOfData);
|
||||
var cirachannel = socket.tag.channels[RecipientChannel];
|
||||
if (cirachannel == null) { console.log("MPS Error in CHANNEL_DATA: Unable to find channelid " + RecipientChannel); return 9 + LengthOfData; }
|
||||
cirachannel.amtpendingcredits += LengthOfData;
|
||||
if (cirachannel.onData) cirachannel.onData(cirachannel, data.substring(9, 9 + LengthOfData));
|
||||
if (cirachannel.amtpendingcredits > (cirachannel.ciraWindow / 2)) {
|
||||
SendChannelWindowAdjust(cirachannel.socket, cirachannel.amtchannelid, cirachannel.amtpendingcredits); // Adjust the buffer window
|
||||
cirachannel.amtpendingcredits = 0;
|
||||
return 17;
|
||||
}
|
||||
case APFProtocol.CHANNEL_OPEN_FAILURE:
|
||||
{
|
||||
if (len < 17) return 0;
|
||||
var RecipientChannel = common.ReadInt(data, 1);
|
||||
var ReasonCode = common.ReadInt(data, 5);
|
||||
channelOpenFailCount++;
|
||||
parent.debug('mpscmd', '--> CHANNEL_OPEN_FAILURE', RecipientChannel, ReasonCode);
|
||||
var cirachannel = socket.tag.channels[RecipientChannel];
|
||||
if (cirachannel == null) { console.log("MPS Error in CHANNEL_OPEN_FAILURE: Unable to find channelid " + RecipientChannel); return 17; }
|
||||
if (cirachannel.state > 0) {
|
||||
cirachannel.state = 0;
|
||||
if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
|
||||
delete socket.tag.channels[RecipientChannel];
|
||||
}
|
||||
return 17;
|
||||
}
|
||||
case APFProtocol.CHANNEL_CLOSE:
|
||||
{
|
||||
if (len < 5) return 0;
|
||||
var RecipientChannel = common.ReadInt(data, 1);
|
||||
channelCloseCount++;
|
||||
parent.debug('mpscmd', '--> CHANNEL_CLOSE', RecipientChannel);
|
||||
var cirachannel = socket.tag.channels[RecipientChannel];
|
||||
if (cirachannel == null) { console.log("MPS Error in CHANNEL_CLOSE: Unable to find channelid " + RecipientChannel); return 5; }
|
||||
socket.tag.activetunnels--;
|
||||
if (cirachannel.state > 0) {
|
||||
cirachannel.state = 0;
|
||||
if (cirachannel.onStateChange) { cirachannel.onStateChange(cirachannel, cirachannel.state); }
|
||||
SendChannelClose(cirachannel.socket, cirachannel.amtchannelid);
|
||||
delete socket.tag.channels[RecipientChannel];
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
case APFProtocol.CHANNEL_WINDOW_ADJUST:
|
||||
{
|
||||
if (len < 9) return 0;
|
||||
var RecipientChannel = common.ReadInt(data, 1);
|
||||
var ByteToAdd = common.ReadInt(data, 5);
|
||||
var cirachannel = socket.tag.channels[RecipientChannel];
|
||||
if (cirachannel == null) { console.log("MPS Error in CHANNEL_WINDOW_ADJUST: Unable to find channelid " + RecipientChannel); return 9; }
|
||||
cirachannel.sendcredits += ByteToAdd;
|
||||
parent.debug('mpscmd', '--> CHANNEL_WINDOW_ADJUST', RecipientChannel, ByteToAdd, cirachannel.sendcredits);
|
||||
if (cirachannel.state == 2 && cirachannel.sendBuffer != null) {
|
||||
// Compute how much data we can send
|
||||
if (cirachannel.sendBuffer.length <= cirachannel.sendcredits) {
|
||||
// Send the entire pending buffer
|
||||
SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer);
|
||||
cirachannel.sendcredits -= cirachannel.sendBuffer.length;
|
||||
delete cirachannel.sendBuffer;
|
||||
if (cirachannel.onSendOk) { cirachannel.onSendOk(cirachannel); }
|
||||
} else {
|
||||
// Send a part of the pending buffer
|
||||
SendChannelData(cirachannel.socket, cirachannel.amtchannelid, cirachannel.sendBuffer.substring(0, cirachannel.sendcredits));
|
||||
cirachannel.sendBuffer = cirachannel.sendBuffer.substring(cirachannel.sendcredits);
|
||||
cirachannel.sendcredits = 0;
|
||||
}
|
||||
return 9 + LengthOfData;
|
||||
}
|
||||
case APFProtocol.DISCONNECT:
|
||||
{
|
||||
if (len < 7) return 0;
|
||||
var ReasonCode = common.ReadInt(data, 1);
|
||||
disconnectCommandCount++;
|
||||
parent.debug('mpscmd', '--> DISCONNECT', ReasonCode);
|
||||
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
|
||||
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
|
||||
return 7;
|
||||
return 9;
|
||||
}
|
||||
case APFProtocol.CHANNEL_DATA:
|
||||
{
|
||||
if (len < 9) return 0;
|
||||
var RecipientChannel = common.ReadInt(data, 1);
|
||||
var LengthOfData = common.ReadInt(data, 5);
|
||||
if (len < (9 + LengthOfData)) return 0;
|
||||
parent.debug('mpscmddata', '--> CHANNEL_DATA', RecipientChannel, LengthOfData);
|
||||
var cirachannel = socket.tag.channels[RecipientChannel];
|
||||
if (cirachannel == null) { console.log("MPS Error in CHANNEL_DATA: Unable to find channelid " + RecipientChannel); return 9 + LengthOfData; }
|
||||
cirachannel.amtpendingcredits += LengthOfData;
|
||||
if (cirachannel.onData) cirachannel.onData(cirachannel, data.substring(9, 9 + LengthOfData));
|
||||
if (cirachannel.amtpendingcredits > (cirachannel.ciraWindow / 2)) {
|
||||
SendChannelWindowAdjust(cirachannel.socket, cirachannel.amtchannelid, cirachannel.amtpendingcredits); // Adjust the buffer window
|
||||
cirachannel.amtpendingcredits = 0;
|
||||
}
|
||||
default:
|
||||
{
|
||||
parent.debug('mpscmd', '--> Unknown CIRA command: ' + cmd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 9 + LengthOfData;
|
||||
}
|
||||
case APFProtocol.DISCONNECT:
|
||||
{
|
||||
if (len < 7) return 0;
|
||||
var ReasonCode = common.ReadInt(data, 1);
|
||||
disconnectCommandCount++;
|
||||
parent.debug('mpscmd', '--> DISCONNECT', ReasonCode);
|
||||
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
|
||||
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connType);
|
||||
return 7;
|
||||
}
|
||||
default:
|
||||
{
|
||||
parent.debug('mpscmd', '--> Unknown CIRA command: ' + cmd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
socket.addListener('close', function () {
|
||||
socketClosedCount++;
|
||||
parent.debug('mps', 'CIRA connection closed');
|
||||
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
|
||||
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
|
||||
});
|
||||
|
||||
socket.addListener('error', function () {
|
||||
socketErrorCount++;
|
||||
parent.debug('mps', 'CIRA connection error');
|
||||
//console.log("MPS Error: " + socket.remoteAddress);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Disconnect CIRA tunnel
|
||||
obj.close = function (socket) {
|
||||
try { socket.end(); } catch (e) { }
|
||||
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
|
||||
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
|
||||
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connType);
|
||||
};
|
||||
|
||||
function SendServiceAccept(socket, service) {
|
||||
|
@ -886,9 +920,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
// Print out sent bytes
|
||||
var buf = Buffer.from(data, 'binary');
|
||||
console.log('MPS <-- (' + buf.length + '):' + buf.toString('hex'));
|
||||
socket.write(buf);
|
||||
if (socket.websocket == 1) { socket.send(buf); } else { socket.write(buf); }
|
||||
} else {
|
||||
socket.write(Buffer.from(data, 'binary'));
|
||||
if (socket.websocket == 1) { socket.send(Buffer.from(data, 'binary')); } else { socket.write(Buffer.from(data, 'binary')); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue