PageRenderTime 42ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llmessage/llxfer_vfile.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 338 lines | 215 code | 75 blank | 48 comment | 19 complexity | 819461d81902861a8989c53782685cc6 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llxfer_vfile.cpp
  3. * @brief implementation of LLXfer_VFile class for a single xfer (vfile).
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "llxfer_vfile.h"
  28. #include "lluuid.h"
  29. #include "llerror.h"
  30. #include "llmath.h"
  31. #include "llvfile.h"
  32. #include "llvfs.h"
  33. #include "lldir.h"
  34. // size of chunks read from/written to disk
  35. const U32 LL_MAX_XFER_FILE_BUFFER = 65536;
  36. ///////////////////////////////////////////////////////////
  37. LLXfer_VFile::LLXfer_VFile ()
  38. : LLXfer(-1)
  39. {
  40. init(NULL, LLUUID::null, LLAssetType::AT_NONE);
  41. }
  42. LLXfer_VFile::LLXfer_VFile (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type)
  43. : LLXfer(-1)
  44. {
  45. init(vfs, local_id, type);
  46. }
  47. ///////////////////////////////////////////////////////////
  48. LLXfer_VFile::~LLXfer_VFile ()
  49. {
  50. cleanup();
  51. }
  52. ///////////////////////////////////////////////////////////
  53. void LLXfer_VFile::init (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type)
  54. {
  55. mVFS = vfs;
  56. mLocalID = local_id;
  57. mType = type;
  58. mVFile = NULL;
  59. std::string id_string;
  60. mLocalID.toString(id_string);
  61. mName = llformat("VFile %s:%s", id_string.c_str(), LLAssetType::lookup(mType));
  62. }
  63. ///////////////////////////////////////////////////////////
  64. void LLXfer_VFile::cleanup ()
  65. {
  66. LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE);
  67. file.remove();
  68. delete mVFile;
  69. mVFile = NULL;
  70. LLXfer::cleanup();
  71. }
  72. ///////////////////////////////////////////////////////////
  73. S32 LLXfer_VFile::initializeRequest(U64 xfer_id,
  74. LLVFS* vfs,
  75. const LLUUID& local_id,
  76. const LLUUID& remote_id,
  77. LLAssetType::EType type,
  78. const LLHost& remote_host,
  79. void (*callback)(void**,S32,LLExtStat),
  80. void** user_data)
  81. {
  82. S32 retval = 0; // presume success
  83. mRemoteHost = remote_host;
  84. mVFS = vfs;
  85. mLocalID = local_id;
  86. mRemoteID = remote_id;
  87. mType = type;
  88. mID = xfer_id;
  89. mCallback = callback;
  90. mCallbackDataHandle = user_data;
  91. mCallbackResult = LL_ERR_NOERR;
  92. std::string id_string;
  93. mLocalID.toString(id_string);
  94. mName = llformat("VFile %s:%s", id_string.c_str(), LLAssetType::lookup(mType));
  95. llinfos << "Requesting " << mName << llendl;
  96. if (mBuffer)
  97. {
  98. delete[] mBuffer;
  99. mBuffer = NULL;
  100. }
  101. mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
  102. mBufferLength = 0;
  103. mPacketNum = 0;
  104. mTempID.generate();
  105. mStatus = e_LL_XFER_PENDING;
  106. return retval;
  107. }
  108. //////////////////////////////////////////////////////////
  109. S32 LLXfer_VFile::startDownload()
  110. {
  111. S32 retval = 0; // presume success
  112. LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
  113. gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
  114. gMessageSystem->nextBlockFast(_PREHASH_XferID);
  115. gMessageSystem->addU64Fast(_PREHASH_ID, mID);
  116. gMessageSystem->addStringFast(_PREHASH_Filename, "");
  117. gMessageSystem->addU8("FilePath", (U8) LL_PATH_NONE);
  118. gMessageSystem->addBOOL("DeleteOnCompletion", FALSE);
  119. gMessageSystem->addBOOL("UseBigPackets", BOOL(mChunkSize == LL_XFER_LARGE_PAYLOAD));
  120. gMessageSystem->addUUIDFast(_PREHASH_VFileID, mRemoteID);
  121. gMessageSystem->addS16Fast(_PREHASH_VFileType, (S16)mType);
  122. gMessageSystem->sendReliable(mRemoteHost);
  123. mStatus = e_LL_XFER_IN_PROGRESS;
  124. return (retval);
  125. }
  126. ///////////////////////////////////////////////////////////
  127. S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host)
  128. {
  129. S32 retval = LL_ERR_NOERR; // presume success
  130. mRemoteHost = remote_host;
  131. mID = xfer_id;
  132. mPacketNum = -1;
  133. // cout << "Sending file: " << mLocalFilename << endl;
  134. delete [] mBuffer;
  135. mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
  136. mBufferLength = 0;
  137. mBufferStartOffset = 0;
  138. delete mVFile;
  139. mVFile = NULL;
  140. if(mVFS->getExists(mLocalID, mType))
  141. {
  142. mVFile = new LLVFile(mVFS, mLocalID, mType, LLVFile::READ);
  143. if (mVFile->getSize() <= 0)
  144. {
  145. delete mVFile;
  146. mVFile = NULL;
  147. return LL_ERR_FILE_EMPTY;
  148. }
  149. }
  150. if(mVFile)
  151. {
  152. setXferSize(mVFile->getSize());
  153. mStatus = e_LL_XFER_PENDING;
  154. }
  155. else
  156. {
  157. retval = LL_ERR_FILE_NOT_FOUND;
  158. }
  159. return (retval);
  160. }
  161. ///////////////////////////////////////////////////////////
  162. void LLXfer_VFile::setXferSize (S32 xfer_size)
  163. {
  164. LLXfer::setXferSize(xfer_size);
  165. // Don't do this on the server side, where we have a persistent mVFile
  166. // It would be nice if LLXFers could tell which end of the pipe they were
  167. if (! mVFile)
  168. {
  169. LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
  170. file.setMaxSize(xfer_size);
  171. }
  172. }
  173. ///////////////////////////////////////////////////////////
  174. S32 LLXfer_VFile::getMaxBufferSize ()
  175. {
  176. return(LL_MAX_XFER_FILE_BUFFER);
  177. }
  178. ///////////////////////////////////////////////////////////
  179. S32 LLXfer_VFile::suck(S32 start_position)
  180. {
  181. S32 retval = 0;
  182. if (mVFile)
  183. {
  184. // grab a buffer from the right place in the file
  185. if (! mVFile->seek(start_position, 0))
  186. {
  187. llwarns << "VFile Xfer Can't seek to position " << start_position << ", file length " << mVFile->getSize() << llendl;
  188. llwarns << "While sending file " << mLocalID << llendl;
  189. return -1;
  190. }
  191. if (mVFile->read((U8*)mBuffer, LL_MAX_XFER_FILE_BUFFER)) /* Flawfinder : ignore */
  192. {
  193. mBufferLength = mVFile->getLastBytesRead();
  194. mBufferStartOffset = start_position;
  195. mBufferContainsEOF = mVFile->eof();
  196. }
  197. else
  198. {
  199. retval = -1;
  200. }
  201. }
  202. else
  203. {
  204. retval = -1;
  205. }
  206. return (retval);
  207. }
  208. ///////////////////////////////////////////////////////////
  209. S32 LLXfer_VFile::flush()
  210. {
  211. S32 retval = 0;
  212. if (mBufferLength)
  213. {
  214. LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
  215. file.write((U8*)mBuffer, mBufferLength);
  216. mBufferLength = 0;
  217. }
  218. return (retval);
  219. }
  220. ///////////////////////////////////////////////////////////
  221. S32 LLXfer_VFile::processEOF()
  222. {
  223. S32 retval = 0;
  224. mStatus = e_LL_XFER_COMPLETE;
  225. flush();
  226. if (!mCallbackResult)
  227. {
  228. LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE);
  229. if (! file.rename(mLocalID, mType))
  230. {
  231. llinfos << "copy from temp file failed: unable to rename to " << mLocalID << llendl;
  232. }
  233. }
  234. if (mVFile)
  235. {
  236. delete mVFile;
  237. mVFile = NULL;
  238. }
  239. retval = LLXfer::processEOF();
  240. return(retval);
  241. }
  242. ////////////////////////////////////////////////////////////
  243. BOOL LLXfer_VFile::matchesLocalFile(const LLUUID &id, LLAssetType::EType type)
  244. {
  245. return (id == mLocalID && type == mType);
  246. }
  247. //////////////////////////////////////////////////////////
  248. BOOL LLXfer_VFile::matchesRemoteFile(const LLUUID &id, LLAssetType::EType type)
  249. {
  250. return (id == mRemoteID && type == mType);
  251. }
  252. //////////////////////////////////////////////////////////
  253. std::string LLXfer_VFile::getFileName()
  254. {
  255. return mName;
  256. }
  257. //////////////////////////////////////////////////////////
  258. // hacky - doesn't matter what this is
  259. // as long as it's different from the other classes
  260. U32 LLXfer_VFile::getXferTypeTag()
  261. {
  262. return LLXfer::XFER_VFILE;
  263. }