Fixed meshagent connection race on the server.

Ylian Saint-Hilaire committed Aug 21, 2018 at 11:02 UTC d3db0e4ef645819dd89a30bcd5af1d9820bb8a21
8 files changed +89 -57
agents/modules_meshcmd/serviceManager.js
+9 -17
@@ -87,22 +87,12 @@ function serviceManager() {
87 }
88 return admin;
89 };
90 + this.getProgramFolder = function getProgramFolder() {
91 + if ((require('os').arch() == 'x64') && (this.GM.PointerSize == 4)) { return process.env['ProgramFiles(x86)']; } // 64 bit Windows with 32 Bit App
92 + return process.env['ProgramFiles']; // All other cases: 32 bit Windows or 64 bit App
93 + };
94 this.getServiceFolder = function getServiceFolder() {
91 - var destinationFolder = null;
92 - if (require('os').arch() == 'x64') {
93 - // 64 bit Windows
94 - if (this.GM.PointerSize == 4) {
95 - // 32 Bit App
96 - destinationFolder = process.env['ProgramFiles(x86)'];
97 - } else {
98 - // 64 bit App
99 - destinationFolder = process.env['ProgramFiles'];
100 - }
101 - } else {
102 - // 32 bit Windows
103 - destinationFolder = process.env['ProgramFiles'];
104 - }
105 - return (destinationFolder + '\\Open Source\\MeshCmd');
95 + return getProgramFolder() + '\\Open Source\\MeshCmd';
96 };
97
98 this.enumerateService = function () {
@@ -192,8 +182,10 @@ function serviceManager() {
182 if (!this.isAdmin()) { throw ('Installing as Service, requires administrator permissions.'); }
183
184 // Before we start, we need to copy the binary to the right place
195 - var folder = this.getServiceFolder();
196 - if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); }
185 + var folder = this.getProgramFolder() + '\\Open Source';
186 + if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); } // Create the "Open Source" folder
187 + folder += '\\MeshCmd';
188 + if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); } // Create the "MeshCmd" folder
189 require('fs').copyFileSync(options.servicePath, folder + '\\' + options.name + '.exe');
190 options.servicePath = folder + '\\' + options.name + '.exe';
191 console.log('Installing to "' + options.servicePath + '"');
certoperations.js
+14 -4
@@ -484,7 +484,16 @@ module.exports.CertificateOperations = function () {
484 if (acceleratorCreateCount > 0) {
485 acceleratorCreateCount--;
486 var accelerator = fork(program, [], { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] });
487 - accelerator.on('message', function (message) { this.func(message); if (pendingAccelerator.length > 0) { accelerator.send(pendingAccelerator.shift()); } else { freeAccelerators.push(this); } });
487 + accelerator.accid = acceleratorCreateCount;
488 + accelerator.on('message', function (message) {
489 + this.func(this.tag, message);
490 + delete this.tag;
491 + if (pendingAccelerator.length > 0) {
492 + var x = pendingAccelerator.shift();
493 + if (x.tag) { this.tag = x.tag; delete x.tag; }
494 + accelerator.send(x);
495 + } else { freeAccelerators.push(this); }
496 + });
497 accelerator.send({ action: 'setState', certs: obj.acceleratorCertStore });
498 return accelerator;
499 }
@@ -499,21 +508,22 @@ module.exports.CertificateOperations = function () {
508 }
509
510 // Perform any RSA signature, just pass in the private key and data.
502 - obj.acceleratorPerformSignature = function (privatekey, data, func) {
511 + obj.acceleratorPerformSignature = function (privatekey, data, tag, func) {
512 if (acceleratorTotalCount <= 1) {
513 // No accelerators available
514 if (typeof privatekey == 'number') { privatekey = obj.acceleratorCertStore[privatekey].key; }
515 const sign = obj.crypto.createSign('SHA384');
516 sign.end(new Buffer(data, 'binary'));
508 - func(sign.sign(privatekey).toString('binary'));
517 + func(tag, sign.sign(privatekey).toString('binary'));
518 } else {
519 var acc = obj.getAccelerator();
520 if (acc == null) {
521 // Add to pending accelerator workload
513 - pendingAccelerator.push({ action: 'sign', key: privatekey, data: data });
522 + pendingAccelerator.push({ action: 'sign', key: privatekey, data: data, tag: tag });
523 } else {
524 // Send to accelerator now
525 acc.func = func;
526 + acc.tag = tag;
527 acc.send({ action: 'sign', key: privatekey, data: data });
528 }
529 }
meshagent.js
+12 -5
@@ -6,6 +6,8 @@
6 * @version v0.0.1
7 */
8
9 +var AgentConnectCount = 0;
10 +
11 // Construct a MeshAgent object, called upon connection
12 module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
13 var obj = {};
@@ -30,6 +32,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
32 const agentUpdateBlockSize = 65520;
33 obj.remoteaddr = obj.ws._socket.remoteAddress;
34 obj.useSHA386 = false;
35 + obj.agentConnectCount = ++AgentConnectCount;
36 if (obj.remoteaddr.startsWith('::ffff:')) { obj.remoteaddr = obj.remoteaddr.substring(7); }
37 ws._socket.setKeepAlive(true, 240000); // Set TCP keep alive, 4 minutes
38
@@ -65,6 +68,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
68 if ((state.connectivity & 2) != 0) { obj.parent.parent.mpsserver.close(obj.parent.parent.mpsserver.ciraConnections[obj.dbNodeKey]); } // Disconnect CIRA connection
69 }
70 }
71 + delete obj.nodeid;
72 }
73
74 // When data is received from the mesh agent web socket
@@ -183,15 +187,15 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
187 obj.agentnonce = msg.substring(50);
188 if (obj.useSwarmCert == true) {
189 // Perform the hash signature using older swarm server certificate
186 - obj.parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, function (signature) {
190 + obj.parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
191 // Send back our certificate + signature
188 - obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.parent.swarmCertificateAsn1.length) + obj.parent.swarmCertificateAsn1 + signature); // Command 2, certificate + signature
192 + obj2.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.parent.swarmCertificateAsn1.length) + obj2.parent.swarmCertificateAsn1 + signature); // Command 2, certificate + signature
193 });
194 } else {
195 // Perform the hash signature using the server agent certificate
192 - obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, function (signature) {
196 + obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
197 // Send back our certificate + signature
194 - obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.parent.agentCertificateAsn1.length) + obj.parent.agentCertificateAsn1 + signature); // Command 2, certificate + signature
198 + obj2.send(obj2.common.ShortToStr(2) + obj.common.ShortToStr(obj2.parent.agentCertificateAsn1.length) + obj2.parent.agentCertificateAsn1 + signature); // Command 2, certificate + signature
199 });
200 }
201
@@ -259,7 +263,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
263
264 // Once we get all the information about an agent, run this to hook everything up to the server
265 function completeAgentConnection() {
262 - if (obj.authenticated =! 1 || obj.meshid == null) return;
266 + if (obj.authenticated = !1 || obj.meshid == null || obj.pendingCompleteAgentConnection) return;
267 + obj.pendingCompleteAgentConnection = true;
268 +
269 // Check that the mesh exists
270 obj.db.Get(obj.dbMeshKey, function (err, meshes) {
271 if (meshes.length == 0) { console.log('Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddr + ', ' + obj.dbMeshKey + ').'); return; } // If we disconnect, the agnet will just reconnect. We need to log this or tell agent to connect in a few hours.
@@ -327,6 +333,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
333 }
334
335 // We are done, ready to communicate with this agent
336 + delete obj.pendingCompleteAgentConnection;
337 obj.authenticated = 2;
338
339 // Command 4, inform mesh agent that it's authenticated.
multiserver.js
+4 -4
@@ -94,9 +94,9 @@ module.exports.CreateMultiServer = function (parent, args) {
94 obj.servernonce = msg.substring(50);
95
96 // Perform the hash signature using the server agent certificate
97 - obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, function (signature) {
97 + obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
98 // Send back our certificate + signature
99 - obj.ws.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificateAsn1.length) + obj.agentCertificateAsn1 + signature); // Command 2, certificate + signature
99 + obj2.ws.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature
100 });
101
102 break;
@@ -257,9 +257,9 @@ module.exports.CreateMultiServer = function (parent, args) {
257 obj.peernonce = msg.substring(50);
258
259 // Perform the hash signature using the server agent certificate
260 - obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, function (signature) {
260 + obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (signature) {
261 // Send back our certificate + signature
262 - obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificateAsn1.length) + obj.agentCertificateAsn1 + signature); // Command 2, certificate + signature
262 + obj2.send(obj2.common.ShortToStr(2) + obj.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature
263 });
264
265 // Check the peer server signature if we can
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.1.9-i",
3 + "version": "0.1.9-j",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",
views/default-mobile.handlebars
+11 -5
@@ -1177,6 +1177,10 @@
1177 // MY DEVICES
1178 //
1179
1180 + // Since the update device call can be quite frequent, we can moderate it and only call it at most 5 times a second.
1181 + var updateDevicesTimer = null;
1182 + function updateDevices() { if (updateDevicesTimer != null) return; updateDevicesTimer = setTimeout(updateDevicesEx, 200); }
1183 +
1184 var sort = 0;
1185 var deviceHeaderId = 0;
1186 var deviceHeaderCount;
@@ -1185,7 +1189,7 @@
1189 var deviceHeaderTotal = 0;
1190 var deviceHeaders = {};
1191 var deviceHeadersTitles = {};
1188 - function updateDevices() {
1192 + function updateDevicesEx() {
1193 var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, groups = {}, groupCount = {};
1194
1195 // 3 wide, list view or desktop view
@@ -1196,6 +1200,11 @@
1200 deviceHeadersTitles = {};
1201 var current;
1202
1203 + // Perform node sort
1204 + if (sort == 0) { nodes.sort(meshSort); }
1205 + else if (sort == 1) { nodes.sort(powerSort); }
1206 + else if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
1207 +
1208 // Go thru the list of nodes and display them
1209 for (var i in nodes) {
1210 if (nodes[i].v == false) continue;
@@ -1324,10 +1333,7 @@
1333 function onSortSelectChange(skipsave) {
1334 sort = document.getElementById("sortselect").selectedIndex;
1335 if (!skipsave) { putstore("sort", sort); }
1327 - if (sort == 0) { nodes.sort(meshSort); }
1328 - if (sort == 1) { nodes.sort(powerSort); }
1329 - if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
1330 - updateDevices();
1336 + updateDevicesEx();
1337 }
1338
1339 function deviceHeaderSet() {
views/default.handlebars
+27 -20
@@ -842,7 +842,6 @@
842 // Display the page devices
843 onSortSelectChange();
844 onSearchInputChanged();
845 - updateDevices();
845
846 // Setup upload drag & drop
847 Q('p5filetable').addEventListener("drop", p5fileDragDrop, false);
@@ -1494,11 +1493,16 @@
1493 if (Q('viewselect').value == 3) { if ((e.keyCode === 8 && mapSearchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
1494 }
1495
1496 + // Since the update device call can be quite frequent, we can moderate it and only call it at most 5 times a second.
1497 + var updateDevicesTimer = null;
1498 + function updateDevices() { if (updateDevicesTimer != null) return; updateDevicesTimer = setTimeout(updateDevicesEx, 200); }
1499 +
1500 var deviceHeaderId = 0;
1501 var deviceHeaderCount;
1502 var deviceHeaders = {};
1503 var oldviewmode = 0;
1501 - function updateDevices() {
1504 + function updateDevicesEx() {
1505 + if (updateDevicesTimer != null) { clearTimeout(updateDevicesTimer); updateDevicesTimer = null; }
1506 var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, view = Q('viewselect').value, groups = {}, groupCount = {};
1507 QV('xdevices', view < 4);
1508 QV('xdevicesmap', view == 4);
@@ -1522,9 +1526,14 @@
1526 deviceHeadersTitles = {};
1527 var kvmDivs = [];
1528
1529 + // Perform node sort
1530 + if (sort == 0) { nodes.sort(meshSort); }
1531 + else if (sort == 1) { nodes.sort(powerSort); }
1532 + else if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
1533 +
1534 // Save the list of currently checked nodeid's
1535 var checkedNodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
1527 - for (var i in elements) { if (elements[i].checked) { checkedNodeids.push(elements[i].value); } }
1536 + for (var i=0;i<elements.length;i++) { if (elements[i].checked) { checkedNodeids.push(elements[i].value); } }
1537 if ((oldviewmode < 3) && (view == 3)) { multiDesktopFilter = checkedNodeids; }
1538 else if ((oldviewmode == 3) && (view < 3)) { checkedNodeids = multiDesktopFilter; }
1539
@@ -1551,11 +1560,12 @@
1560 }
1561 } else if (sort == 1) {
1562 // Power header
1554 - if (nodes[i].pwr !== current) {
1563 + var pwr = nodes[i].pwr?nodes[i].pwr:0;
1564 + if (pwr !== current) {
1565 deviceHeaderSet();
1566 if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
1567 r += '<div class=DevSt style=width:100%;padding-top:4px><span>' + PowerStateStr2(nodes[i].pwr) + '</span><span id=DevxHeader' + deviceHeaderId + ' class="devHeaderx"></span></div>';
1558 - current = nodes[i].pwr;
1568 + current = pwr;
1569 c = 0;
1570 }
1571 } else if (sort == 2) {
@@ -1670,7 +1680,7 @@
1680
1681 // Re-check nodeid's
1682 var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
1673 - for (var i in elements) { elements[i].checked = (checkedNodeids.indexOf(elements[i].value) >= 0); }
1683 + for (var i=0;i<elements.length;i++) { elements[i].checked = (checkedNodeids.indexOf(elements[i].value) >= 0); }
1684
1685 for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
1686 for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
@@ -1862,7 +1872,7 @@
1872 // Called when OK is pressed on the Intel AMT scanning box
1873 function addAmtScanToMeshEx(button, meshid) {
1874 var elements = document.getElementsByClassName("DevScanCheckbox"), checkcount = 0;
1865 - for (var i in elements) {
1875 + for (var i=0;i<elements.length;i++) {
1876 if (elements[i].checked) {
1877 var ipaddr = elements[i].getAttribute('tag');
1878 var amtinfo = amtScanResults[ipaddr];
@@ -1882,7 +1892,7 @@
1892 // Called when a scanned computer is checked or unchecked.
1893 function addAmtScanToMeshCheckbox() {
1894 var elements = document.getElementsByClassName("DevScanCheckbox"), checkcount = 0;
1885 - for (var i in elements) { if (elements[i].checked) checkcount++; }
1895 + for (var i=0;i<elements.length;i++) { if (elements[i].checked) checkcount++; }
1896 QE('idx_dlgOkButton', checkcount > 0);
1897 }
1898
@@ -2063,14 +2073,14 @@
2073
2074 function selectallButtonFunction() {
2075 var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
2066 - for (var i in elements) { if (elements[i].checked) checkcount++; }
2067 - for (var i in elements) { elements[i].checked = (checkcount == 0); }
2076 + for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) checkcount++; }
2077 + for (var i=0;i<elements.length;i++) { elements[i].checked = (checkcount == 0); }
2078 p1updateInfo();
2079 }
2080
2081 function p1updateInfo() {
2082 var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
2073 - for (var i in elements) { if (elements[i].checked) checkcount++; }
2083 + for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) { checkcount++; } }
2084 if (checkcount > 0) {
2085 QE('GroupActionButton', true);
2086 Q('SelectAllButton').value = 'Select None';
@@ -2093,7 +2103,7 @@
2103 // Get the list of checked devices, removes any duplicates.
2104 function getCheckedDevices() {
2105 var nodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
2096 - for (var i in elements) { if (elements[i].checked) { if (elements[i].value) { var nid = elements[i].value.substring(6); if (nodeids.indexOf(nid) == -1) { nodeids.push(nid); } } } }
2106 + for (var i=0;i<elements.length;i++) { if (elements[i].checked) { if (elements[i].value) { var nid = elements[i].value.substring(6); if (nodeids.indexOf(nid) == -1) { nodeids.push(nid); } } } }
2107 return nodeids;
2108 }
2109
@@ -2120,14 +2130,11 @@
2130 function onSortSelectChange(skipsave) {
2131 sort = document.getElementById("sortselect").selectedIndex;
2132 if (!skipsave) { putstore("sort", sort); }
2123 - if (sort == 0) { nodes.sort(meshSort); }
2124 - if (sort == 1) { nodes.sort(powerSort); }
2125 - if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
2126 - updateDevices();
2133 + updateDevicesEx();
2134 }
2135
2136 function meshSort(a, b) { if (a.meshnamel > b.meshnamel) return 1; if (a.meshnamel < b.meshnamel) return -1; if (a.meshid == b.meshid) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
2130 - function powerSort(a, b) { var ap = a.pwr?a.pwr:0; var bp = b.pwr?b.pwr:0; if (ap == bp) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } if (ap > bp) return 1; if (ap < bp) return -1; return 0; }
2137 + function powerSort(a, b) { var ap = a.pwr?a.pwr:0; var bp = b.pwr?b.pwr:0; if (ap > bp) return -1; if (ap < bp) return 1; if (ap == bp) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
2138 function deviceSort(a, b) { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; }
2139 function deviceHostSort(a, b) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; }
2140 function onSearchFocus(x) { searchFocus = x; }
@@ -2200,8 +2207,8 @@
2207 function cmmeshaction(action) {
2208 var meshid = contextelement.attributes.onclick.value.substring(32, (32 + 69));
2209 var elements = document.getElementsByClassName("DeviceCheckbox");
2203 - if (action == 1) { for (var i in elements) { if (elements[i].attributes && elements[i].attributes.class.value.substring(0, 69) == meshid) { elements[i].checked = true; } } }
2204 - if (action == 2) { for (var i in elements) { if (elements[i].attributes && elements[i].attributes.class.value.substring(0, 69) == meshid) { elements[i].checked = false; } } }
2210 + if (action == 1) { for (var i=0;i<elements.length;i++) { if (elements[i].attributes && elements[i].attributes.class.value.substring(0, 69) == meshid) { elements[i].checked = true; } } }
2211 + if (action == 2) { for (var i=0;i<elements.length;i++) { if (elements[i].attributes && elements[i].attributes.class.value.substring(0, 69) == meshid) { elements[i].checked = false; } } }
2212 //if (action == 3) { window.location = "multidesktop.aspx?mesh=" + meshid + "&auto=1"; }
2213 p1updateInfo();
2214 }
@@ -5802,7 +5809,7 @@
5809 QV('UserSubMenuSpan', x >= 30 && x < 40);
5810 QS('UserGeneral').backgroundColor = ((x == 30) ? "#003366" : "#808080");
5811 QS('UserEvents').backgroundColor = ((x == 31) ? "#003366" : "#808080");
5805 - if (x == 1) updateDevices();
5812 + if (x == 1) updateDevicesEx();
5813 }
5814
5815 // Generic methods
webserver.js
+11 -1
@@ -71,6 +71,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
71 obj.userAllowedIp = args.userallowedip; // List of allowed IP addresses for users
72 obj.tlsSniCredentials;
73 obj.dnsDomains = {};
74 + //obj.agentConnCount = 0;
75
76 // Mesh Rights
77 const MESHRIGHT_EDITMESH = 1;
@@ -1695,7 +1696,16 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
1696 obj.app.ws(url + 'meshrelay.ashx', function (ws, req) { try { obj.meshRelayHandler.CreateMeshRelay(obj, ws, req, getDomain(req)); } catch (e) { console.log(e); } });
1697
1698 // Receive mesh agent connections
1698 - obj.app.ws(url + 'agent.ashx', function (ws, req) { try { obj.meshAgentHandler.CreateMeshAgent(obj, obj.db, ws, req, obj.args, getDomain(req)); } catch (e) { console.log(e); } });
1699 + obj.app.ws(url + 'agent.ashx', function (ws, req) {
1700 + //console.log(++obj.agentConnCount);
1701 + /*
1702 + var ip, port, type;
1703 + if (req.connection) { ip = req.connection.remoteAddress; port = req.connection.remotePort; type = 1; } // HTTP(S) request
1704 + else if (req._socket) { ip = req._socket.remoteAddress; port = req._socket.remotePort; type = 2; } // WebSocket request
1705 + console.log('AgentConnect', ip, port, type);
1706 + */
1707 + try { obj.meshAgentHandler.CreateMeshAgent(obj, obj.db, ws, req, obj.args, getDomain(req)); } catch (e) { console.log(e); }
1708 + });
1709
1710 obj.app.get(url + 'stop', function (req, res) { res.send('Stopping Server, <a href="' + url + '">click here to login</a>.'); setTimeout(function () { parent.Stop(); }, 500); });
1711