00001
00032 #include "linden_common.h"
00033
00034 #include "llxfer_vfile.h"
00035 #include "lluuid.h"
00036 #include "llerror.h"
00037 #include "llmath.h"
00038 #include "llvfile.h"
00039 #include "llvfs.h"
00040 #include "lldir.h"
00041
00042
00043 const U32 LL_MAX_XFER_FILE_BUFFER = 65536;
00044
00046
00047 LLXfer_VFile::LLXfer_VFile ()
00048 : LLXfer(-1)
00049 {
00050 init(NULL, LLUUID::null, LLAssetType::AT_NONE);
00051 }
00052
00053 LLXfer_VFile::LLXfer_VFile (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type)
00054 : LLXfer(-1)
00055 {
00056 init(vfs, local_id, type);
00057 }
00058
00060
00061 LLXfer_VFile::~LLXfer_VFile ()
00062 {
00063 free();
00064 }
00065
00067
00068 void LLXfer_VFile::init (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type)
00069 {
00070
00071 mVFS = vfs;
00072 mLocalID = local_id;
00073 mType = type;
00074
00075 mVFile = NULL;
00076
00077 char id_string[UUID_STR_LENGTH];
00078 mLocalID.toString(id_string);
00079
00080 snprintf(mName, sizeof(mName), "VFile %s:%s", id_string, LLAssetType::lookup(mType));
00081 }
00082
00084
00085 void LLXfer_VFile::free ()
00086 {
00087 LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE);
00088 file.remove();
00089
00090 delete mVFile;
00091 mVFile = NULL;
00092
00093 LLXfer::free();
00094 }
00095
00097
00098 S32 LLXfer_VFile::initializeRequest(U64 xfer_id,
00099 LLVFS* vfs,
00100 const LLUUID& local_id,
00101 const LLUUID& remote_id,
00102 LLAssetType::EType type,
00103 const LLHost& remote_host,
00104 void (*callback)(void**,S32,LLExtStat),
00105 void** user_data)
00106 {
00107 S32 retval = 0;
00108
00109 mRemoteHost = remote_host;
00110
00111 mVFS = vfs;
00112 mLocalID = local_id;
00113 mRemoteID = remote_id;
00114 mType = type;
00115
00116 mID = xfer_id;
00117 mCallback = callback;
00118 mCallbackDataHandle = user_data;
00119 mCallbackResult = LL_ERR_NOERR;
00120
00121 char id_string[UUID_STR_LENGTH];
00122 mLocalID.toString(id_string);
00123
00124 snprintf(mName, sizeof(mName), "VFile %s:%s", id_string, LLAssetType::lookup(mType));
00125
00126 llinfos << "Requesting " << mName << llendl;
00127
00128 if (mBuffer)
00129 {
00130 delete[] mBuffer;
00131 mBuffer = NULL;
00132 }
00133
00134 mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
00135
00136 mBufferLength = 0;
00137 mPacketNum = 0;
00138 mTempID.generate();
00139 mStatus = e_LL_XFER_PENDING;
00140 return retval;
00141 }
00142
00144
00145 S32 LLXfer_VFile::startDownload()
00146 {
00147 S32 retval = 0;
00148 LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
00149
00150 gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
00151 gMessageSystem->nextBlockFast(_PREHASH_XferID);
00152 gMessageSystem->addU64Fast(_PREHASH_ID, mID);
00153 gMessageSystem->addStringFast(_PREHASH_Filename, "");
00154 gMessageSystem->addU8("FilePath", (U8) LL_PATH_NONE);
00155 gMessageSystem->addBOOL("DeleteOnCompletion", FALSE);
00156 gMessageSystem->addBOOL("UseBigPackets", BOOL(mChunkSize == LL_XFER_LARGE_PAYLOAD));
00157 gMessageSystem->addUUIDFast(_PREHASH_VFileID, mRemoteID);
00158 gMessageSystem->addS16Fast(_PREHASH_VFileType, (S16)mType);
00159
00160 gMessageSystem->sendReliable(mRemoteHost);
00161 mStatus = e_LL_XFER_IN_PROGRESS;
00162
00163 return (retval);
00164 }
00165
00167
00168 S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host)
00169 {
00170 S32 retval = LL_ERR_NOERR;
00171
00172 mRemoteHost = remote_host;
00173 mID = xfer_id;
00174 mPacketNum = -1;
00175
00176
00177
00178 delete [] mBuffer;
00179 mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
00180
00181 mBufferLength = 0;
00182 mBufferStartOffset = 0;
00183
00184 delete mVFile;
00185 mVFile = NULL;
00186 if(mVFS->getExists(mLocalID, mType))
00187 {
00188 mVFile = new LLVFile(mVFS, mLocalID, mType, LLVFile::READ);
00189
00190 if (mVFile->getSize() <= 0)
00191 {
00192 delete mVFile;
00193 mVFile = NULL;
00194
00195 return LL_ERR_FILE_EMPTY;
00196 }
00197 }
00198
00199 if(mVFile)
00200 {
00201 setXferSize(mVFile->getSize());
00202 mStatus = e_LL_XFER_PENDING;
00203 }
00204 else
00205 {
00206 retval = LL_ERR_FILE_NOT_FOUND;
00207 }
00208
00209 return (retval);
00210 }
00211
00213 void LLXfer_VFile::setXferSize (S32 xfer_size)
00214 {
00215 LLXfer::setXferSize(xfer_size);
00216
00217
00218
00219 if (! mVFile)
00220 {
00221 LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
00222 file.setMaxSize(xfer_size);
00223 }
00224 }
00225
00227
00228 S32 LLXfer_VFile::getMaxBufferSize ()
00229 {
00230 return(LL_MAX_XFER_FILE_BUFFER);
00231 }
00232
00234
00235 S32 LLXfer_VFile::suck(S32 start_position)
00236 {
00237 S32 retval = 0;
00238
00239 if (mVFile)
00240 {
00241
00242 if (! mVFile->seek(start_position, 0))
00243 {
00244 llwarns << "VFile Xfer Can't seek to position " << start_position << ", file length " << mVFile->getSize() << llendl;
00245 llwarns << "While sending file " << mLocalID << llendl;
00246 return -1;
00247 }
00248
00249 if (mVFile->read((U8*)mBuffer, LL_MAX_XFER_FILE_BUFFER))
00250 {
00251 mBufferLength = mVFile->getLastBytesRead();
00252 mBufferStartOffset = start_position;
00253
00254 mBufferContainsEOF = mVFile->eof();
00255 }
00256 else
00257 {
00258 retval = -1;
00259 }
00260 }
00261 else
00262 {
00263 retval = -1;
00264 }
00265
00266 return (retval);
00267 }
00268
00270
00271 S32 LLXfer_VFile::flush()
00272 {
00273 S32 retval = 0;
00274 if (mBufferLength)
00275 {
00276 LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
00277
00278 file.write((U8*)mBuffer, mBufferLength);
00279
00280 mBufferLength = 0;
00281 }
00282 return (retval);
00283 }
00284
00286
00287 S32 LLXfer_VFile::processEOF()
00288 {
00289 S32 retval = 0;
00290 mStatus = e_LL_XFER_COMPLETE;
00291
00292 flush();
00293
00294 if (!mCallbackResult)
00295 {
00296 LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE);
00297 if (! file.rename(mLocalID, mType))
00298 {
00299 llinfos << "copy from temp file failed: unable to rename to " << mLocalID << llendl;
00300 }
00301
00302 }
00303
00304 if (mVFile)
00305 {
00306 delete mVFile;
00307 mVFile = NULL;
00308 }
00309
00310 retval = LLXfer::processEOF();
00311
00312 return(retval);
00313 }
00314
00316
00317 BOOL LLXfer_VFile::matchesLocalFile(const LLUUID &id, LLAssetType::EType type)
00318 {
00319 return (id == mLocalID && type == mType);
00320 }
00321
00323
00324 BOOL LLXfer_VFile::matchesRemoteFile(const LLUUID &id, LLAssetType::EType type)
00325 {
00326 return (id == mRemoteID && type == mType);
00327 }
00328
00330
00331 const char * LLXfer_VFile::getName()
00332 {
00333 return mName;
00334 }
00335
00337
00338
00339
00340 U32 LLXfer_VFile::getXferTypeTag()
00341 {
00342 return LLXfer::XFER_VFILE;
00343 }