//// 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;}
//
// 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;
}