diff --git a/agents/meshcore.js b/agents/meshcore.js index 80e67bdf..dfd0f825 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -1219,8 +1219,8 @@ function createMeshCore(agent) { */ // If there is a upload or download active on this connection, close the file - if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; } - if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; } + if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); delete this.httprequest.uploadFile; } + if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); delete this.httprequest.downloadFile; } // Clean up WebRTC if (this.webrtc != null) { @@ -1244,8 +1244,16 @@ function createMeshCore(agent) { // If this is upload data, save it to file if (this.httprequest.uploadFile) { if (typeof data == 'object') { - 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. - this.write(new Buffer(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data + // Save the data to file being uploaded. + if (this.httprequest.uploadFile) { + 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. + this.write(new Buffer(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data. + } + } else if (typeof data == 'string') { + // 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. + if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); delete this.httprequest.uploadFile; } + this.write(new Buffer(JSON.stringify({ action: 'uploaddone', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file. + this.end(); } return; } @@ -2044,7 +2052,7 @@ function createMeshCore(agent) { */ case 'upload': { // Upload a file, browser to agent - if (this.httprequest.uploadFile != undefined) { fs.closeSync(this.httprequest.uploadFile); this.httprequest.uploadFile = undefined; } + if (this.httprequest.uploadFile != null) { fs.closeSync(this.httprequest.uploadFile); delete this.httprequest.uploadFile; } if (cmd.path == undefined) break; var filepath = cmd.name ? obj.path.join(cmd.path, cmd.name) : cmd.path; MeshServerLog('Upload: \"' + filepath + '\"', this.httprequest); diff --git a/meshuser.js b/meshuser.js index 8e471fad..29fa10de 100644 --- a/meshuser.js +++ b/meshuser.js @@ -785,7 +785,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use switch (cmd) { case 'help': { - 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'; + 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'; if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; } availcommands = availcommands.split(',').sort(); while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); } diff --git a/views/default.handlebars b/views/default.handlebars index d06b118e..1dc40a1d 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -7961,7 +7961,6 @@ function p13uploadReconnect() { uploadFile.ws = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotUploadData), serverPublicNamePort, authCookie, authRelayCookie, domainUrl); uploadFile.ws.attemptWebRTC = false; - uploadFile.ws.ctrlMsgAllowed = false; uploadFile.ws.onStateChanged = onFileUploadStateChange; uploadFile.ws.Start(filesNode._id); } @@ -8016,6 +8015,9 @@ for (var i = 0; i < 8; i++) { p13uploadNextPart(true); } // Send 8 more blocks of 4 k to full the websocket. } else if (cmd.action == 'uploadack') { p13uploadNextPart(false); + } else if (cmd.action == 'uploaddone') { + if (uploadFile.ws != null) { uploadFile.ws.Stop(); uploadFile.ws = null; } + if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadReconnect(); } else { p13uploadFileCancel(); } } else if (cmd.action == 'uploaderror') { p13uploadFileCancel(); } @@ -8025,12 +8027,11 @@ function p13uploadNextPart(dataPriming) { var data = uploadFile.xdata; var start = uploadFile.xptr; - var end = uploadFile.xptr + 4096; - if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; } - if (start == data.byteLength) { - if (uploadFile.ws != null) { uploadFile.ws.Stop(); uploadFile.ws = null; } - if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadReconnect(); } else { p13uploadFileCancel(); } + if (start >= data.byteLength) { + uploadFile.ws.sendCtrlMsg('{"ctrlChannel":"102938","type":"close"}'); } else { + var end = uploadFile.xptr + 16384; + if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; } var datapart = data.slice(start, end); uploadFile.ws.send(datapart); uploadFile.xptr = end;