From 81ccbae15cfddeaef6c3cea1f84f0e807847a580 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Fri, 13 Jul 2018 19:18:43 -0700 Subject: [PATCH] Fixed usernames that include a dot (.) --- agents/MeshCmd-signed.exe | Bin 3347160 -> 3347304 bytes agents/MeshCmd64-signed.exe | Bin 3341016 -> 3341160 bytes agents/meshcmd.js | 5 ++ agents/meshcore.js | 5 ++ certoperations.js | 108 +++++++++++++------------- common.js | 10 +++ db.js | 11 +-- meshcentral.js | 35 ++++++--- meshuser.js | 13 ++-- mpsserver.js | 1 - package.json | 2 +- public/scripts/agent-desktop-0.0.2.js | 1 + public/scripts/common-0.0.1.js | 6 +- public/scripts/meshcentral.js | 5 ++ views/default.handlebars | 13 +++- webserver.js | 15 ++-- 16 files changed, 139 insertions(+), 91 deletions(-) diff --git a/agents/MeshCmd-signed.exe b/agents/MeshCmd-signed.exe index 23e19265aa1a81119acf9c9df89fd2c32b32183c..4edd965f0db8c55ee5d5c5a752cd02accc155f28 100644 GIT binary patch delta 1040 zcmcby^bF&RWoH;S6fiPrdrvN6v||eR(7cJUeG?-HGXXI(5VHU=D-g2*F*^`*05K;J za{)0o5c2>rFA(zqF+UIs0I?tt3jwh(5Q_k@C=iPQu{aP*0I?(xO98Po5X%6uED*~9 zu{;nfY~RGF81P}D0ZTj6Cq*Du0%Bz#R@u(a3EXW6HQmECmo_=w@ zk^c4-6OGv7nEshf-|*gOu0rvJfazDCdmemWFtNe*eg3+b0F|SeTS^W^n;r1q-~Oh3 zd+rA#WBGdat?7^4^5b?|?>w=UbNQBO-vw*}ZhOqEdmG!Ba^aL}g#j-cr&gOs+jm|@ zMn+Z!mL^69*DbqdJPet(xAL92N9t+e)wYYGABmJs)H)Ml;D+#R9lb>pRcmdv9JdtZ+#$MC}k9dss~kV$c>PHUML z@xON?Yx_kWq3`8W7M}ZQ)NC7YtYybK-ZNo$8b8LpxwfE;SMQ*HaMq`Xo7=*K52lnJ zYhBha9TM?rhcwSZg`cL9@vqEIM%6FS;&S^nJd!~J?J+fz-D@#5566I53FGaE~zJ3m1l?yipu)VH1$y|E+a z(5IfL*4=NN)@Eh|?BqKA_RyJXjd@`^BvSTCzwx;D#%xXZ*6r&oCYs*-;K6HBRJXFA zcw@%3J?-%|Yj*g!E^=pxzI_&s#{zm`<1ONaI$;pra delta 958 zcmYk&eNfs39LI5f3aBW8!(metP#$~$<%7Dx>^cW)f2i}JhNQ{X*3Ep_gGSf4^RDZA_qy-h=g;@U9v3p* z?Lzvik$}~D!x=;pF#7ZpE26U^{|W$s01Yqz3xYr}2mv?{3c>&$gaZN~f(Wn;kU%8Z z4#*%1yaINBXb=M^AQr>{Dxle{2z}qO4!c4J@gM;(Y}gfMay6o`@rzma$%vu_K1Ih= zvTRHx+YpQhw}wd#TQ{jm1W6znqyP@!f>e+Ocz|!4)CleqY&)9-*!KebrWWb4z(_0q zfF&G4QoRR$neSw2Sjwg9jwc#vuhe*N`zfpZl*Z;?76_^8a>k?R=3`F#SZ>$3Ct0Tt zU47|I<7U_6*cT{ssxJ*59v&N#Tqmo0jz7e zqgCjj*4R9~p<<~A*WrpCzNCCuGv7QkG4mmZSh_%aQG)QK1y>WaK4#jFe%h|zzZVrx z_)%>= zVrhQ7c6ve7^PBtgD`mC+uZY>I*fNVRtzE=qsb5n?)%D0XmfCOJ{m5uZQb-6D>1X_H zn*&uTGqZhtbEkt=eN)*r>l3q#$b%i9aR~E_BS|?;kJa7zUUXl-pBY>jIIVay_OGx# z3$6@&KAqNnF@zQ~V@a@4L>KdDplEcNeeW9jw`$Fp(DH}#Z@ ziHDWcbpjy-F^Sv04m)Y?ZhgTh{?)9nthj|Dnb^ieuH%lr@@9FVZ*481=2AwY4%Pi? z#cG4&_4XYD502{dc)JwGiZ*k{7P({iY*}Sp?}*;R7c<0vynV+j$C=WflTP&0?Q7vf WUg4*4RC$4uu@U1fSP2xMw(cK^CR z!a)R}fmZuKkx6w1Bv>6n^A#$FhQgT3>iq7s8E!b*#aRajA(;^Sfp*_5}RzmBB(2%fM{ z5;9B^20q8ySIZ~v#I2;5EK~eeEG@~>blP*~DU)(g=3~n82Z>|twcm?mJjI!^m1MQt zTJGWtVl<1Hr@S^|9{#E$_&`G;yXNVTLEk(P-Fj?Aw7F$EB(d~w>z619f)D~w z9TE`Q)hd47QsQTtdUnrPDDRSQ*0-Gh#^mx<^-s^G=kD;(n)Eu!&>i3St@$YP@>ZE} zr1`5-^2z4OY;{3h2cym2zw7hpfvtXq)vZy;4M`R9`M59lFR$r6HDwu#+@)yybH2Zm zE_IY=wW4#Eg1T>gH%Q0MX&FS}2dasv@wx27<^!Fbi^pcwzm;U|p^Pb&wv>z2rLr&f zEnN0yC{CnK*7S*w#{ccBSk8KHO8Z8B!=3AsH#|>fv?G|Lqo+$BjJHLZX)~$39m2Po zpNJQ8t~^$`UyE69IYbuheArzlTwvL1dLtfn9%QS#g%7SdZW@1_j_9|etok;yCS=5P z-OInK5hSN_1@Cj${vU{h^1@MSEGm86L-wMP?S|vRDqlr|*CcqcBH?*O-6(CT@BG3j z%k8+YTol`WP2t_@*=pKaexN{$5P5CfA7q@N~G2%(M+*$!{+R&y=<}kMu&x+dhP3b&U^OwMq+u{s(zJCG2nywfC delta 924 zcmaFy?KIE==*M*6dh;d5_DhT)%ml>DK+FQftU$~L#Oy%K0mPg@ z%mu{UK+FTgygBIFqQQ-Jwp)rotOUf$K&%49sz9s;#Ogq-0mPa>tOdl{K&%7Ax3`IOi5Mca~fdIrje0gfHA@CHhR>=)C(` z_(tmR`|W>k7#YjgKbV)^S+;G)#^gRW)%le)=ddluelzMqz}!a?}!1c&HM+m<(CX&foq*+qwrx=y=qWp{hV zhXR|RRtE3m0&bJ|>v|$yEsH6Yc{S0L;irk5-9LWebz<%6Ta;ZUwTmqM@ulkYPeXx0O%B{YHZ?%MJSMkz6fpQz==R~tG<{1dG?fbCA{N;Mi!$+7Gytgq} zJVm0w@#>AI54MZsga<52S=cz~o$KA;>B&Eh4%8bMn;05K87RX8h?B)oj76j-Vk3Lu zZ`YjL{l*#-iyy7GFca)X4ny7Hk(Mq-g641c zCx?6A-F#lSJ#Fc`&$(~Kh9i`@R+2 z*-^PAmus<@iv**H&rU{JrBAWv=a)XN{Zz*+agC8HJ?Ko>v&;4my_T= minlen)) && ((maxlen == null) || (str.length <= maxlen))); } module.exports.validateInt = function(int, minval, maxval) { return ((int != null) && (typeof int == 'number') && ((minval == null) || (int >= minval)) && ((maxval == null) || (int <= maxval))); } diff --git a/db.js b/db.js index f10380ee..882855b0 100644 --- a/db.js +++ b/db.js @@ -17,24 +17,25 @@ // Just run with --mongodb [connectionstring], where the connection string is documented here: https://docs.mongodb.com/manual/reference/connection-string/ // The default collection is "meshcentral", but you can override it using --mongodbcol [collection] // -module.exports.CreateDB = function (args, datapath) { +module.exports.CreateDB = function (parent) { var obj = {}; obj.path = require('path'); + obj.parent = parent; obj.identifier = null; - if (args.mongodb) { + if (obj.parent.args.mongodb) { // Use MongoDB obj.databaseType = 2; var Datastore = require('mongojs'); - var db = Datastore(args.mongodb); + var db = Datastore(obj.parent.args.mongodb); var dbcollection = 'meshcentral'; - if (args.mongodbcol) { dbcollection = args.mongodbcol; } + if (obj.parent.args.mongodbcol) { dbcollection = obj.parent.args.mongodbcol; } obj.file = db.collection(dbcollection); } else { // Use NeDB (The default) obj.databaseType = 1; var Datastore = require('nedb'); - obj.file = new Datastore({ filename: obj.path.join(datapath, 'meshcentral.db'), autoload: true }); + obj.file = new Datastore({ filename: obj.parent.getConfigFilePath('meshcentral.db'), autoload: true }); obj.file.persistence.setAutocompactionInterval(3600); } diff --git a/meshcentral.js b/meshcentral.js index 11ca7e13..796ceec8 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -99,6 +99,7 @@ function CreateMeshCentralServer(config, args) { console.log(' --redirport [number] Creates an additional HTTP server to redirect users to the HTTPS server.'); console.log(' --exactports Server must run with correct ports or exit.'); console.log(' --noagentupdate Server will not update mesh agent native binaries.'); + console.log(' --fastcert Generate weaker RSA2048 certificates.'); console.log(' --cert [name], (country), (org) Create a web server certificate with [name] server name.'); console.log(' country and organization can optionaly be set.'); return; @@ -169,7 +170,7 @@ function CreateMeshCentralServer(config, args) { xprocess.stdout.on('data', function (data) { if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); } if (data.indexOf('Updating settings folder...') >= 0) { xprocess.xrestart = 1; } else if (data.indexOf('Updating server certificates...') >= 0) { xprocess.xrestart = 1; } else if (data.indexOf('Server Ctrl-C exit...') >= 0) { xprocess.xrestart = 2; } else if (data.indexOf('Starting self upgrade...') >= 0) { xprocess.xrestart = 3; } console.log(data); }); xprocess.stderr.on('data', function (data) { if (data.startsWith('le.challenges[tls-sni-01].loopback')) { return; } // Ignore this error output from GreenLock - if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); } obj.fs.appendFileSync(obj.path.join(obj.datapath, 'mesherrors.txt'), '-------- ' + new Date().toLocaleString() + ' --------\r\n\r\n' + data + '\r\n\r\n\r\n'); + if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); } obj.fs.appendFileSync(obj.getConfigFilePath('mesherrors.txt'), '-------- ' + new Date().toLocaleString() + ' --------\r\n\r\n' + data + '\r\n\r\n\r\n'); }); xprocess.on('close', function (code) { if ((code != 0) && (code != 123)) { /* console.log("Exited with code " + code); */ } }); } @@ -237,7 +238,7 @@ function CreateMeshCentralServer(config, args) { if (obj.args.notls == null && obj.args.redirport == null) obj.args.redirport = 80; if (typeof obj.args.debug == 'number') obj.debugLevel = obj.args.debug; if (obj.args.debug == true) obj.debugLevel = 1; - obj.db = require('./db.js').CreateDB(obj.args, obj.datapath); + obj.db = require('./db.js').CreateDB(obj); obj.db.SetupDatabase(function (dbversion) { // See if any database operations needs to be completed if (obj.args.deletedomain) { obj.db.DeleteDomain(obj.args.deletedomain, function () { console.log('Deleted domain ' + obj.args.deletedomain + '.'); process.exit(); }); return; } @@ -254,7 +255,7 @@ function CreateMeshCentralServer(config, args) { if (obj.args.logintokenkey) { obj.showLoginTokenKey(function (r) { console.log(r); process.exit(); }); return; } if (obj.args.dbexport) { // Export the entire database to a JSON file - if (obj.args.dbexport == true) { obj.args.dbexport = obj.path.join(obj.datapath, 'meshcentral.db.json'); } + if (obj.args.dbexport == true) { obj.args.dbexport = obj.getConfigFilePath('meshcentral.db.json'); } obj.db.GetAll(function (err, docs) { obj.fs.writeFileSync(obj.args.dbexport, JSON.stringify(docs)); console.log('Exported ' + docs.length + ' objects(s) to ' + obj.args.dbexport + '.'); process.exit(); @@ -263,12 +264,14 @@ function CreateMeshCentralServer(config, args) { } if (obj.args.dbimport) { // Import the entire database from a JSON file - if (obj.args.dbimport == true) { obj.args.dbimport = obj.path.join(obj.datapath, 'meshcentral.db.json'); } - var json = null; + if (obj.args.dbimport == true) { obj.args.dbimport = obj.getConfigFilePath('meshcentral.db.json'); } + var json = null, json2 = ""; try { json = obj.fs.readFileSync(obj.args.dbimport); } catch (e) { console.log('Invalid JSON file: ' + obj.args.dbimport + '.'); process.exit(); } - try { json = JSON.parse(json); } catch (e) { console.log('Invalid JSON format: ' + obj.args.dbimport + '.'); process.exit(); } + for (var i = 0; i < json.length; i++) { if (json[i] >= 32) json2 += String.fromCharCode(json[i]); } // Remove all bad chars + try { json = JSON.parse(json2); } catch (e) { console.log('Invalid JSON format: ' + obj.args.dbimport + ': ' + e); process.exit(); } if ((json == null) || (typeof json.length != 'number') || (json.length < 1)) { console.log('Invalid JSON format: ' + obj.args.dbimport + '.'); } - obj.db.RemoveAll(function () { obj.db.InsertMany(json, function () { console.log('Imported ' + json.length + ' objects(s) from ' + obj.args.dbimport + '.'); process.exit(); }); }); + for (var i in json) { if ((json[i].type == "mesh") && (json[i].links != null)) { for (var j in json[i].links) { var esc = obj.common.escapeFieldName(j); if (esc !== j) { json[i].links[esc] = json[i].links[j]; delete json[i].links[j]; } } } } // Escape MongoDB invalid field chars + obj.db.RemoveAll(function () { obj.db.InsertMany(json, function (err) { if (err != null) { console.log(err); } else { console.log('Imported ' + json.length + ' objects(s) from ' + obj.args.dbimport + '.'); } process.exit(); }); }); return; } @@ -330,7 +333,7 @@ function CreateMeshCentralServer(config, args) { obj.StartEx2 = function () { // Load server certificates obj.certificateOperations = require('./certoperations.js').CertificateOperations() - obj.certificateOperations.GetMeshServerCertificate(obj.datapath, obj.args, obj.config, obj, function (certs) { + obj.certificateOperations.GetMeshServerCertificate(obj, obj.args, obj.config, function (certs) { if (obj.config.letsencrypt == null) { obj.StartEx3(certs); // Just use the configured certificates } else { @@ -496,8 +499,8 @@ function CreateMeshCentralServer(config, args) { zipfile.openReadStream(entry, function (err, readStream) { if (err) throw err; readStream.on("end", function () { zipfile.readEntry(); }); - // console.log('Extracting:', obj.path.join(obj.datapath, entry.fileName)); - readStream.pipe(obj.fs.createWriteStream(obj.path.join(obj.datapath, entry.fileName))); + // console.log('Extracting:', obj.getConfigFilePath(entry.fileName)); + readStream.pipe(obj.fs.createWriteStream(obj.getConfigFilePath(entry.fileName))); }); } }); @@ -1044,7 +1047,7 @@ function CreateMeshCentralServer(config, args) { } r = 'time=' + Date.now() + '\r\n'; for (var i in meshServerState) { r += (i + '=' + meshServerState[i] + '\r\n'); } - obj.fs.writeFileSync(obj.path.join(obj.datapath, 'serverstate.txt'), r); + obj.fs.writeFileSync(obj.getConfigFilePath('serverstate.txt'), r); } // Logging funtions @@ -1074,6 +1077,16 @@ function CreateMeshCentralServer(config, args) { } catch (e) { console.log(e); if (called == false) { func(null); } } } + // Return the path of a file into the meshcentral-data path + obj.getConfigFilePath = function (filename) { + if ((obj.config != null) && (obj.config.configfiles != null) && (obj.config.configfiles[filename] != null) && (typeof obj.config.configfiles[filename] == 'string')) { + //console.log('getConfigFilePath(\"' + filename + '\") = ' + obj.config.configfiles[filename]); + return obj.config.configfiles[filename]; + } + //console.log('getConfigFilePath(\"' + filename + '\") = ' + obj.path.join(obj.datapath, filename)); + return obj.path.join(obj.datapath, filename); + } + return obj; } diff --git a/meshuser.js b/meshuser.js index 57a63ce6..df05a571 100644 --- a/meshuser.js +++ b/meshuser.js @@ -111,6 +111,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { if ((user == null) || (obj.common.validateString(command.action, 3, 32) == false)) return; // User must be set and action must be a string between 3 and 32 chars switch (command.action) { + case 'ping': { ws.send(JSON.stringify({ action: 'pong' })); break; } case 'meshes': { // Request a list of all meshes this user as rights to @@ -565,7 +566,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { var links = {} links[user._id] = { name: user.name, rights: 0xFFFFFFFF }; var mesh = { type: 'mesh', _id: meshid, name: command.meshname, mtype: command.meshtype, desc: command.desc, domain: domain.id, links: links }; - obj.db.Set(mesh); + obj.db.Set(obj.common.escapeLinksFieldName(mesh)); obj.parent.meshes[meshid] = mesh; obj.parent.parent.AddEventDispatch([meshid], ws); if (user.links == null) user.links = {}; @@ -583,7 +584,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { if (obj.common.validateString(command.meshid, 1, 1024) == false) break; // Check the meshid obj.db.Get(command.meshid, function (err, meshes) { if (meshes.length != 1) return; - var mesh = meshes[0]; + var mesh = obj.common.unEscapeLinksFieldName(meshes[0]); // Check if this user has rights to do this if (mesh.links[user._id] == null || mesh.links[user._id].rights != 0xFFFFFFFF) return; @@ -627,7 +628,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { if ((obj.common.validateString(command.meshname, 1, 64) == true) && (command.meshname != mesh.name)) { change = 'Mesh name changed from "' + mesh.name + '" to "' + command.meshname + '"'; mesh.name = command.meshname; } if ((obj.common.validateString(command.desc, 0, 1024) == true) && (command.desc != mesh.desc)) { if (change != '') change += ' and description changed'; else change += 'Mesh "' + mesh.name + '" description changed'; mesh.desc = command.desc; } - if (change != '') { obj.db.Set(mesh); obj.parent.parent.DispatchEvent(['*', mesh._id, user._id], obj, { etype: 'mesh', username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }) } + if (change != '') { obj.db.Set(obj.common.escapeLinksFieldName(mesh)); obj.parent.parent.DispatchEvent(['*', mesh._id, user._id], obj, { etype: 'mesh', username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }) } } break; } @@ -659,7 +660,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { // Add a user to the mesh mesh.links[newuserid] = { name: newuser.name, rights: command.meshadmin }; - obj.db.Set(mesh); + obj.db.Set(obj.common.escapeLinksFieldName(mesh)); // Notify mesh change var change = 'Added user ' + newuser.name + ' to mesh ' + mesh.name; @@ -685,7 +686,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { // Remove mesh from user if (deluser.links != null && deluser.links[command.meshid] != null) { var delmeshrights = deluser.links[command.meshid].rights; - if ((delmeshrights == 0xFFFFFFFF) && (mesh.links[user._id].rights != 0xFFFFFFFF)) return; // A non-admin can't kick out an admin + if ((delmeshrights == 0xFFFFFFFF) && (mesh.links[deluserid].rights != 0xFFFFFFFF)) return; // A non-admin can't kick out an admin delete deluser.links[command.meshid]; obj.db.Set(deluser); obj.parent.parent.DispatchEvent([deluser._id], obj, 'resubscribe'); @@ -695,7 +696,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) { // Remove user from the mesh if (mesh.links[command.userid] != null) { delete mesh.links[command.userid]; - obj.db.Set(mesh); + obj.db.Set(obj.common.escapeLinksFieldName(mesh)); // Notify mesh change var change = 'Removed user ' + deluser.name + ' from mesh ' + mesh.name; diff --git a/mpsserver.js b/mpsserver.js index 831374b5..4c9e91a1 100644 --- a/mpsserver.js +++ b/mpsserver.js @@ -669,7 +669,6 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { var node = nodes[0]; // See if any changes need to be made - console.log(node.intelamt); if ((node.intelamt != undefined) && (node.intelamt.host == host) && (node.name != '') && (node.intelamt.state == 2)) return; // Get the mesh for this device diff --git a/package.json b/package.json index 59857717..74445d95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.1.8-m", + "version": "0.1.8-r", "keywords": [ "Remote Management", "Intel AMT", diff --git a/public/scripts/agent-desktop-0.0.2.js b/public/scripts/agent-desktop-0.0.2.js index 5f08890f..761fb1da 100644 --- a/public/scripts/agent-desktop-0.0.2.js +++ b/public/scripts/agent-desktop-0.0.2.js @@ -272,6 +272,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) { } obj.SendKeyMsgKC = function (action, kc) { + console.log('SendKeyMsgKC', action, kc); if (obj.State != 3) return; if (typeof action == 'object') { for (var i in action) { obj.SendKeyMsgKC(action[i][0], action[i][1]); } } else { obj.send(String.fromCharCode(0x00, obj.InputType.KEY, 0x00, 0x06, (action - 1), kc)); } diff --git a/public/scripts/common-0.0.1.js b/public/scripts/common-0.0.1.js index 6ffb0c62..c1e9674b 100644 --- a/public/scripts/common-0.0.1.js +++ b/public/scripts/common-0.0.1.js @@ -79,11 +79,7 @@ function hex2rstr(d) { function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); } // Convert a raw string to a hex string -function rstr2hex(input) { - var r = '', i; - for (i = 0; i < input.length; i++) { r += char2hex(input.charCodeAt(i)); } - return r; -} +function rstr2hex(input) { var r = '', i; for (i = 0; i < input.length; i++) { r += char2hex(input.charCodeAt(i)); } return r; } // UTF-8 encoding & decoding functions function encode_utf8(s) { return unescape(encodeURIComponent(s)); } diff --git a/public/scripts/meshcentral.js b/public/scripts/meshcentral.js index 317cdba4..1cf016fc 100644 --- a/public/scripts/meshcentral.js +++ b/public/scripts/meshcentral.js @@ -8,6 +8,7 @@ var MeshServerCreateControl = function (domain) { var obj = {}; obj.State = 0; obj.connectstate = 0; + obj.pingTimer = null; obj.xxStateChange = function (newstate) { if (obj.State == newstate) return; @@ -22,11 +23,14 @@ var MeshServerCreateControl = function (domain) { obj.socket.onmessage = obj.xxOnMessage; obj.socket.onclose = function () { obj.Stop(); } obj.xxStateChange(1); + if (obj.pingTimer != null) { clearInterval(obj.pingTimer); } + obj.pingTimer = setInterval(function () { obj.send({ action: 'ping' }); }, 29000); // Ping the server every 29 seconds, stops corporate proxies from disconnecting. } obj.Stop = function () { obj.connectstate = 0; if (obj.socket) { obj.socket.close(); delete obj.socket; } + if (obj.pingTimer != null) { clearInterval(obj.pingTimer); obj.pingTimer = null; } obj.xxStateChange(0); } @@ -34,6 +38,7 @@ var MeshServerCreateControl = function (domain) { // console.log('xxOnMessage', e.data); var message; try { message = JSON.parse(e.data); } catch (e) { return; } + if (message.action == 'pong') { return; } if (obj.onMessage) obj.onMessage(obj, message); }; diff --git a/views/default.handlebars b/views/default.handlebars index e25b84bc..4a168596 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -391,6 +391,7 @@