Fixed file upload to agent when websocket compression is used.

Ylian Saint-Hilaire committed Jul 22, 2020 at 11:19 UTC c1d702149815a398e390b1656332857c5b40856c
3 files changed +21 -12
agents/meshcore.js
+13 -5
@@ -1219,8 +1219,8 @@ function createMeshCore(agent) {
1219 */
1220
1221 // If there is a upload or download active on this connection, close the file
1222 - if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
1223 - if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; }
1222 + if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); delete this.httprequest.uploadFile; }
1223 + if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); delete this.httprequest.downloadFile; }
1224
1225 // Clean up WebRTC
1226 if (this.webrtc != null) {
@@ -1244,8 +1244,16 @@ function createMeshCore(agent) {
1244 // If this is upload data, save it to file
1245 if (this.httprequest.uploadFile) {
1246 if (typeof data == 'object') {
1247 - try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
1248 - this.write(new Buffer(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data
1247 + // Save the data to file being uploaded.
1248 + if (this.httprequest.uploadFile) {
1249 + try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { sendConsoleText('FileSave ERROR'); this.write(new Buffer(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
1250 + this.write(new Buffer(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data.
1251 + }
1252 + } else if (typeof data == 'string') {
1253 + // Close the file and confirm. We need to make this added round trip since websocket deflate compression can cause the last message before a websocket close to not be received.
1254 + if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); delete this.httprequest.uploadFile; }
1255 + this.write(new Buffer(JSON.stringify({ action: 'uploaddone', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file.
1256 + this.end();
1257 }
1258 return;
1259 }
@@ -2044,7 +2052,7 @@ function createMeshCore(agent) {
2052 */
2053 case 'upload': {
2054 // Upload a file, browser to agent
2047 - if (this.httprequest.uploadFile != undefined) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; }
2055 + if (this.httprequest.uploadFile != null) { fs.closeSync(this.httprequest.uploadFile); delete this.httprequest.uploadFile; }
2056 if (cmd.path == undefined) break;
2057 var filepath = cmd.name ? obj.path.join(cmd.path, cmd.name) : cmd.path;
2058 MeshServerLog('Upload: \"' + filepath + '\"', this.httprequest);
meshuser.js
+1 -1
@@ -785,7 +785,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
785
786 switch (cmd) {
787 case 'help': {
788 - var fin = '', f = '', availcommands = 'help,info,versions,args,resetserver,showconfig,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,sms,amtacm,certhashes,watchdog';
788 + var fin = '', f = '', availcommands = 'help,info,versions,args,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,sms,amtacm,certhashes,watchdog';
789 if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; }
790 availcommands = availcommands.split(',').sort();
791 while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); }
views/default.handlebars
+7 -6
@@ -7961,7 +7961,6 @@
7961 function p13uploadReconnect() {
7962 uploadFile.ws = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotUploadData), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
7963 uploadFile.ws.attemptWebRTC = false;
7964 - uploadFile.ws.ctrlMsgAllowed = false;
7964 uploadFile.ws.onStateChanged = onFileUploadStateChange;
7965 uploadFile.ws.Start(filesNode._id);
7966 }
@@ -8016,6 +8015,9 @@
8015 for (var i = 0; i < 8; i++) { p13uploadNextPart(true); } // Send 8 more blocks of 4 k to full the websocket.
8016 } else if (cmd.action == 'uploadack') {
8017 p13uploadNextPart(false);
8018 + } else if (cmd.action == 'uploaddone') {
8019 + if (uploadFile.ws != null) { uploadFile.ws.Stop(); uploadFile.ws = null; }
8020 + if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadReconnect(); } else { p13uploadFileCancel(); }
8021 } else if (cmd.action == 'uploaderror') {
8022 p13uploadFileCancel();
8023 }
@@ -8025,12 +8027,11 @@
8027 function p13uploadNextPart(dataPriming) {
8028 var data = uploadFile.xdata;
8029 var start = uploadFile.xptr;
8028 - var end = uploadFile.xptr + 4096;
8029 - if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; }
8030 - if (start == data.byteLength) {
8031 - if (uploadFile.ws != null) { uploadFile.ws.Stop(); uploadFile.ws = null; }
8032 - if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadReconnect(); } else { p13uploadFileCancel(); }
8030 + if (start >= data.byteLength) {
8031 + uploadFile.ws.sendCtrlMsg('{"ctrlChannel":"102938","type":"close"}');
8032 } else {
8033 + var end = uploadFile.xptr + 16384;
8034 + if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; }
8035 var datapart = data.slice(start, end);
8036 uploadFile.ws.send(datapart);
8037 uploadFile.xptr = end;