Add ViewerAsset over HTTP support
Has fallbacks for grids without HTTP, of course. Though some assets might be dropped initially, as it is untested, but better than nothing.
This commit is contained in:
@@ -33,9 +33,12 @@
|
||||
#include "message.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llviewerregion.h"
|
||||
|
||||
#include "lltransfersourceasset.h"
|
||||
#include "lltransfertargetvfile.h"
|
||||
#include "llviewerassetstats.h"
|
||||
#include "llworld.h"
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// LLViewerAssetRequest
|
||||
@@ -138,7 +141,6 @@ void LLViewerAssetStorage::storeAssetData(
|
||||
LLVFile vfile(mVFS, asset_id, asset_type, LLVFile::READ);
|
||||
S32 asset_size = vfile.getSize();
|
||||
|
||||
|
||||
LLAssetRequest *req = new LLAssetRequest(asset_id, asset_type);
|
||||
req->mUpCallback = callback;
|
||||
req->mUserData = user_data;
|
||||
@@ -324,6 +326,7 @@ void LLViewerAssetStorage::storeAssetData(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Allocate and queue an asset fetch request for the viewer
|
||||
*
|
||||
@@ -360,9 +363,13 @@ void LLViewerAssetStorage::queueRequestUDP(
|
||||
BOOL duplicate,
|
||||
BOOL is_priority)
|
||||
{
|
||||
LL_DEBUGS("ViewerAsset") << "Request asset via HTTP " << uuid << " type " << LLAssetType::lookup(atype) << LL_ENDL;
|
||||
|
||||
if (mUpstreamHost.isOk())
|
||||
{
|
||||
bool with_http = false;
|
||||
const auto region = gAgent.getRegion();
|
||||
// Fallback on UDP if we have no cap or haven't received caps. This means missing some UDP-only region assets before caps received, but that's better for HTTP only.
|
||||
bool with_http = !region || !region->capabilitiesReceived() || region->getViewerAssetUrl().empty();
|
||||
LLViewerAssetRequest *req = new LLViewerAssetRequest(uuid, atype, with_http);
|
||||
req->mDownCallback = callback;
|
||||
req->mUserData = user_data;
|
||||
@@ -373,28 +380,33 @@ void LLViewerAssetStorage::queueRequestUDP(
|
||||
// are piggy-backing and will artificially lower averages.
|
||||
req->mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
|
||||
}
|
||||
|
||||
mPendingDownloads.push_back(req);
|
||||
|
||||
// This is the same as the current UDP logic - don't re-request a duplicate.
|
||||
if (!duplicate)
|
||||
{
|
||||
// send request message to our upstream data provider
|
||||
// Create a new asset transfer.
|
||||
LLTransferSourceParamsAsset spa;
|
||||
spa.setAsset(uuid, atype);
|
||||
|
||||
// Set our destination file, and the completion callback.
|
||||
LLTransferTargetParamsVFile tpvf;
|
||||
tpvf.setAsset(uuid, atype);
|
||||
tpvf.setCallback(downloadCompleteCallback, *req);
|
||||
|
||||
LL_DEBUGS("AssetStorage") << "Starting transfer for " << uuid << LL_ENDL;
|
||||
LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET);
|
||||
ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f));
|
||||
|
||||
bool with_http = false;
|
||||
bool is_temp = false;
|
||||
LLViewerAssetStatsFF::record_enqueue_main(atype, with_http, is_temp);
|
||||
if (!with_http) // maintain this code for older grids
|
||||
{
|
||||
// send request message to our upstream data provider
|
||||
// Create a new asset transfer.
|
||||
LLTransferSourceParamsAsset spa;
|
||||
spa.setAsset(uuid, atype);
|
||||
|
||||
// Set our destination file, and the completion callback.
|
||||
LLTransferTargetParamsVFile tpvf;
|
||||
tpvf.setAsset(uuid, atype);
|
||||
tpvf.setCallback(downloadCompleteCallback, *req);
|
||||
|
||||
LL_DEBUGS("AssetStorage") << "Starting transfer for " << uuid << LL_ENDL;
|
||||
LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET);
|
||||
ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f));
|
||||
}
|
||||
else
|
||||
{
|
||||
LLViewerAssetStorage::assetRequestCoro(req, uuid, atype, callback, user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -408,3 +420,138 @@ void LLViewerAssetStorage::queueRequestUDP(
|
||||
}
|
||||
}
|
||||
|
||||
extern AIHTTPTimeoutPolicy HTTPGetResponder_timeout;
|
||||
class LLViewerAssetResponder : public LLHTTPClient::ResponderWithCompleted
|
||||
{
|
||||
public:
|
||||
LLViewerAssetResponder(const LLUUID& id, LLAssetType::EType type) : LLHTTPClient::ResponderWithCompleted()
|
||||
, uuid(id), atype(type)
|
||||
{}
|
||||
private:
|
||||
LLUUID uuid;
|
||||
LLAssetType::EType atype;
|
||||
|
||||
void completedRaw(LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) override
|
||||
{
|
||||
if (LLApp::isQuitting())
|
||||
{
|
||||
// Bail out if result arrives after shutdown has been started.
|
||||
return;
|
||||
}
|
||||
|
||||
LL_DEBUGS("ViewerAsset") << "request succeeded, url " << mURL << LL_ENDL;
|
||||
|
||||
S32 result_code = LL_ERR_NOERR;
|
||||
LLExtStat ext_status = LL_EXSTAT_NONE;
|
||||
|
||||
if (!isGoodStatus(mStatus))
|
||||
{
|
||||
LL_DEBUGS("ViewerAsset") << "request failed, status " << mStatus << LL_ENDL;
|
||||
result_code = LL_ERR_ASSET_REQUEST_FAILED;
|
||||
ext_status = LL_EXSTAT_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string raw;
|
||||
decode_raw_body(channels, buffer, raw);
|
||||
|
||||
S32 size = raw.size();
|
||||
if (size > 0)
|
||||
{
|
||||
// This create-then-rename flow is modeled on
|
||||
// LLTransferTargetVFile, which is what was used in the UDP
|
||||
// case.
|
||||
LLUUID temp_id;
|
||||
temp_id.generate();
|
||||
LLVFile vf(gAssetStorage->mVFS, temp_id, atype, LLVFile::WRITE);
|
||||
vf.setMaxSize(size);
|
||||
if (!vf.write((const U8*)raw.data(), size))
|
||||
{
|
||||
// TODO asset-http: handle error
|
||||
LL_WARNS("ViewerAsset") << "Failure in vf.write()" << LL_ENDL;
|
||||
result_code = LL_ERR_ASSET_REQUEST_FAILED;
|
||||
ext_status = LL_EXSTAT_VFS_CORRUPT;
|
||||
}
|
||||
else if (!vf.rename(uuid, atype))
|
||||
{
|
||||
LL_WARNS("ViewerAsset") << "rename failed" << LL_ENDL;
|
||||
result_code = LL_ERR_ASSET_REQUEST_FAILED;
|
||||
ext_status = LL_EXSTAT_VFS_CORRUPT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO asset-http: handle invalid size case
|
||||
LL_WARNS("ViewerAsset") << "bad size" << LL_ENDL;
|
||||
result_code = LL_ERR_ASSET_REQUEST_FAILED;
|
||||
ext_status = LL_EXSTAT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up pending downloads and trigger callbacks
|
||||
gAssetStorage->removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status);
|
||||
}
|
||||
AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy() const override { return HTTPGetResponder_timeout; }
|
||||
char const* getName() const override { return "assetRequestCoro"; }
|
||||
};
|
||||
|
||||
void LLViewerAssetStorage::capsRecvForRegion(const LLUUID& uuid, LLAssetType::EType atype, const LLUUID& region_id)
|
||||
{
|
||||
LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(region_id);
|
||||
if (!regionp)
|
||||
{
|
||||
LL_WARNS("ViewerAsset") << "region not found for region_id " << region_id << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mViewerAssetUrl = regionp->getViewerAssetUrl();
|
||||
}
|
||||
|
||||
LL_WARNS_ONCE("ViewerAsset") << "capsRecv got event" << LL_ENDL;
|
||||
LL_WARNS_ONCE("ViewerAsset") << "region " << gAgent.getRegion() << " mViewerAssetUrl " << mViewerAssetUrl << LL_ENDL;
|
||||
if (mViewerAssetUrl.empty())
|
||||
{
|
||||
LL_WARNS_ONCE("ViewerAsset") << "asset request fails: caps received but no viewer asset cap found" << LL_ENDL;
|
||||
auto result_code = LL_ERR_ASSET_REQUEST_FAILED;
|
||||
auto ext_status = LL_EXSTAT_NONE;
|
||||
removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status);
|
||||
return;
|
||||
}
|
||||
std::string url = getAssetURL(mViewerAssetUrl, uuid,atype);
|
||||
LL_DEBUGS("ViewerAsset") << "request url: " << url << LL_ENDL;
|
||||
|
||||
LLHTTPClient::get(url, new LLViewerAssetResponder(uuid, atype));
|
||||
}
|
||||
|
||||
void LLViewerAssetStorage::assetRequestCoro(
|
||||
LLViewerAssetRequest *req,
|
||||
const LLUUID uuid,
|
||||
LLAssetType::EType atype,
|
||||
LLGetAssetCallback callback,
|
||||
void *user_data)
|
||||
{
|
||||
if (!gAgent.getRegion())
|
||||
{
|
||||
LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL;
|
||||
auto result_code = LL_ERR_ASSET_REQUEST_FAILED;
|
||||
auto ext_status = LL_EXSTAT_NONE;
|
||||
removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status);
|
||||
return;
|
||||
}
|
||||
else if (!gAgent.getRegion()->capabilitiesReceived())
|
||||
{
|
||||
LL_WARNS_ONCE("ViewerAsset") << "Waiting for capabilities" << LL_ENDL;
|
||||
|
||||
gAgent.getRegion()->setCapabilitiesReceivedCallback(
|
||||
boost::bind(&LLViewerAssetStorage::capsRecvForRegion, this, uuid, atype, _1));
|
||||
}
|
||||
else capsRecvForRegion(uuid, atype, gAgent.getRegion()->getRegionID());
|
||||
}
|
||||
|
||||
std::string LLViewerAssetStorage::getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype)
|
||||
{
|
||||
std::string type_name = LLAssetType::lookup(atype);
|
||||
std::string url = cap_url + "/?" + type_name + "_id=" + uuid.asString();
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
class LLVFile;
|
||||
|
||||
class LLViewerAssetRequest;
|
||||
|
||||
class LLViewerAssetStorage : public LLAssetStorage
|
||||
{
|
||||
public:
|
||||
@@ -73,7 +75,6 @@ protected:
|
||||
BOOL duplicate,
|
||||
BOOL is_priority);
|
||||
|
||||
|
||||
void queueRequestUDP(const LLUUID& uuid,
|
||||
LLAssetType::EType type,
|
||||
void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
|
||||
@@ -81,6 +82,17 @@ protected:
|
||||
BOOL duplicate,
|
||||
BOOL is_priority);
|
||||
|
||||
void capsRecvForRegion(const LLUUID& uuid, LLAssetType::EType atype, const LLUUID& region_id);
|
||||
|
||||
void assetRequestCoro(LLViewerAssetRequest *req,
|
||||
const LLUUID uuid,
|
||||
LLAssetType::EType atype,
|
||||
void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
|
||||
void *user_data);
|
||||
|
||||
std::string getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype);
|
||||
|
||||
std::string mViewerAssetUrl;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user