// // UploadAssetTask.cpp // assignment-client/src/assets // // Created by Stephen Birarda on 2015-08-28. // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "UploadAssetTask.h" #include #include #include #include #include #include "ClientServerUtils.h" UploadAssetTask::UploadAssetTask(QSharedPointer receivedMessage, SharedNodePointer senderNode, const QDir& resourcesDir, uint64_t filesizeLimit) : _receivedMessage(receivedMessage), _senderNode(senderNode), _resourcesDir(resourcesDir), _filesizeLimit(filesizeLimit) { } void UploadAssetTask::run() { auto data = _receivedMessage->getMessage(); QBuffer buffer { &data }; buffer.open(QIODevice::ReadOnly); MessageID messageID; buffer.read(reinterpret_cast(&messageID), sizeof(messageID)); uint64_t fileSize; buffer.read(reinterpret_cast(&fileSize), sizeof(fileSize)); if (_senderNode) { qDebug() << "UploadAssetTask reading a file of " << fileSize << "bytes from" << uuidStringWithoutCurlyBraces(_senderNode->getUUID()); } else { qDebug() << "UploadAssetTask reading a file of " << fileSize << "bytes from" << _receivedMessage->getSenderSockAddr(); } auto replyPacket = NLPacket::create(PacketType::AssetUploadReply, -1, true); replyPacket->writePrimitive(messageID); if (fileSize > _filesizeLimit) { replyPacket->writePrimitive(AssetUtils::AssetServerError::AssetTooLarge); } else { QByteArray fileData = buffer.read(fileSize); auto hash = AssetUtils::hashData(fileData); auto hexHash = hash.toHex(); if (_senderNode) { qDebug() << "Hash for uploaded file from" << uuidStringWithoutCurlyBraces(_senderNode->getUUID()) << "is: (" << hexHash << ")"; } else { qDebug() << "Hash for uploaded file from" << _receivedMessage->getSenderSockAddr() << "is: (" << hexHash << ")"; } QFile file { _resourcesDir.filePath(QString(hexHash)) }; bool existingCorrectFile = false; if (file.exists()) { // check if the local file has the correct contents, otherwise we overwrite if (file.open(QIODevice::ReadOnly) && AssetUtils::hashData(file.readAll()) == hash) { qDebug() << "Not overwriting existing verified file: " << hexHash; existingCorrectFile = true; replyPacket->writePrimitive(AssetUtils::AssetServerError::NoError); replyPacket->write(hash); } else { qDebug() << "Overwriting an existing file whose contents did not match the expected hash: " << hexHash; file.close(); } } if (!existingCorrectFile) { if (file.open(QIODevice::WriteOnly) && file.write(fileData) == qint64(fileSize)) { qDebug() << "Wrote file" << hexHash << "to disk. Upload complete"; file.close(); replyPacket->writePrimitive(AssetUtils::AssetServerError::NoError); replyPacket->write(hash); } else { qWarning() << "Failed to upload or write to file" << hexHash << " - upload failed."; // upload has failed - remove the file and return an error auto removed = file.remove(); if (!removed) { qWarning() << "Removal of failed upload file" << hexHash << "failed."; } replyPacket->writePrimitive(AssetUtils::AssetServerError::FileOperationFailed); } } } auto nodeList = DependencyManager::get(); if (_senderNode) { nodeList->sendPacket(std::move(replyPacket), *_senderNode); } else { nodeList->sendPacket(std::move(replyPacket), _receivedMessage->getSenderSockAddr()); } }