/** * @file lltransfersourceasset.cpp * @brief Transfer system for sending an asset. * * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "linden_common.h" #include "lltransfersourceasset.h" #include "llerror.h" #include "message.h" #include "lldatapacker.h" #include "lldir.h" #include "llfilesystem.h" LLTransferSourceAsset::LLTransferSourceAsset(const LLUUID &request_id, const F32 priority) : LLTransferSource(LLTST_ASSET, request_id, priority), mGotResponse(false), mCurPos(0) { } LLTransferSourceAsset::~LLTransferSourceAsset() { } void LLTransferSourceAsset::initTransfer() { if (gAssetStorage) { // *HACK: asset transfers will only be coming from the viewer // to the simulator. This is subset of assets we allow to be // simply pulled straight from the asset system. LLUUID* tidp; if(LLAssetType::lookupIsAssetFetchByIDAllowed(mParams.getAssetType())) { tidp = new LLUUID(getID()); gAssetStorage->getAssetData( mParams.getAssetID(), mParams.getAssetType(), LLTransferSourceAsset::responderCallback, tidp, false); } else { LL_WARNS() << "Attempted to request blocked asset " << mParams.getAssetID() << ":" << LLAssetType::lookupHumanReadable(mParams.getAssetType()) << LL_ENDL; sendTransferStatus(LLTS_ERROR); } } else { LL_WARNS() << "Attempted to request asset " << mParams.getAssetID() << ":" << LLAssetType::lookupHumanReadable(mParams.getAssetType()) << " without an asset system!" << LL_ENDL; sendTransferStatus(LLTS_ERROR); } } F32 LLTransferSourceAsset::updatePriority() { return 0.f; } LLTSCode LLTransferSourceAsset::dataCallback(const S32 packet_id, const S32 max_bytes, U8 **data_handle, S32 &returned_bytes, bool &delete_returned) { //LL_INFOS() << "LLTransferSourceAsset::dataCallback" << LL_ENDL; if (!mGotResponse) { return LLTS_SKIP; } LLFileSystem vf(mParams.getAssetID(), mParams.getAssetType(), LLFileSystem::READ); if (!vf.getSize()) { // Something bad happened with the asset request! return LLTS_ERROR; } if (packet_id != mLastPacketID + 1) { LL_ERRS() << "Can't handle out of order file transfer yet!" << LL_ENDL; } // grab a buffer from the right place in the file if (!vf.seek(mCurPos, 0)) { LL_WARNS() << "LLTransferSourceAsset Can't seek to " << mCurPos << " length " << vf.getSize() << LL_ENDL; LL_WARNS() << "While sending " << mParams.getAssetID() << LL_ENDL; return LLTS_ERROR; } delete_returned = true; U8 *tmpp = new U8[max_bytes]; *data_handle = tmpp; if (!vf.read(tmpp, max_bytes)) /* Flawfinder: Ignore */ { // Read failure, need to deal with it. delete[] tmpp; *data_handle = NULL; returned_bytes = 0; delete_returned = false; return LLTS_ERROR; } returned_bytes = vf.getLastBytesRead(); mCurPos += returned_bytes; if (vf.eof()) { if (!returned_bytes) { delete[] tmpp; *data_handle = NULL; returned_bytes = 0; delete_returned = false; } return LLTS_DONE; } return LLTS_OK; } void LLTransferSourceAsset::completionCallback(const LLTSCode status) { // No matter what happens, all we want to do is close the vfile if // we've got it open. } void LLTransferSourceAsset::packParams(LLDataPacker& dp) const { //LL_INFOS() << "LLTransferSourceAsset::packParams" << LL_ENDL; mParams.packParams(dp); } bool LLTransferSourceAsset::unpackParams(LLDataPacker &dp) { //LL_INFOS() << "LLTransferSourceAsset::unpackParams" << LL_ENDL; return mParams.unpackParams(dp); } void LLTransferSourceAsset::responderCallback(const LLUUID& uuid, LLAssetType::EType type, void *user_data, S32 result, LLExtStat ext_status ) { LLUUID *tidp = ((LLUUID*) user_data); LLUUID transfer_id = *(tidp); delete tidp; tidp = NULL; LLTransferSourceAsset *tsap = (LLTransferSourceAsset *) gTransferManager.findTransferSource(transfer_id); if (!tsap) { LL_INFOS() << "Aborting transfer " << transfer_id << " callback, transfer source went away" << LL_ENDL; return; } if (result) { LL_INFOS() << "AssetStorage: Error " << gAssetStorage->getErrorString(result) << " downloading uuid " << uuid << LL_ENDL; } LLTSCode status; tsap->mGotResponse = true; if (LL_ERR_NOERR == result) { // Everything's OK. LLFileSystem vf(uuid, type, LLFileSystem::READ); tsap->mSize = vf.getSize(); status = LLTS_OK; } else { // Uh oh, something bad happened when we tried to get this asset! switch (result) { case LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE: status = LLTS_UNKNOWN_SOURCE; break; default: status = LLTS_ERROR; } } tsap->sendTransferStatus(status); } LLTransferSourceParamsAsset::LLTransferSourceParamsAsset() : LLTransferSourceParams(LLTST_ASSET), mAssetType(LLAssetType::AT_NONE) { } void LLTransferSourceParamsAsset::setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type) { mAssetID = asset_id; mAssetType = asset_type; } void LLTransferSourceParamsAsset::packParams(LLDataPacker &dp) const { dp.packUUID(mAssetID, "AssetID"); dp.packS32(mAssetType, "AssetType"); } bool LLTransferSourceParamsAsset::unpackParams(LLDataPacker &dp) { S32 tmp_at; dp.unpackUUID(mAssetID, "AssetID"); dp.unpackS32(tmp_at, "AssetType"); mAssetType = (LLAssetType::EType)tmp_at; return true; }