Improved device batch upload.
This commit is contained in:
parent
d833ac2472
commit
8c007666b9
|
@ -44,6 +44,7 @@ var MESHRIGHT_NODESKTOP = 65536;
|
|||
function createMeshCore(agent) {
|
||||
var obj = {};
|
||||
var agentFileHttpRequests = {}; // Currently active agent HTTPS GET requests from the server.
|
||||
var agentFileHttpPendingRequests = []; // Pending HTTPS GET requests from the server.
|
||||
|
||||
if (process.platform == 'win32' && require('user-sessions').isRoot()) {
|
||||
// Check the Agent Uninstall MetaData for correctness, as the installer may have written an incorrect value
|
||||
|
@ -1148,38 +1149,8 @@ function createMeshCore(agent) {
|
|||
if (data.pipe == true) { delete data.pipe; delete data.action; data.cmd = 'meshToolInfo'; broadcastToRegisteredApps(data); }
|
||||
break;
|
||||
case 'wget': // Server uses this command to tell the agent to download a file using HTTPS/GET and place it in a given path. This is used for one-to-many file uploads.
|
||||
sendConsoleText(JSON.stringify(data));
|
||||
if ((data.overwrite !== true) && fs.existsSync(data.path)) break; // Don't overwrite an existing file.
|
||||
if (data.createFolder) { try { fs.mkdirSync(data.folder); } catch (ex) { } } // If requested, create the local folder.
|
||||
data.url = 'http' + getServerTargetUrlEx('*/').substring(2);
|
||||
var agentFileHttpOptions = http.parseUri(data.url);
|
||||
agentFileHttpOptions.path = data.urlpath;
|
||||
|
||||
// Perform manual server TLS certificate checking based on the certificate hash given by the server.
|
||||
agentFileHttpOptions.rejectUnauthorized = 0;
|
||||
agentFileHttpOptions.checkServerIdentity = function checkServerIdentity(certs) { if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash != certs[0].fingerprint.split(':').join('').toLowerCase())) { throw new Error('BadCert') } }
|
||||
agentFileHttpOptions.checkServerIdentity.servertlshash = data.servertlshash;
|
||||
|
||||
if (agentFileHttpOptions == null) break;
|
||||
var agentFileHttpRequest = http.request(agentFileHttpOptions,
|
||||
function (response) {
|
||||
response.xparent = this;
|
||||
try {
|
||||
response.xfile = fs.createWriteStream(this.xpath, { flags: 'wbN' })
|
||||
response.pipe(response.xfile);
|
||||
response.end = function () { delete agentFileHttpRequests[this.xparent.xurlpath]; delete this.xparent; }
|
||||
} catch (ex) {
|
||||
delete agentFileHttpRequests[this.xurlpath];
|
||||
delete response.xparent;
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
agentFileHttpRequest.on('error', function (ex) { delete agentFileHttpRequests[this.xurlpath]; });
|
||||
agentFileHttpRequest.end();
|
||||
agentFileHttpRequest.xurlpath = data.urlpath;
|
||||
agentFileHttpRequest.xpath = data.path;
|
||||
agentFileHttpRequests[data.urlpath] = agentFileHttpRequest;
|
||||
agentFileHttpPendingRequests.push(data);
|
||||
serverFetchFile();
|
||||
break;
|
||||
default:
|
||||
// Unknown action, ignore it.
|
||||
|
@ -1188,6 +1159,39 @@ function createMeshCore(agent) {
|
|||
}
|
||||
}
|
||||
|
||||
// Agent just get a file from the server and save it locally.
|
||||
function serverFetchFile() {
|
||||
if ((Object.keys(agentFileHttpRequests).length > 4) || (agentFileHttpPendingRequests.length == 0)) return; // No more than 4 active HTTPS requests to the server.
|
||||
var data = agentFileHttpPendingRequests.shift();
|
||||
if ((data.overwrite !== true) && fs.existsSync(data.path)) return; // Don't overwrite an existing file.
|
||||
if (data.createFolder) { try { fs.mkdirSync(data.folder); } catch (ex) { } } // If requested, create the local folder.
|
||||
data.url = 'http' + getServerTargetUrlEx('*/').substring(2);
|
||||
var agentFileHttpOptions = http.parseUri(data.url);
|
||||
agentFileHttpOptions.path = data.urlpath;
|
||||
|
||||
// Perform manual server TLS certificate checking based on the certificate hash given by the server.
|
||||
agentFileHttpOptions.rejectUnauthorized = 0;
|
||||
agentFileHttpOptions.checkServerIdentity = function checkServerIdentity(certs) { if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash != certs[0].fingerprint.split(':').join('').toLowerCase())) { throw new Error('BadCert') } }
|
||||
agentFileHttpOptions.checkServerIdentity.servertlshash = data.servertlshash;
|
||||
|
||||
if (agentFileHttpOptions == null) return;
|
||||
var agentFileHttpRequest = http.request(agentFileHttpOptions,
|
||||
function (response) {
|
||||
response.xparent = this;
|
||||
try {
|
||||
response.xfile = fs.createWriteStream(this.xpath, { flags: 'wbN' })
|
||||
response.pipe(response.xfile);
|
||||
response.end = function () { delete agentFileHttpRequests[this.xparent.xurlpath]; delete this.xparent; serverFetchFile(); }
|
||||
} catch (ex) { delete agentFileHttpRequests[this.xurlpath]; delete response.xparent; serverFetchFile(); return; }
|
||||
}
|
||||
);
|
||||
agentFileHttpRequest.on('error', function (ex) { delete agentFileHttpRequests[this.xurlpath]; serverFetchFile(); });
|
||||
agentFileHttpRequest.end();
|
||||
agentFileHttpRequest.xurlpath = data.urlpath;
|
||||
agentFileHttpRequest.xpath = data.path;
|
||||
agentFileHttpRequests[data.urlpath] = agentFileHttpRequest;
|
||||
}
|
||||
|
||||
// Called when a file changed in the file system
|
||||
/*
|
||||
function onFileWatcher(a, b) {
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -10935,7 +10935,8 @@
|
|||
99: "Running commands as user",
|
||||
100: "Running commands as user if possible",
|
||||
101: "Added device share {0} from {1} to {2}",
|
||||
102: "Removed device share {0}"
|
||||
102: "Removed device share {0}",
|
||||
103: "Batch upload of {0} file(s) to folder {1}",
|
||||
};
|
||||
|
||||
// Highlights the device being hovered
|
||||
|
|
46
webserver.js
46
webserver.js
|
@ -3211,9 +3211,31 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
obj.fs.rename(file.path, fpath, function (err) {
|
||||
if (err && (err.code === 'EXDEV')) {
|
||||
// On some Linux, the rename will fail with a "EXDEV" error, do a copy+unlink instead.
|
||||
obj.common.copyFile(file.path, fpath, function (err) { obj.fs.unlink(file.path, function (err) { handleUploadFileBatchEx(cmd); }); });
|
||||
} else {
|
||||
handleUploadFileBatchEx(cmd);
|
||||
obj.common.copyFile(file.path, fpath, function (err) { obj.fs.unlink(file.path, function (err) { }); });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Instruct one of more agents to download a URL to a given local drive location.
|
||||
var tlsCertHash = obj.webCertificateHashs[cmd.domain.id];
|
||||
if (tlsCertHash != null) { tlsCertHash = Buffer.from(tlsCertHash, 'binary').toString('hex'); }
|
||||
for (var i in cmd.nodeids) {
|
||||
obj.GetNodeWithRights(cmd.domain, cmd.user, cmd.nodeids[i], function (node, rights, visible) {
|
||||
if ((node == null) || ((rights & 8) == 0) || (visible == false)) return; // We don't have remote control rights to this device
|
||||
var agentPath = ((node.agent.id > 0) && (node.agent.id < 5)) ? cmd.windowsPath : cmd.linuxPath;
|
||||
|
||||
// Event that this operation is being performed.
|
||||
var targets = obj.CreateNodeDispatchTargets(node.meshid, node._id, ['server-users', cmd.user._id]);
|
||||
var msgid = 103; // "Batch upload of {0} file(s) to folder {1}"
|
||||
var event = { etype: 'node', userid: cmd.user._id, username: cmd.user.name, nodeid: node._id, action: 'batchupload', msg: 'Performing batch upload of ' + cmd.files.length + ' file(s) to ' + agentPath, msgid: msgid, msgArgs: [cmd.files.length, agentPath], domain: cmd.domain.id };
|
||||
parent.DispatchEvent(targets, obj, event);
|
||||
|
||||
// Send the agent commands to perform the batch upload operation
|
||||
for (var f in cmd.files) {
|
||||
const acmd = { action: 'wget', overwrite: cmd.overwrite, createFolder: cmd.createFolder, urlpath: '/agentdownload.ashx?c=' + obj.parent.encodeCookie({ a: 'tmpdl', d: cmd.domain.id, nid: node._id, f: cmd.files[f].target }, obj.parent.loginCookieEncryptionKey), path: obj.path.join(agentPath, cmd.files[f].name), folder: agentPath, servertlshash: tlsCertHash };
|
||||
var agent = obj.wsagents[node._id];
|
||||
if (agent != null) { try { agent.send(JSON.stringify(acmd)); } catch (ex) { } }
|
||||
// TODO: Add support for peer servers.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -3222,24 +3244,6 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
});
|
||||
}
|
||||
|
||||
// Instruct one of more agents to download a URL to a given local drive location.
|
||||
function handleUploadFileBatchEx(cmd) {
|
||||
var tlsCertHash = obj.webCertificateHashs[cmd.domain.id];
|
||||
if (tlsCertHash != null) { tlsCertHash = Buffer.from(tlsCertHash, 'binary').toString('hex'); }
|
||||
for (var i in cmd.nodeids) {
|
||||
obj.GetNodeWithRights(cmd.domain, cmd.user, cmd.nodeids[i], function (node, rights, visible) {
|
||||
if ((node == null) || ((rights & 8) == 0) || (visible == false)) return; // We don't have remote control rights to this device
|
||||
var agentPath = ((node.agent.id > 0) && (node.agent.id < 5)) ? cmd.windowsPath : cmd.linuxPath;
|
||||
for (var f in cmd.files) {
|
||||
const acmd = { action: 'wget', overwrite: cmd.overwrite, createFolder: cmd.createFolder, urlpath: '/agentdownload.ashx?c=' + obj.parent.encodeCookie({ a: 'tmpdl', d: cmd.domain.id, nid: node._id, f: cmd.files[f].target }, obj.parent.loginCookieEncryptionKey), path: obj.path.join(agentPath, cmd.files[f].name), folder: agentPath, servertlshash: tlsCertHash };
|
||||
var agent = obj.wsagents[node._id];
|
||||
if (agent != null) { try { agent.send(JSON.stringify(acmd)); } catch (ex) { } }
|
||||
// TODO: Add support for peer servers.
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Subscribe to all events we are allowed to receive
|
||||
obj.subscribe = function (userid, target) {
|
||||
const user = obj.users[userid];
|
||||
|
|
Loading…
Reference in New Issue