PageRenderTime 81ms CodeModel.GetById 29ms app.highlight 47ms RepoModel.GetById 2ms 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
  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
 27#include "linden_common.h"
 28
 29#include "llxfer_vfile.h"
 30#include "lluuid.h"
 31#include "llerror.h"
 32#include "llmath.h"
 33#include "llvfile.h"
 34#include "llvfs.h"
 35#include "lldir.h"
 36
 37// size of chunks read from/written to disk
 38const U32 LL_MAX_XFER_FILE_BUFFER = 65536;
 39
 40///////////////////////////////////////////////////////////
 41
 42LLXfer_VFile::LLXfer_VFile ()
 43: LLXfer(-1)
 44{
 45	init(NULL, LLUUID::null, LLAssetType::AT_NONE);
 46}
 47
 48LLXfer_VFile::LLXfer_VFile (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type)
 49: LLXfer(-1)
 50{
 51	init(vfs, local_id, type);
 52}
 53
 54///////////////////////////////////////////////////////////
 55
 56LLXfer_VFile::~LLXfer_VFile ()
 57{
 58	cleanup();
 59}
 60
 61///////////////////////////////////////////////////////////
 62
 63void LLXfer_VFile::init (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type)
 64{
 65
 66	mVFS = vfs;
 67	mLocalID = local_id;
 68	mType = type;
 69
 70	mVFile = NULL;
 71
 72	std::string id_string;
 73	mLocalID.toString(id_string);
 74
 75	mName = llformat("VFile %s:%s", id_string.c_str(), LLAssetType::lookup(mType));
 76}
 77	
 78///////////////////////////////////////////////////////////
 79
 80void LLXfer_VFile::cleanup ()
 81{
 82	LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE);
 83	file.remove();
 84
 85	delete mVFile;
 86	mVFile = NULL;
 87
 88	LLXfer::cleanup();
 89}
 90
 91///////////////////////////////////////////////////////////
 92
 93S32 LLXfer_VFile::initializeRequest(U64 xfer_id,
 94									LLVFS* vfs,
 95									const LLUUID& local_id,
 96									const LLUUID& remote_id,
 97									LLAssetType::EType type,
 98									const LLHost& remote_host,
 99									void (*callback)(void**,S32,LLExtStat),
100									void** user_data)
101{
102 	S32 retval = 0;  // presume success
103	
104	mRemoteHost = remote_host;
105
106	mVFS = vfs;
107	mLocalID = local_id;
108	mRemoteID = remote_id;
109	mType = type;
110
111	mID = xfer_id;
112	mCallback = callback;
113	mCallbackDataHandle = user_data;
114	mCallbackResult = LL_ERR_NOERR;
115
116	std::string id_string;
117	mLocalID.toString(id_string);
118
119	mName = llformat("VFile %s:%s", id_string.c_str(), LLAssetType::lookup(mType));
120
121	llinfos << "Requesting " << mName << llendl;
122
123	if (mBuffer)
124	{
125		delete[] mBuffer;
126		mBuffer = NULL;
127	}
128
129	mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
130
131	mBufferLength = 0;
132	mPacketNum = 0;
133	mTempID.generate();
134 	mStatus = e_LL_XFER_PENDING;
135	return retval;
136}
137
138//////////////////////////////////////////////////////////
139
140S32 LLXfer_VFile::startDownload()
141{
142 	S32 retval = 0;  // presume success
143	LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
144
145	gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
146	gMessageSystem->nextBlockFast(_PREHASH_XferID);
147	gMessageSystem->addU64Fast(_PREHASH_ID, mID);
148	gMessageSystem->addStringFast(_PREHASH_Filename, "");
149	gMessageSystem->addU8("FilePath", (U8) LL_PATH_NONE);
150	gMessageSystem->addBOOL("DeleteOnCompletion", FALSE);
151	gMessageSystem->addBOOL("UseBigPackets", BOOL(mChunkSize == LL_XFER_LARGE_PAYLOAD));
152	gMessageSystem->addUUIDFast(_PREHASH_VFileID, mRemoteID);
153	gMessageSystem->addS16Fast(_PREHASH_VFileType, (S16)mType);
154
155	gMessageSystem->sendReliable(mRemoteHost);		
156	mStatus = e_LL_XFER_IN_PROGRESS;
157
158	return (retval);
159}
160
161///////////////////////////////////////////////////////////
162
163S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host)
164{
165	S32 retval = LL_ERR_NOERR;  // presume success
166	
167    mRemoteHost = remote_host;
168	mID = xfer_id;
169   	mPacketNum = -1;
170
171//	cout << "Sending file: " << mLocalFilename << endl;
172
173	delete [] mBuffer;
174	mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
175
176	mBufferLength = 0;
177	mBufferStartOffset = 0;	
178	
179	delete mVFile;
180	mVFile = NULL;
181	if(mVFS->getExists(mLocalID, mType))
182	{
183		mVFile = new LLVFile(mVFS, mLocalID, mType, LLVFile::READ);
184
185		if (mVFile->getSize() <= 0)
186		{
187			delete mVFile;
188			mVFile = NULL;
189
190			return LL_ERR_FILE_EMPTY;
191		}
192	}
193
194	if(mVFile)
195	{
196		setXferSize(mVFile->getSize());
197		mStatus = e_LL_XFER_PENDING;
198	}
199	else
200	{
201		retval = LL_ERR_FILE_NOT_FOUND;
202	}
203
204	return (retval);
205}
206
207///////////////////////////////////////////////////////////
208void LLXfer_VFile::setXferSize (S32 xfer_size)
209{	
210	LLXfer::setXferSize(xfer_size);
211
212	// Don't do this on the server side, where we have a persistent mVFile
213	// It would be nice if LLXFers could tell which end of the pipe they were
214	if (! mVFile)
215	{
216		LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
217		file.setMaxSize(xfer_size);
218	}
219}
220
221///////////////////////////////////////////////////////////
222
223S32 LLXfer_VFile::getMaxBufferSize ()
224{
225	return(LL_MAX_XFER_FILE_BUFFER);
226}
227
228///////////////////////////////////////////////////////////
229
230S32 LLXfer_VFile::suck(S32 start_position)
231{
232	S32 retval = 0;
233
234	if (mVFile)
235	{
236		// grab a buffer from the right place in the file
237		if (! mVFile->seek(start_position, 0))
238		{
239			llwarns << "VFile Xfer Can't seek to position " << start_position << ", file length " << mVFile->getSize() << llendl;
240			llwarns << "While sending file " << mLocalID << llendl;
241			return -1;
242		}
243		
244		if (mVFile->read((U8*)mBuffer, LL_MAX_XFER_FILE_BUFFER))		/* Flawfinder : ignore */
245		{
246			mBufferLength = mVFile->getLastBytesRead();
247			mBufferStartOffset = start_position;
248
249			mBufferContainsEOF = mVFile->eof();
250		}
251		else
252		{
253			retval = -1;
254		}
255	}
256	else
257	{
258		retval = -1;
259	}
260
261	return (retval);
262}
263
264///////////////////////////////////////////////////////////
265
266S32 LLXfer_VFile::flush()
267{
268	S32 retval = 0;
269	if (mBufferLength)
270	{
271		LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND);
272
273		file.write((U8*)mBuffer, mBufferLength);
274			
275		mBufferLength = 0;
276	}
277	return (retval);
278}
279
280///////////////////////////////////////////////////////////
281
282S32 LLXfer_VFile::processEOF()
283{
284	S32 retval = 0;
285	mStatus = e_LL_XFER_COMPLETE;
286
287	flush();
288
289	if (!mCallbackResult)
290	{
291		LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE);
292		if (! file.rename(mLocalID, mType))
293		{
294			llinfos << "copy from temp file failed: unable to rename to " << mLocalID << llendl;
295		}
296
297	}
298
299	if (mVFile)
300	{
301		delete mVFile;
302		mVFile = NULL;
303	}
304
305	retval = LLXfer::processEOF();
306
307	return(retval);
308}
309
310////////////////////////////////////////////////////////////
311
312BOOL LLXfer_VFile::matchesLocalFile(const LLUUID &id, LLAssetType::EType type)
313{
314	return (id == mLocalID && type == mType);
315}
316
317//////////////////////////////////////////////////////////
318
319BOOL LLXfer_VFile::matchesRemoteFile(const LLUUID &id, LLAssetType::EType type)
320{
321	return (id == mRemoteID && type == mType);
322}
323
324//////////////////////////////////////////////////////////
325
326std::string LLXfer_VFile::getFileName() 
327{
328	return mName;
329}
330
331//////////////////////////////////////////////////////////
332
333// hacky - doesn't matter what this is
334// as long as it's different from the other classes
335U32 LLXfer_VFile::getXferTypeTag()
336{
337	return LLXfer::XFER_VFILE;
338}