147 lines · 4.1 KB · C++
RawDownload
////  AssetRequest.cpp//  libraries/networking/src////  Created by Ryan Huffman on 2015/07/24//  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 "AssetRequest.h" #include <algorithm> #include <QtCore/QThread> #include <StatTracker.h>#include <Trace.h> #include "AssetClient.h"#include "NetworkLogging.h"#include "NodeList.h"#include "ResourceCache.h" static int requestID = 0; AssetRequest::AssetRequest(const QString& hash, const ByteRange& byteRange) :    _requestID(++requestID),    _hash(hash),    _byteRange(byteRange){    } AssetRequest::~AssetRequest() {    auto assetClient = DependencyManager::get<AssetClient>();    if (_assetRequestID) {        assetClient->cancelGetAssetRequest(_assetRequestID);    }} void AssetRequest::start() {    if (QThread::currentThread() != thread()) {        QMetaObject::invokeMethod(this, "start", Qt::AutoConnection);        return;    }     if (_state != NotStarted) {        qCWarning(asset_client) << "AssetRequest already started.";        return;    }     // in case we haven't parsed a valid hash, return an error now    if (!AssetUtils::isValidHash(_hash)) {        _error = InvalidHash;        _state = Finished;         emit finished(this);        return;    }        // Try to load from cache    _data = AssetUtils::loadFromCache(getUrl());    if (!_data.isNull()) {        _error = NoError;         _loadedFromCache = true;         _state = Finished;        emit finished(this);         return;    }     _state = WaitingForData;     auto assetClient = DependencyManager::get<AssetClient>();    auto that = QPointer<AssetRequest>(this); // Used to track the request's lifetime    auto hash = _hash;     _assetRequestID = assetClient->getAsset(_hash, _byteRange.fromInclusive, _byteRange.toExclusive,        [this, that, hash](bool responseReceived, AssetUtils::AssetServerError serverError, const QByteArray& data) {         if (!that) {            qCWarning(asset_client) << "Got reply for dead asset request " << hash << "- error code" << _error;            // If the request is dead, return            return;        }        _assetRequestID = INVALID_MESSAGE_ID;         if (!responseReceived) {            _error = NetworkError;        } else if (serverError != AssetUtils::AssetServerError::NoError) {            switch (serverError) {                case AssetUtils::AssetServerError::AssetNotFound:                    _error = NotFound;                    break;                case AssetUtils::AssetServerError::InvalidByteRange:                    _error = InvalidByteRange;                    break;                default:                    _error = UnknownError;                    break;            }        } else {            if (!_byteRange.isSet() && AssetUtils::hashData(data).toHex() != _hash) {                // the hash of the received data does not match what we expect, so we return an error                _error = HashVerificationFailed;            }             if (_error == NoError) {                _data = data;                _totalReceived += data.size();                emit progress(_totalReceived, data.size());                 if (!_byteRange.isSet()) {                    AssetUtils::saveToCache(getUrl(), data);                }            }        }                if (_error != NoError) {            qCWarning(asset_client) << "Got error retrieving asset" << _hash << "- error code" << _error;        }                _state = Finished;        emit finished(this);    }, [this, that](qint64 totalReceived, qint64 total) {        if (!that) {            // If the request is dead, return            return;        }        emit progress(totalReceived, total);    });}  const QString AssetRequest::getErrorString() const {    QString result;    if (_error != Error::NoError) {        QVariant v;        v.setValue(_error);         result = v.toString(); // courtesy of Q_ENUM    }    return result;}