From 2d2cc0eaca55a14af050e622d63168872d6f6431 Mon Sep 17 00:00:00 2001
From: Simon Walton <simon@highfidelity.io>
Date: Fri, 16 Nov 2018 15:56:39 -0800
Subject: [PATCH] Use a random session id for a sequence of chunks

---
 .../resources/web/content/js/content.js       | 13 +++++++----
 domain-server/src/DomainServer.cpp            | 22 ++++++++++---------
 domain-server/src/DomainServer.h              |  4 ++--
 3 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/domain-server/resources/web/content/js/content.js b/domain-server/resources/web/content/js/content.js
index 365c5e8403..afee2cc8a9 100644
--- a/domain-server/resources/web/content/js/content.js
+++ b/domain-server/resources/web/content/js/content.js
@@ -10,7 +10,7 @@ $(document).ready(function(){
   function progressBarHTML(extraClass, label) {
     var html = "<div class='progress'>";
     html += "<div class='" + extraClass + " progress-bar progress-bar-success progress-bar-striped active' role='progressbar' aria-valuemin='0' aria-valuemax='100'>";
-    html += label + "<span class='ongoing-msg'></span></div></div>";
+    html += "<span class='ongoing-msg'></span></div></div>";
     return html;
   }
 
@@ -24,10 +24,14 @@ $(document).ready(function(){
     });
   }
 
-  function uploadNextChunk(file, offset) {
+  function uploadNextChunk(file, offset, id) {
       if (offset == undefined) {
           offset = 0;
       }
+      if (id == undefined) {
+          // Identify this upload session
+          id = Math.round(Math.random() * 2147483647);
+      }
 
       var fileSize = file.size;
       var filename = file.name;
@@ -45,6 +49,7 @@ $(document).ready(function(){
         url: '/content/upload',
         type: 'POST',
         timeout: 30000, // 30 s
+        headers: {"X-Session-Id": id},
         cache: false,
         processData: false,
         contentType: false,
@@ -64,7 +69,7 @@ $(document).ready(function(){
 
       if (!isFinal) {
         ajaxObject.done(function (data, textStatus, jqXHR)
-          { uploadNextChunk(file, offset + CHUNK_SIZE); });
+          { uploadNextChunk(file, offset + CHUNK_SIZE, id); });
       } else {
         ajaxObject.done(function(data, textStatus, jqXHR) {
           isRestoring = true;
@@ -210,7 +215,7 @@ $(document).ready(function(){
 
   function updateProgressBars($progressBar, value) {
     $progressBar.attr('aria-valuenow', value).attr('style', 'width: ' + value + '%');
-    $progressBar.find('.ongoing-msg').html(" " + Math.round(value) + "% Complete");
+    $progressBar.find('.ongoing-msg').html(" " + Math.round(value) + "%");
   }
 
   function reloadBackupInformation() {
diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp
index 20ca5c94d4..2a5ada729c 100644
--- a/domain-server/src/DomainServer.cpp
+++ b/domain-server/src/DomainServer.cpp
@@ -2519,18 +2519,21 @@ bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &u
 }
 
 bool DomainServer::processPendingContent(HTTPConnection* connection, QString itemName, QString filename, QByteArray dataChunk) {
+    static const QString UPLOAD_SESSION_KEY { "X-Session-Id" };
+    QByteArray sessionIdBytes = connection->requestHeader(UPLOAD_SESSION_KEY);
+    int sessionId = sessionIdBytes.toInt();
+
     if (filename.endsWith(".zip", Qt::CaseInsensitive)) {
         static const QString TEMPORARY_CONTENT_FILEPATH { QDir::tempPath() + "/hifiUploadContent_XXXXXX.zip" };
-        const auto peerAddressHash = qHash(connection->socket()->peerAddress());
 
-        if (_pendingContentFiles.find(peerAddressHash) == _pendingContentFiles.end()) {
+        if (_pendingContentFiles.find(sessionId) == _pendingContentFiles.end()) {
             std::unique_ptr<QTemporaryFile> newTemp(new QTemporaryFile(TEMPORARY_CONTENT_FILEPATH));
-            _pendingContentFiles[peerAddressHash] = std::move(newTemp);
+            _pendingContentFiles[sessionId] = std::move(newTemp);
         }
 
-        QTemporaryFile& _pendingFileContent = *_pendingContentFiles[peerAddressHash];
+        QTemporaryFile& _pendingFileContent = *_pendingContentFiles[sessionId];
         if (!_pendingFileContent.open()) {
-            _pendingContentFiles.erase(peerAddressHash);
+            _pendingContentFiles.erase(sessionId);
             connection->respond(HTTPConnection::StatusCode400);
             return false;
         }
@@ -2543,16 +2546,15 @@ bool DomainServer::processPendingContent(HTTPConnection* connection, QString ite
         if (itemName == "restore-file-chunk-final" || itemName == "restore-file") {
             auto deferred = makePromise("recoverFromUploadedBackup");
 
-            deferred->then([this, peerAddressHash](QString error, QVariantMap result) {
-                _pendingContentFiles.erase(peerAddressHash);
+            deferred->then([this, sessionId](QString error, QVariantMap result) {
+                _pendingContentFiles.erase(sessionId);
             });
 
             _contentManager->recoverFromUploadedFile(deferred, _pendingFileContent.fileName());
         }
     } else if (filename.endsWith(".json", Qt::CaseInsensitive)
         || filename.endsWith(".json.gz", Qt::CaseInsensitive)) {
-        auto peerAddressHash = qHash(connection->socket()->peerAddress());
-        QByteArray& _pendingUploadedContent = _pendingUploadedContents[peerAddressHash];
+        QByteArray& _pendingUploadedContent = _pendingUploadedContents[sessionId];
         _pendingUploadedContent += dataChunk;
         connection->respond(HTTPConnection::StatusCode200);
 
@@ -2560,7 +2562,7 @@ bool DomainServer::processPendingContent(HTTPConnection* connection, QString ite
             // invoke our method to hand the new octree file off to the octree server
             QMetaObject::invokeMethod(this, "handleOctreeFileReplacement",
                 Qt::QueuedConnection, Q_ARG(QByteArray, _pendingUploadedContent));
-            _pendingUploadedContents.erase(peerAddressHash);
+            _pendingUploadedContents.erase(sessionId);
         }
     } else {
         connection->respond(HTTPConnection::StatusCode400);
diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h
index 5d6cd4e5f9..f0c20241a2 100644
--- a/domain-server/src/DomainServer.h
+++ b/domain-server/src/DomainServer.h
@@ -284,8 +284,8 @@ private:
 
     QHash<QUuid, QPointer<HTTPSConnection>> _pendingOAuthConnections;
 
-    std::unordered_map<uint, QByteArray> _pendingUploadedContents;
-    std::unordered_map<uint, std::unique_ptr<QTemporaryFile>> _pendingContentFiles;
+    std::unordered_map<int, QByteArray> _pendingUploadedContents;
+    std::unordered_map<int, std::unique_ptr<QTemporaryFile>> _pendingContentFiles;
 
     QThread _assetClientThread;
 };