PageRenderTime 113ms CodeModel.GetById 17ms app.highlight 87ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llmessage/llxfermanager.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1277 lines | 905 code | 201 blank | 171 comment | 162 complexity | d51f91f93569cf78f5baaf51e30cfb6c MD5 | raw file
   1/** 
   2 * @file llxfermanager.cpp
   3 * @brief implementation of LLXferManager class for a collection of xfers
   4 *
   5 * $LicenseInfo:firstyear=2001&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 "llxfermanager.h"
  30
  31#include "llxfer.h"
  32#include "llxfer_file.h"
  33#include "llxfer_mem.h"
  34#include "llxfer_vfile.h"
  35
  36#include "llerror.h"
  37#include "lluuid.h"
  38#include "u64.h"
  39
  40const F32 LL_XFER_REGISTRATION_TIMEOUT = 60.0f;  // timeout if a registered transfer hasn't been requested in 60 seconds
  41const F32 LL_PACKET_TIMEOUT = 3.0f;             // packet timeout at 3 s
  42const S32 LL_PACKET_RETRY_LIMIT = 10;            // packet retransmission limit
  43
  44const S32 LL_DEFAULT_MAX_SIMULTANEOUS_XFERS = 10;
  45const S32 LL_DEFAULT_MAX_REQUEST_FIFO_XFERS = 1000;
  46
  47#define LL_XFER_PROGRESS_MESSAGES 0
  48#define LL_XFER_TEST_REXMIT       0
  49
  50
  51///////////////////////////////////////////////////////////
  52
  53LLXferManager::LLXferManager (LLVFS *vfs)
  54{
  55	init(vfs);
  56}
  57
  58///////////////////////////////////////////////////////////
  59
  60LLXferManager::~LLXferManager ()
  61{
  62	cleanup();
  63}
  64
  65///////////////////////////////////////////////////////////
  66
  67void LLXferManager::init (LLVFS *vfs)
  68{
  69	mSendList = NULL;
  70	mReceiveList = NULL;
  71
  72	setMaxOutgoingXfersPerCircuit(LL_DEFAULT_MAX_SIMULTANEOUS_XFERS);
  73	setMaxIncomingXfers(LL_DEFAULT_MAX_REQUEST_FIFO_XFERS);
  74
  75	mVFS = vfs;
  76
  77	// Turn on or off ack throttling
  78	mUseAckThrottling = FALSE;
  79	setAckThrottleBPS(100000);
  80}
  81	
  82///////////////////////////////////////////////////////////
  83
  84void LLXferManager::cleanup ()
  85{
  86	LLXfer *xferp;
  87	LLXfer *delp;
  88
  89	for_each(mOutgoingHosts.begin(), mOutgoingHosts.end(), DeletePointer());
  90	mOutgoingHosts.clear();
  91
  92	delp = mSendList;
  93	while (delp)
  94	{
  95		xferp = delp->mNext;
  96		delete delp;
  97		delp = xferp;
  98	}
  99	mSendList = NULL;
 100
 101	delp = mReceiveList;
 102	while (delp)
 103	{
 104		xferp = delp->mNext;
 105		delete delp;
 106		delp = xferp;
 107	}
 108	mReceiveList = NULL;
 109}
 110
 111///////////////////////////////////////////////////////////
 112
 113void LLXferManager::setMaxIncomingXfers(S32 max_num)
 114{
 115	mMaxIncomingXfers = max_num;
 116}
 117
 118///////////////////////////////////////////////////////////
 119
 120void LLXferManager::setMaxOutgoingXfersPerCircuit(S32 max_num)
 121{
 122	mMaxOutgoingXfersPerCircuit = max_num;
 123}
 124
 125void LLXferManager::setUseAckThrottling(const BOOL use)
 126{
 127	mUseAckThrottling = use;
 128}
 129
 130void LLXferManager::setAckThrottleBPS(const F32 bps)
 131{
 132	// Let's figure out the min we can set based on the ack retry rate
 133	// and number of simultaneous.
 134
 135	// Assuming we're running as slow as possible, this is the lowest ack
 136	// rate we can use.
 137	F32 min_bps = (1000.f * 8.f* mMaxIncomingXfers) / LL_PACKET_TIMEOUT;
 138
 139	// Set
 140	F32 actual_rate = llmax(min_bps*1.1f, bps);
 141	LL_DEBUGS("AppInit") << "LLXferManager ack throttle min rate: " << min_bps << LL_ENDL;
 142	LL_DEBUGS("AppInit") << "LLXferManager ack throttle actual rate: " << actual_rate << LL_ENDL;
 143	mAckThrottle.setRate(actual_rate);
 144}
 145
 146
 147///////////////////////////////////////////////////////////
 148
 149void LLXferManager::updateHostStatus()
 150{
 151    LLXfer *xferp;
 152	LLHostStatus *host_statusp = NULL;
 153
 154	for_each(mOutgoingHosts.begin(), mOutgoingHosts.end(), DeletePointer());
 155	mOutgoingHosts.clear();
 156
 157	for (xferp = mSendList; xferp; xferp = xferp->mNext)
 158	{
 159		for (status_list_t::iterator iter = mOutgoingHosts.begin();
 160			 iter != mOutgoingHosts.end(); ++iter)
 161		{
 162			host_statusp = *iter;
 163			if (host_statusp->mHost == xferp->mRemoteHost)
 164			{
 165				break;
 166			}
 167		}
 168		if (!host_statusp)
 169		{
 170			host_statusp = new LLHostStatus();
 171			if (host_statusp)
 172			{
 173				host_statusp->mHost = xferp->mRemoteHost;
 174				mOutgoingHosts.push_front(host_statusp);
 175			}
 176		}
 177		if (host_statusp)
 178		{
 179			if (xferp->mStatus == e_LL_XFER_PENDING)
 180			{
 181				host_statusp->mNumPending++;
 182			}
 183			else if (xferp->mStatus == e_LL_XFER_IN_PROGRESS)
 184			{
 185				host_statusp->mNumActive++;
 186			}
 187		}
 188		
 189	}	
 190}
 191
 192///////////////////////////////////////////////////////////
 193
 194void LLXferManager::printHostStatus()
 195{
 196	LLHostStatus *host_statusp = NULL;
 197	if (!mOutgoingHosts.empty())
 198	{
 199		llinfos << "Outgoing Xfers:" << llendl;
 200
 201		for (status_list_t::iterator iter = mOutgoingHosts.begin();
 202			 iter != mOutgoingHosts.end(); ++iter)
 203		{
 204			host_statusp = *iter;
 205			llinfos << "    " << host_statusp->mHost << "  active: " << host_statusp->mNumActive << "  pending: " << host_statusp->mNumPending << llendl;
 206		}
 207	}	
 208}
 209
 210///////////////////////////////////////////////////////////
 211
 212LLXfer *LLXferManager::findXfer (U64 id, LLXfer *list_head)
 213{
 214    LLXfer *xferp;
 215	for (xferp = list_head; xferp; xferp = xferp->mNext)
 216	{
 217		if (xferp->mID == id)
 218		{
 219			return(xferp);
 220		}
 221	}
 222	return(NULL);
 223}
 224
 225
 226///////////////////////////////////////////////////////////
 227
 228void LLXferManager::removeXfer (LLXfer *delp, LLXfer **list_head)
 229{
 230	// This function assumes that delp will only occur in the list
 231	// zero or one times.
 232	if (delp)
 233	{
 234		if (*list_head == delp)
 235		{
 236			*list_head = delp->mNext;
 237			delete (delp);
 238		}
 239		else
 240		{
 241			LLXfer *xferp = *list_head;
 242			while (xferp->mNext)
 243			{
 244				if (xferp->mNext == delp)
 245				{
 246					xferp->mNext = delp->mNext;
 247					delete (delp);
 248					break;
 249				}
 250				xferp = xferp->mNext;
 251			}
 252		}
 253	}
 254}
 255
 256///////////////////////////////////////////////////////////
 257
 258U32 LLXferManager::numActiveListEntries(LLXfer *list_head)
 259{
 260	U32 num_entries = 0;
 261
 262	while (list_head)
 263	{
 264		if ((list_head->mStatus == e_LL_XFER_IN_PROGRESS)) 
 265		{
 266			num_entries++;
 267		}
 268		list_head = list_head->mNext;
 269	}
 270	return(num_entries);
 271}
 272
 273///////////////////////////////////////////////////////////
 274
 275S32 LLXferManager::numPendingXfers(const LLHost &host)
 276{
 277	LLHostStatus *host_statusp = NULL;
 278
 279	for (status_list_t::iterator iter = mOutgoingHosts.begin();
 280		 iter != mOutgoingHosts.end(); ++iter)
 281	{
 282		host_statusp = *iter;
 283		if (host_statusp->mHost == host)
 284		{
 285			return (host_statusp->mNumPending);
 286		}
 287	}
 288	return 0;
 289}
 290
 291///////////////////////////////////////////////////////////
 292
 293S32 LLXferManager::numActiveXfers(const LLHost &host)
 294{
 295	LLHostStatus *host_statusp = NULL;
 296
 297	for (status_list_t::iterator iter = mOutgoingHosts.begin();
 298		 iter != mOutgoingHosts.end(); ++iter)
 299	{
 300		host_statusp = *iter;
 301		if (host_statusp->mHost == host)
 302		{
 303			return (host_statusp->mNumActive);
 304		}
 305	}
 306	return 0;
 307}
 308
 309///////////////////////////////////////////////////////////
 310
 311void LLXferManager::changeNumActiveXfers(const LLHost &host, S32 delta)
 312{
 313	LLHostStatus *host_statusp = NULL;
 314
 315	for (status_list_t::iterator iter = mOutgoingHosts.begin();
 316		 iter != mOutgoingHosts.end(); ++iter)
 317	{
 318		host_statusp = *iter;
 319		if (host_statusp->mHost == host)
 320		{
 321			host_statusp->mNumActive += delta;
 322		}
 323	}
 324}
 325
 326///////////////////////////////////////////////////////////
 327
 328void LLXferManager::registerCallbacks(LLMessageSystem *msgsystem)
 329{
 330	msgsystem->setHandlerFuncFast(_PREHASH_ConfirmXferPacket,  process_confirm_packet, NULL);
 331	msgsystem->setHandlerFuncFast(_PREHASH_RequestXfer,        process_request_xfer,        NULL);
 332	msgsystem->setHandlerFuncFast(_PREHASH_SendXferPacket,	   	continue_file_receive,		 NULL);
 333	msgsystem->setHandlerFuncFast(_PREHASH_AbortXfer, 	   	process_abort_xfer,		     NULL);
 334}
 335
 336///////////////////////////////////////////////////////////
 337
 338U64 LLXferManager::getNextID ()
 339{
 340	LLUUID a_guid;
 341
 342	a_guid.generate();
 343
 344	
 345	return(*((U64*)(a_guid.mData)));
 346}
 347
 348///////////////////////////////////////////////////////////
 349
 350S32 LLXferManager::encodePacketNum(S32 packet_num, BOOL is_EOF)
 351{
 352	if (is_EOF)
 353	{
 354		packet_num |= 0x80000000;
 355	}
 356	return packet_num;
 357}
 358
 359///////////////////////////////////////////////////////////
 360
 361S32 LLXferManager::decodePacketNum(S32 packet_num)
 362{
 363	return(packet_num & 0x0FFFFFFF);
 364}
 365
 366///////////////////////////////////////////////////////////
 367
 368BOOL LLXferManager::isLastPacket(S32 packet_num)
 369{
 370	return(packet_num & 0x80000000);
 371}
 372
 373///////////////////////////////////////////////////////////
 374
 375U64 LLXferManager::registerXfer(const void *datap, const S32 length)
 376{
 377	LLXfer *xferp;
 378	U64 xfer_id = getNextID();
 379
 380	xferp = (LLXfer *) new LLXfer_Mem();
 381	if (xferp)
 382	{
 383		xferp->mNext = mSendList;
 384		mSendList = xferp;
 385
 386		xfer_id = ((LLXfer_Mem *)xferp)->registerXfer(xfer_id, datap,length);
 387
 388		if (!xfer_id)
 389		{
 390			removeXfer(xferp,&mSendList);
 391		}
 392	}
 393	else
 394	{
 395		llerrs << "Xfer allocation error" << llendl;
 396		xfer_id = 0;
 397	}	
 398
 399    return(xfer_id);
 400}
 401
 402///////////////////////////////////////////////////////////
 403
 404void LLXferManager::requestFile(const std::string& local_filename,
 405								const std::string& remote_filename,
 406								ELLPath remote_path,
 407								const LLHost& remote_host,
 408								BOOL delete_remote_on_completion,
 409								void (*callback)(void**,S32,LLExtStat),
 410								void** user_data,
 411								BOOL is_priority,
 412								BOOL use_big_packets)
 413{
 414	LLXfer *xferp;
 415
 416	for (xferp = mReceiveList; xferp ; xferp = xferp->mNext)
 417	{
 418		if (xferp->getXferTypeTag() == LLXfer::XFER_FILE
 419			&& (((LLXfer_File*)xferp)->matchesLocalFilename(local_filename))
 420			&& (((LLXfer_File*)xferp)->matchesRemoteFilename(remote_filename, remote_path))
 421			&& (remote_host == xferp->mRemoteHost)
 422			&& (callback == xferp->mCallback)
 423			&& (user_data == xferp->mCallbackDataHandle))
 424
 425		{
 426			// cout << "requested a xfer already in progress" << endl;
 427			return;
 428		}
 429	}
 430
 431	S32 chunk_size = use_big_packets ? LL_XFER_LARGE_PAYLOAD : -1;
 432	xferp = (LLXfer *) new LLXfer_File(chunk_size);
 433	if (xferp)
 434	{
 435		addToList(xferp, mReceiveList, is_priority);
 436
 437		// Remove any file by the same name that happens to be lying
 438		// around.
 439		// Note: according to AaronB, this is here to deal with locks on files that were
 440		// in transit during a crash,
 441		if(delete_remote_on_completion &&
 442		   (remote_filename.substr(remote_filename.length()-4) == ".tmp"))
 443		{
 444			LLFile::remove(local_filename);
 445		}
 446		((LLXfer_File *)xferp)->initializeRequest(
 447			getNextID(),
 448			local_filename,
 449			remote_filename,
 450			remote_path,
 451			remote_host,
 452			delete_remote_on_completion,
 453			callback,user_data);
 454		startPendingDownloads();
 455	}
 456	else
 457	{
 458		llerrs << "Xfer allocation error" << llendl;
 459	}
 460}
 461
 462void LLXferManager::requestFile(const std::string& remote_filename,
 463								ELLPath remote_path,
 464								const LLHost& remote_host,
 465								BOOL delete_remote_on_completion,
 466								void (*callback)(void*,S32,void**,S32,LLExtStat),
 467								void** user_data,
 468								BOOL is_priority)
 469{
 470	LLXfer *xferp;
 471
 472	xferp = (LLXfer *) new LLXfer_Mem();
 473	if (xferp)
 474	{
 475		addToList(xferp, mReceiveList, is_priority);
 476		((LLXfer_Mem *)xferp)->initializeRequest(getNextID(),
 477												 remote_filename, 
 478												 remote_path,
 479												 remote_host,
 480												 delete_remote_on_completion,
 481												 callback, user_data);
 482		startPendingDownloads();
 483	}
 484	else
 485	{
 486		llerrs << "Xfer allocation error" << llendl;
 487	}
 488}
 489
 490void LLXferManager::requestVFile(const LLUUID& local_id,
 491								 const LLUUID& remote_id,
 492								 LLAssetType::EType type, LLVFS* vfs,
 493								 const LLHost& remote_host,
 494								 void (*callback)(void**,S32,LLExtStat),
 495								 void** user_data,
 496								 BOOL is_priority)
 497{
 498	LLXfer *xferp;
 499
 500	for (xferp = mReceiveList; xferp ; xferp = xferp->mNext)
 501	{
 502		if (xferp->getXferTypeTag() == LLXfer::XFER_VFILE
 503			&& (((LLXfer_VFile*)xferp)->matchesLocalFile(local_id, type))
 504			&& (((LLXfer_VFile*)xferp)->matchesRemoteFile(remote_id, type))
 505			&& (remote_host == xferp->mRemoteHost)
 506			&& (callback == xferp->mCallback)
 507			&& (user_data == xferp->mCallbackDataHandle))
 508
 509		{
 510			// cout << "requested a xfer already in progress" << endl;
 511			return;
 512		}
 513	}
 514
 515	xferp = (LLXfer *) new LLXfer_VFile();
 516	if (xferp)
 517	{
 518		addToList(xferp, mReceiveList, is_priority);
 519		((LLXfer_VFile *)xferp)->initializeRequest(getNextID(),
 520			vfs,
 521			local_id,
 522			remote_id,
 523			type,
 524			remote_host,
 525			callback,
 526			user_data);
 527		startPendingDownloads();
 528	}
 529	else
 530	{
 531		llerrs << "Xfer allocation error" << llendl;
 532	}
 533
 534}
 535
 536/*
 537void LLXferManager::requestXfer(
 538								const std::string& local_filename, 
 539								BOOL delete_remote_on_completion,
 540								U64 xfer_id, 
 541								const LLHost &remote_host, 
 542								void (*callback)(void **,S32),
 543								void **user_data)
 544{
 545	LLXfer *xferp;
 546
 547	for (xferp = mReceiveList; xferp ; xferp = xferp->mNext)
 548	{
 549		if (xferp->getXferTypeTag() == LLXfer::XFER_FILE
 550			&& (((LLXfer_File*)xferp)->matchesLocalFilename(local_filename))
 551			&& (xfer_id == xferp->mID)
 552			&& (remote_host == xferp->mRemoteHost)
 553			&& (callback == xferp->mCallback)
 554			&& (user_data == xferp->mCallbackDataHandle))
 555
 556		{
 557			// cout << "requested a xfer already in progress" << endl;
 558			return;
 559		}
 560	}
 561
 562	xferp = (LLXfer *) new LLXfer_File();
 563	if (xferp)
 564	{
 565		xferp->mNext = mReceiveList;
 566		mReceiveList = xferp;
 567
 568		((LLXfer_File *)xferp)->initializeRequest(xfer_id,local_filename,"",LL_PATH_NONE,remote_host,delete_remote_on_completion,callback,user_data);
 569		startPendingDownloads();
 570	}
 571	else
 572	{
 573		llerrs << "Xfer allcoation error" << llendl;
 574	}
 575}
 576
 577void LLXferManager::requestXfer(U64 xfer_id, const LLHost &remote_host, BOOL delete_remote_on_completion, void (*callback)(void *,S32,void **,S32),void **user_data)
 578{
 579	LLXfer *xferp;
 580
 581	xferp = (LLXfer *) new LLXfer_Mem();
 582	if (xferp)
 583	{
 584		xferp->mNext = mReceiveList;
 585		mReceiveList = xferp;
 586
 587		((LLXfer_Mem *)xferp)->initializeRequest(xfer_id,"",LL_PATH_NONE,remote_host,delete_remote_on_completion,callback,user_data);
 588		startPendingDownloads();
 589	}
 590	else
 591	{
 592		llerrs << "Xfer allcoation error" << llendl;
 593	}
 594}
 595*/
 596///////////////////////////////////////////////////////////
 597
 598void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user_data*/)
 599{
 600	// there's sometimes an extra 4 bytes added to an xfer payload
 601	const S32 BUF_SIZE = LL_XFER_LARGE_PAYLOAD + 4;
 602	char fdata_buf[LL_XFER_LARGE_PAYLOAD + 4];		/* Flawfinder : ignore */
 603	S32 fdata_size;
 604	U64 id;
 605	S32 packetnum;
 606	LLXfer * xferp;
 607	
 608	mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
 609	mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Packet, packetnum);
 610
 611	fdata_size = mesgsys->getSizeFast(_PREHASH_DataPacket,_PREHASH_Data);
 612	mesgsys->getBinaryDataFast(_PREHASH_DataPacket, _PREHASH_Data, fdata_buf, 0, 0, BUF_SIZE);
 613
 614	xferp = findXfer(id, mReceiveList);
 615
 616	if (!xferp) 
 617	{
 618		char U64_BUF[MAX_STRING];		/* Flawfinder : ignore */
 619		llwarns << "received xfer data from " << mesgsys->getSender()
 620			<< " for non-existent xfer id: "
 621			<< U64_to_str(id, U64_BUF, sizeof(U64_BUF)) << llendl;
 622		return;
 623	}
 624
 625	S32 xfer_size;
 626
 627	if (decodePacketNum(packetnum) != xferp->mPacketNum) // is the packet different from what we were expecting?
 628	{
 629		// confirm it if it was a resend of the last one, since the confirmation might have gotten dropped
 630		if (decodePacketNum(packetnum) == (xferp->mPacketNum - 1))
 631		{
 632			llinfos << "Reconfirming xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet " << packetnum << llendl; 			sendConfirmPacket(mesgsys, id, decodePacketNum(packetnum), mesgsys->getSender());
 633		}
 634		else
 635		{
 636			llinfos << "Ignoring xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " recv'd packet " << packetnum << "; expecting " << xferp->mPacketNum << llendl;
 637		}
 638		return;		
 639	}
 640
 641	S32 result = 0;
 642
 643	if (xferp->mPacketNum == 0) // first packet has size encoded as additional S32 at beginning of data
 644	{
 645		ntohmemcpy(&xfer_size,fdata_buf,MVT_S32,sizeof(S32));
 646		
 647// do any necessary things on first packet ie. allocate memory
 648		xferp->setXferSize(xfer_size);
 649
 650		// adjust buffer start and size
 651		result = xferp->receiveData(&(fdata_buf[sizeof(S32)]),fdata_size-(sizeof(S32)));
 652	}
 653	else
 654	{
 655		result = xferp->receiveData(fdata_buf,fdata_size);
 656	}
 657	
 658	if (result == LL_ERR_CANNOT_OPEN_FILE)
 659	{
 660			xferp->abort(LL_ERR_CANNOT_OPEN_FILE);
 661			removeXfer(xferp,&mReceiveList);
 662			startPendingDownloads();
 663			return;		
 664	}
 665
 666	xferp->mPacketNum++;  // expect next packet
 667
 668	if (!mUseAckThrottling)
 669	{
 670		// No throttling, confirm right away
 671		sendConfirmPacket(mesgsys, id, decodePacketNum(packetnum), mesgsys->getSender());
 672	}
 673	else
 674	{
 675		// Throttling, put on queue to be confirmed later.
 676		LLXferAckInfo ack_info;
 677		ack_info.mID = id;
 678		ack_info.mPacketNum = decodePacketNum(packetnum);
 679		ack_info.mRemoteHost = mesgsys->getSender();
 680		mXferAckQueue.push(ack_info);
 681	}
 682
 683	if (isLastPacket(packetnum))
 684	{
 685		xferp->processEOF();
 686		removeXfer(xferp,&mReceiveList);
 687		startPendingDownloads();
 688	}
 689}
 690
 691///////////////////////////////////////////////////////////
 692
 693void LLXferManager::sendConfirmPacket (LLMessageSystem *mesgsys, U64 id, S32 packetnum, const LLHost &remote_host)
 694{
 695#if LL_XFER_PROGRESS_MESSAGES
 696	if (!(packetnum % 50))
 697	{
 698		cout << "confirming xfer packet #" << packetnum << endl;
 699	}
 700#endif
 701	mesgsys->newMessageFast(_PREHASH_ConfirmXferPacket);
 702	mesgsys->nextBlockFast(_PREHASH_XferID);
 703	mesgsys->addU64Fast(_PREHASH_ID, id);
 704	mesgsys->addU32Fast(_PREHASH_Packet, packetnum);
 705
 706	mesgsys->sendMessage(remote_host);
 707}
 708
 709///////////////////////////////////////////////////////////
 710
 711static bool find_and_remove(std::multiset<std::string>& files,
 712		const std::string& filename)
 713{
 714	std::multiset<std::string>::iterator ptr;
 715	if ( (ptr = files.find(filename)) != files.end())
 716	{
 717		//erase(filename) erases *all* entries with that key
 718		files.erase(ptr);
 719		return true;
 720	}
 721	return false;
 722}
 723
 724void LLXferManager::expectFileForRequest(const std::string& filename)
 725{
 726	mExpectedRequests.insert(filename);
 727}
 728
 729bool LLXferManager::validateFileForRequest(const std::string& filename)
 730{
 731	return find_and_remove(mExpectedRequests, filename);
 732}
 733
 734void LLXferManager::expectFileForTransfer(const std::string& filename)
 735{
 736	mExpectedTransfers.insert(filename);
 737}
 738
 739bool LLXferManager::validateFileForTransfer(const std::string& filename)
 740{
 741	return find_and_remove(mExpectedTransfers, filename);
 742}
 743
 744static bool remove_prefix(std::string& filename, const std::string& prefix)
 745{
 746	if (std::equal(prefix.begin(), prefix.end(), filename.begin()))
 747	{
 748		filename = filename.substr(prefix.length());
 749		return true;
 750	}
 751	return false;
 752}
 753
 754static bool verify_cache_filename(const std::string& filename)
 755{
 756	//NOTE: This routine is only used to check file names that our own
 757	// code places in the cache directory.	As such, it can be limited
 758	// to this very restrictive file name pattern.	It does not need to
 759	// handle other characters. The only known uses of this are (with examples):
 760	//	sim to sim object pass:			fc0b72d8-9456-63d9-a802-a557ef847313.tmp
 761	//	sim to viewer mute list:		mute_b78eacd0-1244-448e-93ca-28ede242f647.tmp
 762	//	sim to viewer task inventory:	inventory_d8ab59d2-baf0-0e79-c4c2-a3f99b9fcf45.tmp
 763	
 764	//IMPORTANT: Do not broaden the filenames accepted by this routine
 765	// without careful analysis. Anything allowed by this function can
 766	// be downloaded by the viewer.
 767	
 768	size_t len = filename.size();
 769	//const boost::regex expr("[0-9a-zA-Z_-]<1,46>\.tmp");
 770	if (len < 5 || len > 50)
 771	{	
 772		return false;
 773	}
 774	for(size_t i=0; i<(len-4); ++i)
 775	{	
 776		char c = filename[i];
 777		bool ok = isalnum(c) || '_'==c || '-'==c;
 778		if (!ok)
 779		{
 780			return false;
 781		}
 782	}
 783	return filename[len-4] == '.'
 784		&& filename[len-3] == 't'
 785		&& filename[len-2] == 'm'
 786		&& filename[len-1] == 'p';
 787}
 788
 789void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/)
 790{
 791		
 792	U64 id;
 793	std::string local_filename;
 794	ELLPath local_path = LL_PATH_NONE;
 795	S32 result = LL_ERR_NOERR;
 796	LLUUID	uuid;
 797	LLAssetType::EType type;
 798	S16 type_s16;
 799	BOOL b_use_big_packets;
 800
 801	mesgsys->getBOOL("XferID", "UseBigPackets", b_use_big_packets);
 802	
 803	mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
 804	char U64_BUF[MAX_STRING];		/* Flawfinder : ignore */
 805	llinfos << "xfer request id: " << U64_to_str(id, U64_BUF, sizeof(U64_BUF))
 806		   << " to " << mesgsys->getSender() << llendl;
 807
 808	mesgsys->getStringFast(_PREHASH_XferID, _PREHASH_Filename, local_filename);
 809	
 810	{
 811		U8 local_path_u8;
 812		mesgsys->getU8("XferID", "FilePath", local_path_u8);
 813		local_path = (ELLPath)local_path_u8;
 814	}
 815
 816	mesgsys->getUUIDFast(_PREHASH_XferID, _PREHASH_VFileID, uuid);
 817	mesgsys->getS16Fast(_PREHASH_XferID, _PREHASH_VFileType, type_s16);
 818	type = (LLAssetType::EType)type_s16;
 819
 820	LLXfer *xferp;
 821
 822	if (uuid != LLUUID::null)
 823	{
 824		if(NULL == LLAssetType::lookup(type))
 825		{
 826			llwarns << "Invalid type for xfer request: " << uuid << ":"
 827					<< type_s16 << " to " << mesgsys->getSender() << llendl;
 828			return;
 829		}
 830			
 831		llinfos << "starting vfile transfer: " << uuid << "," << LLAssetType::lookup(type) << " to " << mesgsys->getSender() << llendl;
 832
 833		if (! mVFS)
 834		{
 835			llwarns << "Attempt to send VFile w/o available VFS" << llendl;
 836			return;
 837		}
 838
 839		xferp = (LLXfer *)new LLXfer_VFile(mVFS, uuid, type);
 840		if (xferp)
 841		{
 842			xferp->mNext = mSendList;
 843			mSendList = xferp;	
 844			result = xferp->startSend(id,mesgsys->getSender());
 845		}
 846		else
 847		{
 848			llerrs << "Xfer allcoation error" << llendl;
 849		}
 850	}
 851	else if (!local_filename.empty())
 852	{
 853		// See DEV-21775 for detailed security issues
 854
 855		if (local_path == LL_PATH_NONE)
 856		{
 857			// this handles legacy simulators that are passing objects
 858			// by giving a filename that explicitly names the cache directory
 859			static const std::string legacy_cache_prefix = "data/";
 860			if (remove_prefix(local_filename, legacy_cache_prefix))
 861			{
 862				local_path = LL_PATH_CACHE;
 863			}
 864		}
 865
 866		switch (local_path)
 867		{
 868			case LL_PATH_NONE:
 869				if(!validateFileForTransfer(local_filename))
 870				{
 871					llwarns << "SECURITY: Unapproved filename '" << local_filename << llendl;
 872					return;
 873				}
 874				break;
 875
 876			case LL_PATH_CACHE:
 877				if(!verify_cache_filename(local_filename))
 878				{
 879					llwarns << "SECURITY: Illegal cache filename '" << local_filename << llendl;
 880					return;
 881				}
 882				break;
 883
 884			default:
 885				llwarns << "SECURITY: Restricted file dir enum: " << (U32)local_path << llendl;
 886				return;
 887		}
 888
 889
 890		std::string expanded_filename = gDirUtilp->getExpandedFilename( local_path, local_filename );
 891		llinfos << "starting file transfer: " <<  expanded_filename << " to " << mesgsys->getSender() << llendl;
 892
 893		BOOL delete_local_on_completion = FALSE;
 894		mesgsys->getBOOL("XferID", "DeleteOnCompletion", delete_local_on_completion);
 895
 896		// -1 chunk_size causes it to use the default
 897		xferp = (LLXfer *)new LLXfer_File(expanded_filename, delete_local_on_completion, b_use_big_packets ? LL_XFER_LARGE_PAYLOAD : -1);
 898		
 899		if (xferp)
 900		{
 901			xferp->mNext = mSendList;
 902			mSendList = xferp;	
 903			result = xferp->startSend(id,mesgsys->getSender());
 904		}
 905		else
 906		{
 907			llerrs << "Xfer allcoation error" << llendl;
 908		}
 909	}
 910	else
 911	{
 912		char U64_BUF[MAX_STRING];		/* Flawfinder : ignore */
 913		llinfos << "starting memory transfer: "
 914			<< U64_to_str(id, U64_BUF, sizeof(U64_BUF)) << " to "
 915			<< mesgsys->getSender() << llendl;
 916
 917		xferp = findXfer(id, mSendList);
 918		
 919		if (xferp)
 920		{
 921			result = xferp->startSend(id,mesgsys->getSender());
 922		}
 923		else
 924		{
 925			llinfos << "Warning: " << U64_BUF << " not found." << llendl;
 926			result = LL_ERR_FILE_NOT_FOUND;
 927		}
 928	}
 929
 930	if (result)
 931	{
 932		if (xferp)
 933		{
 934			xferp->abort(result);
 935			removeXfer(xferp,&mSendList);
 936		}
 937		else // can happen with a memory transfer not found
 938		{
 939			llinfos << "Aborting xfer to " << mesgsys->getSender() << " with error: " << result << llendl;
 940
 941			mesgsys->newMessageFast(_PREHASH_AbortXfer);
 942			mesgsys->nextBlockFast(_PREHASH_XferID);
 943			mesgsys->addU64Fast(_PREHASH_ID, id);
 944			mesgsys->addS32Fast(_PREHASH_Result, result);
 945	
 946			mesgsys->sendMessage(mesgsys->getSender());		
 947		}
 948	}
 949	else if(xferp && (numActiveXfers(xferp->mRemoteHost) < mMaxOutgoingXfersPerCircuit))
 950	{
 951		xferp->sendNextPacket();
 952		changeNumActiveXfers(xferp->mRemoteHost,1);
 953//		llinfos << "***STARTING XFER IMMEDIATELY***" << llendl;
 954	}
 955	else
 956	{
 957		if(xferp)
 958		{
 959			llinfos << "  queueing xfer request, " << numPendingXfers(xferp->mRemoteHost) << " ahead of this one" << llendl;
 960		}
 961		else
 962		{
 963			llwarns << "LLXferManager::processFileRequest() - no xfer found!"
 964					<< llendl;
 965		}
 966	}
 967}
 968
 969
 970///////////////////////////////////////////////////////////
 971
 972void LLXferManager::processConfirmation (LLMessageSystem *mesgsys, void ** /*user_data*/)
 973{
 974	U64 id = 0;
 975	S32 packetNum = 0;
 976
 977	mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
 978	mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Packet, packetNum);
 979
 980	LLXfer* xferp = findXfer(id, mSendList);
 981	if (xferp)
 982	{
 983//		cout << "confirmed packet #" << packetNum << " ping: "<< xferp->ACKTimer.getElapsedTimeF32() <<  endl;
 984		xferp->mWaitingForACK = FALSE;
 985		if (xferp->mStatus == e_LL_XFER_IN_PROGRESS)
 986		{
 987			xferp->sendNextPacket();
 988		}
 989		else
 990		{
 991			removeXfer(xferp, &mSendList);
 992		}
 993	}
 994}
 995
 996///////////////////////////////////////////////////////////
 997
 998void LLXferManager::retransmitUnackedPackets ()
 999{
1000	LLXfer *xferp;
1001	LLXfer *delp;
1002	xferp = mReceiveList;
1003	while(xferp)
1004	{
1005		if (xferp->mStatus == e_LL_XFER_IN_PROGRESS)
1006		{
1007			// if the circuit dies, abort
1008			if (! gMessageSystem->mCircuitInfo.isCircuitAlive( xferp->mRemoteHost ))
1009			{
1010				llinfos << "Xfer found in progress on dead circuit, aborting" << llendl;
1011				xferp->mCallbackResult = LL_ERR_CIRCUIT_GONE;
1012				xferp->processEOF();
1013				delp = xferp;
1014				xferp = xferp->mNext;
1015				removeXfer(delp,&mReceiveList);
1016				continue;
1017 			}
1018				
1019		}
1020		xferp = xferp->mNext;
1021	}
1022
1023	xferp = mSendList; 
1024	updateHostStatus();
1025	F32 et;
1026	while (xferp)
1027	{
1028		if (xferp->mWaitingForACK && ( (et = xferp->ACKTimer.getElapsedTimeF32()) > LL_PACKET_TIMEOUT))
1029		{
1030			if (xferp->mRetries > LL_PACKET_RETRY_LIMIT)
1031			{
1032				llinfos << "dropping xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet retransmit limit exceeded, xfer dropped" << llendl;
1033				xferp->abort(LL_ERR_TCP_TIMEOUT);
1034				delp = xferp;
1035				xferp = xferp->mNext;
1036				removeXfer(delp,&mSendList);
1037			}
1038			else
1039			{
1040				llinfos << "resending xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet unconfirmed after: "<< et << " sec, packet " << xferp->mPacketNum << llendl;
1041				xferp->resendLastPacket();
1042				xferp = xferp->mNext;
1043			}
1044		}
1045		else if ((xferp->mStatus == e_LL_XFER_REGISTERED) && ( (et = xferp->ACKTimer.getElapsedTimeF32()) > LL_XFER_REGISTRATION_TIMEOUT))
1046		{
1047			llinfos << "registered xfer never requested, xfer dropped" << llendl;
1048			xferp->abort(LL_ERR_TCP_TIMEOUT);
1049			delp = xferp;
1050			xferp = xferp->mNext;
1051			removeXfer(delp,&mSendList);
1052		}
1053		else if (xferp->mStatus == e_LL_XFER_ABORTED)
1054		{
1055			llwarns << "Removing aborted xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << llendl;
1056			delp = xferp;
1057			xferp = xferp->mNext;
1058			removeXfer(delp,&mSendList);
1059		}
1060		else if (xferp->mStatus == e_LL_XFER_PENDING)
1061		{
1062//			llinfos << "*** numActiveXfers = " << numActiveXfers(xferp->mRemoteHost) << "        mMaxOutgoingXfersPerCircuit = " << mMaxOutgoingXfersPerCircuit << llendl;   
1063			if (numActiveXfers(xferp->mRemoteHost) < mMaxOutgoingXfersPerCircuit)
1064			{
1065//			    llinfos << "bumping pending xfer to active" << llendl;
1066				xferp->sendNextPacket();
1067				changeNumActiveXfers(xferp->mRemoteHost,1);
1068			}			
1069			xferp = xferp->mNext;
1070		}
1071		else
1072		{
1073			xferp = xferp->mNext;
1074		}
1075	}
1076
1077	//
1078	// HACK - if we're using xfer confirm throttling, throttle our xfer confirms here
1079	// so we don't blow through bandwidth.
1080	//
1081
1082	while (mXferAckQueue.getLength())
1083	{
1084		if (mAckThrottle.checkOverflow(1000.0f*8.0f))
1085		{
1086			break;
1087		}
1088		//llinfos << "Confirm packet queue length:" << mXferAckQueue.getLength() << llendl;
1089		LLXferAckInfo ack_info;
1090		mXferAckQueue.pop(ack_info);
1091		//llinfos << "Sending confirm packet" << llendl;
1092		sendConfirmPacket(gMessageSystem, ack_info.mID, ack_info.mPacketNum, ack_info.mRemoteHost);
1093		mAckThrottle.throttleOverflow(1000.f*8.f); // Assume 1000 bytes/packet
1094	}
1095}
1096
1097
1098///////////////////////////////////////////////////////////
1099
1100void LLXferManager::processAbort (LLMessageSystem *mesgsys, void ** /*user_data*/)
1101{
1102	U64 id = 0;
1103	S32 result_code = 0;
1104	LLXfer * xferp;
1105
1106	mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
1107	mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Result, result_code);
1108
1109	xferp = findXfer(id, mReceiveList);
1110	if (xferp)
1111	{
1112		xferp->mCallbackResult = result_code;
1113		xferp->processEOF();
1114		removeXfer(xferp, &mReceiveList);
1115		startPendingDownloads();
1116	}
1117}
1118
1119///////////////////////////////////////////////////////////
1120
1121void LLXferManager::startPendingDownloads()
1122{
1123	// This method goes through the list, and starts pending
1124	// operations until active downloads == mMaxIncomingXfers. I copy
1125	// the pending xfers into a temporary data structure because the
1126	// xfers are stored as an intrusive linked list where older
1127	// requests get pushed toward the back. Thus, if we didn't do a
1128	// stateful iteration, it would be possible for old requests to
1129	// never start.
1130	LLXfer* xferp = mReceiveList;
1131	std::list<LLXfer*> pending_downloads;
1132	S32 download_count = 0;
1133	S32 pending_count = 0;
1134	while(xferp)
1135	{
1136		if(xferp->mStatus == e_LL_XFER_PENDING)
1137		{
1138			++pending_count;
1139			pending_downloads.push_front(xferp);
1140		}
1141		else if(xferp->mStatus == e_LL_XFER_IN_PROGRESS)
1142		{
1143			++download_count;
1144		}
1145		xferp = xferp->mNext;
1146	}
1147
1148	S32 start_count = mMaxIncomingXfers - download_count;
1149
1150	lldebugs << "LLXferManager::startPendingDownloads() - XFER_IN_PROGRESS: "
1151			 << download_count << " XFER_PENDING: " << pending_count
1152			 << " startring " << llmin(start_count, pending_count) << llendl;
1153
1154	if((start_count > 0) && (pending_count > 0))
1155	{
1156		S32 result;
1157		for (std::list<LLXfer*>::iterator iter = pending_downloads.begin();
1158			 iter != pending_downloads.end(); ++iter)
1159		{
1160			xferp = *iter;
1161			if (start_count-- <= 0)
1162				break;
1163			result = xferp->startDownload();
1164			if(result)
1165			{
1166				xferp->abort(result);
1167				++start_count;
1168			}
1169		}
1170	}
1171}
1172
1173///////////////////////////////////////////////////////////
1174
1175void LLXferManager::addToList(LLXfer* xferp, LLXfer*& head, BOOL is_priority)
1176{
1177	if(is_priority)
1178	{
1179		xferp->mNext = NULL;
1180		LLXfer* next = head;
1181		if(next)
1182		{
1183			while(next->mNext)
1184			{
1185				next = next->mNext;
1186			}
1187			next->mNext = xferp;
1188		}
1189		else
1190		{
1191			head = xferp;
1192		}
1193	}
1194	else
1195	{
1196		xferp->mNext = head;
1197		head = xferp;
1198	}
1199}
1200
1201///////////////////////////////////////////////////////////
1202//  Globals and C routines
1203///////////////////////////////////////////////////////////
1204
1205LLXferManager *gXferManager = NULL;
1206
1207
1208void start_xfer_manager(LLVFS *vfs)
1209{
1210	gXferManager = new LLXferManager(vfs);
1211}
1212
1213void cleanup_xfer_manager()
1214{
1215	if (gXferManager)
1216	{
1217		delete(gXferManager);
1218		gXferManager = NULL;
1219	}
1220}
1221
1222void process_confirm_packet (LLMessageSystem *mesgsys, void **user_data)
1223{
1224	gXferManager->processConfirmation(mesgsys,user_data);
1225}
1226
1227void process_request_xfer(LLMessageSystem *mesgsys, void **user_data)
1228{
1229	gXferManager->processFileRequest(mesgsys,user_data);
1230}
1231
1232void continue_file_receive(LLMessageSystem *mesgsys, void **user_data)
1233{
1234#if LL_TEST_XFER_REXMIT
1235	if (ll_frand() > 0.05f)
1236	{
1237#endif
1238		gXferManager->processReceiveData(mesgsys,user_data);
1239#if LL_TEST_XFER_REXMIT
1240	}
1241	else
1242	{
1243		cout << "oops! dropped a xfer packet" << endl;
1244	}
1245#endif
1246}
1247
1248void process_abort_xfer(LLMessageSystem *mesgsys, void **user_data)
1249{
1250	gXferManager->processAbort(mesgsys,user_data);
1251}
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277