PageRenderTime 593ms CodeModel.GetById 97ms app.highlight 387ms RepoModel.GetById 74ms app.codeStats 0ms

/indra/llmessage/lltransfermanager.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1381 lines | 978 code | 213 blank | 190 comment | 137 complexity | 6eb764d6104a08f6bd1975547ebad0a1 MD5 | raw file
   1/** 
   2 * @file lltransfermanager.cpp
   3 * @brief Improved transfer mechanism for moving data through the
   4 * message system.
   5 *
   6 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
   7 * Second Life Viewer Source Code
   8 * Copyright (C) 2010, Linden Research, Inc.
   9 * 
  10 * This library is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU Lesser General Public
  12 * License as published by the Free Software Foundation;
  13 * version 2.1 of the License only.
  14 * 
  15 * This library is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18 * Lesser General Public License for more details.
  19 * 
  20 * You should have received a copy of the GNU Lesser General Public
  21 * License along with this library; if not, write to the Free Software
  22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  23 * 
  24 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  25 * $/LicenseInfo$
  26 */
  27
  28#include "linden_common.h"
  29
  30#include "lltransfermanager.h"
  31
  32#include "llerror.h"
  33#include "message.h"
  34#include "lldatapacker.h"
  35
  36#include "lltransfersourcefile.h"
  37#include "lltransfersourceasset.h"
  38#include "lltransfertargetfile.h"
  39#include "lltransfertargetvfile.h"
  40
  41const S32 MAX_PACKET_DATA_SIZE = 2048;
  42const S32 MAX_PARAMS_SIZE = 1024;
  43
  44LLTransferManager gTransferManager;
  45LLTransferSource::stype_scfunc_map LLTransferSource::sSourceCreateMap;
  46
  47//
  48// LLTransferManager implementation
  49//
  50
  51LLTransferManager::LLTransferManager() :
  52	mValid(FALSE)
  53{
  54	S32 i;
  55	for (i = 0; i < LLTTT_NUM_TYPES; i++)
  56	{
  57		mTransferBitsIn[i] = 0;
  58		mTransferBitsOut[i] = 0;
  59	}
  60}
  61
  62
  63LLTransferManager::~LLTransferManager()
  64{
  65	if (mValid)
  66	{
  67		llwarns << "LLTransferManager::~LLTransferManager - Should have been cleaned up by message system shutdown process" << llendl;
  68		cleanup();
  69	}
  70}
  71
  72
  73void LLTransferManager::init()
  74{
  75	if (mValid)
  76	{
  77		llerrs << "Double initializing LLTransferManager!" << llendl;
  78	}
  79	mValid = TRUE;
  80
  81	// Register message system handlers
  82	gMessageSystem->setHandlerFunc("TransferRequest", processTransferRequest, NULL);
  83	gMessageSystem->setHandlerFunc("TransferInfo", processTransferInfo, NULL);
  84	gMessageSystem->setHandlerFunc("TransferPacket", processTransferPacket, NULL);
  85	gMessageSystem->setHandlerFunc("TransferAbort", processTransferAbort, NULL);
  86}
  87
  88
  89void LLTransferManager::cleanup()
  90{
  91	mValid = FALSE;
  92
  93	host_tc_map::iterator iter;
  94	for (iter = mTransferConnections.begin(); iter != mTransferConnections.end(); iter++)
  95	{
  96		delete iter->second;
  97	}
  98	mTransferConnections.clear();
  99}
 100
 101
 102void LLTransferManager::updateTransfers()
 103{
 104	host_tc_map::iterator iter,cur;
 105
 106	iter = mTransferConnections.begin();
 107
 108	while (iter !=mTransferConnections.end())
 109	{
 110		cur = iter;
 111		iter++;
 112		cur->second->updateTransfers();
 113	}
 114}
 115
 116
 117void LLTransferManager::cleanupConnection(const LLHost &host)
 118{
 119	host_tc_map::iterator iter;
 120	iter = mTransferConnections.find(host);
 121	if (iter == mTransferConnections.end())
 122	{
 123		// This can happen legitimately if we've never done a transfer, and we're
 124		// cleaning up a circuit.
 125		//llwarns << "Cleaning up nonexistent transfer connection to " << host << llendl;
 126		return;
 127	}
 128	LLTransferConnection *connp = iter->second;
 129	delete connp;
 130	mTransferConnections.erase(iter);
 131}
 132
 133
 134LLTransferConnection *LLTransferManager::getTransferConnection(const LLHost &host)
 135{
 136	host_tc_map::iterator iter;
 137	iter = mTransferConnections.find(host);
 138	if (iter == mTransferConnections.end())
 139	{
 140		mTransferConnections[host] = new LLTransferConnection(host);
 141		return mTransferConnections[host];
 142	}
 143
 144	return iter->second;
 145}
 146
 147
 148LLTransferSourceChannel *LLTransferManager::getSourceChannel(const LLHost &host, const LLTransferChannelType type)
 149{
 150	LLTransferConnection *tcp = getTransferConnection(host);
 151	if (!tcp)
 152	{
 153		return NULL;
 154	}
 155	return tcp->getSourceChannel(type);
 156}
 157
 158
 159
 160LLTransferTargetChannel *LLTransferManager::getTargetChannel(const LLHost &host, const LLTransferChannelType type)
 161{
 162	LLTransferConnection *tcp = getTransferConnection(host);
 163	if (!tcp)
 164	{
 165		return NULL;
 166	}
 167	return tcp->getTargetChannel(type);
 168}
 169
 170// virtual
 171LLTransferSourceParams::~LLTransferSourceParams()
 172{ }
 173
 174
 175LLTransferSource *LLTransferManager::findTransferSource(const LLUUID &transfer_id)
 176{
 177	// This linear traversal could screw us later if we do lots of
 178	// searches for sources.  However, this ONLY happens right now
 179	// in asset transfer callbacks, so this should be relatively quick.
 180	host_tc_map::iterator iter;
 181	for (iter = mTransferConnections.begin(); iter != mTransferConnections.end(); iter++)
 182	{
 183		LLTransferConnection *tcp = iter->second;
 184		LLTransferConnection::tsc_iter sc_iter;
 185		for (sc_iter = tcp->mTransferSourceChannels.begin(); sc_iter != tcp->mTransferSourceChannels.end(); sc_iter++)
 186		{
 187			LLTransferSourceChannel *scp = *sc_iter;
 188			LLTransferSource *sourcep = scp->findTransferSource(transfer_id);
 189			if (sourcep)
 190			{
 191				return sourcep;
 192			}
 193		}
 194	}
 195
 196	return NULL;
 197}
 198
 199//
 200// Message handlers
 201//
 202
 203//static
 204void LLTransferManager::processTransferRequest(LLMessageSystem *msgp, void **)
 205{
 206	//llinfos << "LLTransferManager::processTransferRequest" << llendl;
 207
 208	LLUUID transfer_id;
 209	LLTransferSourceType source_type;
 210	LLTransferChannelType channel_type;
 211	F32 priority;
 212
 213	msgp->getUUID("TransferInfo", "TransferID", transfer_id);
 214	msgp->getS32("TransferInfo", "SourceType", (S32 &)source_type);
 215	msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
 216	msgp->getF32("TransferInfo", "Priority", priority);
 217
 218	LLTransferSourceChannel *tscp = gTransferManager.getSourceChannel(msgp->getSender(), channel_type);
 219
 220	if (!tscp)
 221	{
 222		llwarns << "Source channel not found" << llendl;
 223		return;
 224	}
 225
 226	if (tscp->findTransferSource(transfer_id))
 227	{
 228		llwarns << "Duplicate request for transfer " << transfer_id << ", aborting!" << llendl;
 229		return;
 230	}
 231
 232	S32 size = msgp->getSize("TransferInfo", "Params");
 233	if(size > MAX_PARAMS_SIZE)
 234	{
 235		llwarns << "LLTransferManager::processTransferRequest params too big."
 236			<< llendl;
 237		return;
 238	}
 239
 240	//llinfos << transfer_id << ":" << source_type << ":" << channel_type << ":" << priority << llendl;
 241	LLTransferSource* tsp = LLTransferSource::createSource(
 242		source_type,
 243		transfer_id,
 244		priority);
 245	if(!tsp)
 246	{
 247		llwarns << "LLTransferManager::processTransferRequest couldn't create"
 248			<< " transfer source!" << llendl;
 249		return;
 250	}
 251	U8 tmp[MAX_PARAMS_SIZE];
 252	msgp->getBinaryData("TransferInfo", "Params", tmp, size);
 253
 254	LLDataPackerBinaryBuffer dpb(tmp, MAX_PARAMS_SIZE);
 255	BOOL unpack_ok = tsp->unpackParams(dpb);
 256	if (!unpack_ok)
 257	{
 258		// This should only happen if the data is corrupt or
 259		// incorrectly packed.
 260		// *NOTE: We may want to call abortTransfer().
 261		llwarns << "LLTransferManager::processTransferRequest: bad parameters."
 262			<< llendl;
 263		delete tsp;
 264		return;
 265	}
 266
 267	tscp->addTransferSource(tsp);
 268	tsp->initTransfer();
 269}
 270
 271
 272//static
 273void LLTransferManager::processTransferInfo(LLMessageSystem *msgp, void **)
 274{
 275	//llinfos << "LLTransferManager::processTransferInfo" << llendl;
 276
 277	LLUUID transfer_id;
 278	LLTransferTargetType target_type;
 279	LLTransferChannelType channel_type;
 280	LLTSCode status;
 281	S32 size;
 282
 283	msgp->getUUID("TransferInfo", "TransferID", transfer_id);
 284	msgp->getS32("TransferInfo", "TargetType", (S32 &)target_type);
 285	msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
 286	msgp->getS32("TransferInfo", "Status", (S32 &)status);
 287	msgp->getS32("TransferInfo", "Size", size);
 288
 289	//llinfos << transfer_id << ":" << target_type<< ":" << channel_type << llendl;
 290	LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
 291	if (!ttcp)
 292	{
 293		llwarns << "Target channel not found" << llendl;
 294		// Should send a message to abort the transfer.
 295		return;
 296	}
 297
 298	LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
 299	if (!ttp)
 300	{
 301		llwarns << "TransferInfo for unknown transfer!  Not able to handle this yet!" << llendl;
 302		// This could happen if we're doing a push transfer, although to avoid confusion,
 303		// maybe it should be a different message.
 304		return;
 305	}
 306
 307	if (status != LLTS_OK)
 308	{
 309		llwarns << transfer_id << ": Non-ok status, cleaning up" << llendl;
 310		ttp->completionCallback(status);
 311		// Clean up the transfer.
 312		ttcp->deleteTransfer(ttp);
 313		return;
 314	}
 315
 316	// unpack the params
 317	S32 params_size = msgp->getSize("TransferInfo", "Params");
 318	if(params_size > MAX_PARAMS_SIZE)
 319	{
 320		llwarns << "LLTransferManager::processTransferInfo params too big."
 321			<< llendl;
 322		return;
 323	}
 324	else if(params_size > 0)
 325	{
 326		U8 tmp[MAX_PARAMS_SIZE];
 327		msgp->getBinaryData("TransferInfo", "Params", tmp, params_size);
 328		LLDataPackerBinaryBuffer dpb(tmp, MAX_PARAMS_SIZE);
 329		if (!ttp->unpackParams(dpb))
 330		{
 331			// This should only happen if the data is corrupt or
 332			// incorrectly packed.
 333			llwarns << "LLTransferManager::processTransferRequest: bad params."
 334				<< llendl;
 335			ttp->abortTransfer();
 336			ttcp->deleteTransfer(ttp);
 337			return;
 338		}
 339	}
 340
 341	//llinfos << "Receiving " << transfer_id << ", size " << size << " bytes" << llendl;
 342	ttp->setSize(size);
 343	ttp->setGotInfo(TRUE);
 344
 345	// OK, at this point we to handle any delayed transfer packets (which could happen
 346	// if this packet was lost)
 347
 348	// This is a lame cut and paste of code down below.  If we change the logic down there,
 349	// we HAVE to change the logic up here.
 350
 351	while (1)
 352	{
 353		S32 packet_id = 0;
 354		U8 tmp_data[MAX_PACKET_DATA_SIZE];
 355		// See if we've got any delayed packets
 356		packet_id = ttp->getNextPacketID();
 357		if (ttp->mDelayedPacketMap.find(packet_id) != ttp->mDelayedPacketMap.end())
 358		{
 359			// Perhaps this stuff should be inside a method in LLTransferPacket?
 360			// I'm too lazy to do it now, though.
 361// 			llinfos << "Playing back delayed packet " << packet_id << llendl;
 362			LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];
 363
 364			// This is somewhat inefficient, but avoids us having to duplicate
 365			// code between the off-the-wire and delayed paths.
 366			packet_id = packetp->mPacketID;
 367			size = packetp->mSize;
 368			if (size)
 369			{
 370				if ((packetp->mDatap != NULL) && (size<(S32)sizeof(tmp_data)))
 371				{
 372					memcpy(tmp_data, packetp->mDatap, size);	/*Flawfinder: ignore*/
 373				}
 374			}
 375			status = packetp->mStatus;
 376			ttp->mDelayedPacketMap.erase(packet_id);
 377			delete packetp;
 378		}
 379		else
 380		{
 381			// No matching delayed packet, we're done.
 382			break;
 383		}
 384
 385		LLTSCode ret_code = ttp->dataCallback(packet_id, tmp_data, size);
 386		if (ret_code == LLTS_OK)
 387		{
 388			ttp->setLastPacketID(packet_id);
 389		}
 390
 391		if (status != LLTS_OK)
 392		{
 393			if (status != LLTS_DONE)
 394			{
 395				llwarns << "LLTransferManager::processTransferInfo Error in playback!" << llendl;
 396			}
 397			else
 398			{
 399				llinfos << "LLTransferManager::processTransferInfo replay FINISHED for " << transfer_id << llendl;
 400			}
 401			// This transfer is done, either via error or not.
 402			ttp->completionCallback(status);
 403			ttcp->deleteTransfer(ttp);
 404			return;
 405		}
 406	}
 407}
 408
 409
 410//static
 411void LLTransferManager::processTransferPacket(LLMessageSystem *msgp, void **)
 412{
 413	//llinfos << "LLTransferManager::processTransferPacket" << llendl;
 414
 415	LLUUID transfer_id;
 416	LLTransferChannelType channel_type;
 417	S32 packet_id;
 418	LLTSCode status;
 419	S32 size;
 420	msgp->getUUID("TransferData", "TransferID", transfer_id);
 421	msgp->getS32("TransferData", "ChannelType", (S32 &)channel_type);
 422	msgp->getS32("TransferData", "Packet", packet_id);
 423	msgp->getS32("TransferData", "Status", (S32 &)status);
 424
 425	// Find the transfer associated with this packet.
 426	//llinfos << transfer_id << ":" << channel_type << llendl;
 427	LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
 428	if (!ttcp)
 429	{
 430		llwarns << "Target channel not found" << llendl;
 431		return;
 432	}
 433
 434	LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
 435	if (!ttp)
 436	{
 437		llwarns << "Didn't find matching transfer for " << transfer_id
 438			<< " processing packet " << packet_id
 439			<< " from " << msgp->getSender() << llendl;
 440		return;
 441	}
 442
 443	size = msgp->getSize("TransferData", "Data");
 444
 445	S32 msg_bytes = 0;
 446	if (msgp->getReceiveCompressedSize())
 447	{
 448		msg_bytes = msgp->getReceiveCompressedSize();
 449	}
 450	else
 451	{
 452		msg_bytes = msgp->getReceiveSize();
 453	}
 454	gTransferManager.addTransferBitsIn(ttcp->mChannelType, msg_bytes*8);
 455
 456	if ((size < 0) || (size > MAX_PACKET_DATA_SIZE))
 457	{
 458		llwarns << "Invalid transfer packet size " << size << llendl;
 459		return;
 460	}
 461
 462	U8 tmp_data[MAX_PACKET_DATA_SIZE];
 463	if (size > 0)
 464	{
 465		// Only pull the data out if the size is > 0
 466		msgp->getBinaryData("TransferData", "Data", tmp_data, size);
 467	}
 468
 469	if ((!ttp->gotInfo()) || (ttp->getNextPacketID() != packet_id))
 470	{
 471		// Put this on a list of packets to be delivered later.
 472		if(!ttp->addDelayedPacket(packet_id, status, tmp_data, size))
 473		{
 474			// Whoops - failed to add a delayed packet for some reason.
 475			llwarns << "Too many delayed packets processing transfer "
 476				<< transfer_id << " from " << msgp->getSender() << llendl;
 477			ttp->abortTransfer();
 478			ttcp->deleteTransfer(ttp);
 479			return;
 480		}
 481#if 0
 482		// Spammy!
 483		const S32 LL_TRANSFER_WARN_GAP = 10;
 484		if(!ttp->gotInfo())
 485		{
 486			llwarns << "Got data packet before information in transfer "
 487				<< transfer_id << " from " << msgp->getSender()
 488				<< ", got " << packet_id << llendl;
 489		}
 490		else if((packet_id - ttp->getNextPacketID()) > LL_TRANSFER_WARN_GAP)
 491		{
 492			llwarns << "Out of order packet in transfer " << transfer_id
 493				<< " from " << msgp->getSender() << ", got " << packet_id
 494				<< " expecting " << ttp->getNextPacketID() << llendl;
 495		}
 496#endif
 497		return;
 498	}
 499
 500	// Loop through this until we're done with all delayed packets
 501	
 502	//
 503	// NOTE: THERE IS A CUT AND PASTE OF THIS CODE IN THE TRANSFERINFO HANDLER
 504	// SO WE CAN PLAY BACK DELAYED PACKETS THERE!!!!!!!!!!!!!!!!!!!!!!!!!
 505	//
 506	BOOL done = FALSE;
 507	while (!done)
 508	{
 509		LLTSCode ret_code = ttp->dataCallback(packet_id, tmp_data, size);
 510		if (ret_code == LLTS_OK)
 511		{
 512			ttp->setLastPacketID(packet_id);
 513		}
 514
 515		if (status != LLTS_OK)
 516		{
 517			if (status != LLTS_DONE)
 518			{
 519				llwarns << "LLTransferManager::processTransferPacket Error in transfer!" << llendl;
 520			}
 521			else
 522			{
 523// 				llinfos << "LLTransferManager::processTransferPacket done for " << transfer_id << llendl;
 524			}
 525			// This transfer is done, either via error or not.
 526			ttp->completionCallback(status);
 527			ttcp->deleteTransfer(ttp);
 528			return;
 529		}
 530
 531		// See if we've got any delayed packets
 532		packet_id = ttp->getNextPacketID();
 533		if (ttp->mDelayedPacketMap.find(packet_id) != ttp->mDelayedPacketMap.end())
 534		{
 535			// Perhaps this stuff should be inside a method in LLTransferPacket?
 536			// I'm too lazy to do it now, though.
 537// 			llinfos << "Playing back delayed packet " << packet_id << llendl;
 538			LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];
 539
 540			// This is somewhat inefficient, but avoids us having to duplicate
 541			// code between the off-the-wire and delayed paths.
 542			packet_id = packetp->mPacketID;
 543			size = packetp->mSize;
 544			if (size)
 545			{
 546				if ((packetp->mDatap != NULL) && (size<(S32)sizeof(tmp_data)))
 547				{
 548					memcpy(tmp_data, packetp->mDatap, size);	/*Flawfinder: ignore*/
 549				}
 550			}
 551			status = packetp->mStatus;
 552			ttp->mDelayedPacketMap.erase(packet_id);
 553			delete packetp;
 554		}
 555		else
 556		{
 557			// No matching delayed packet, abort it.
 558			done = TRUE;
 559		}
 560	}
 561}
 562
 563
 564//static
 565void LLTransferManager::processTransferAbort(LLMessageSystem *msgp, void **)
 566{
 567	//llinfos << "LLTransferManager::processTransferPacket" << llendl;
 568
 569	LLUUID transfer_id;
 570	LLTransferChannelType channel_type;
 571	msgp->getUUID("TransferInfo", "TransferID", transfer_id);
 572	msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
 573
 574	// See if it's a target that we're trying to abort
 575	// Find the transfer associated with this packet.
 576	LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
 577	if (ttcp)
 578	{
 579		LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
 580		if (ttp)
 581		{
 582			ttp->abortTransfer();
 583			ttcp->deleteTransfer(ttp);
 584			return;
 585		}
 586	}
 587
 588	// Hmm, not a target.  Maybe it's a source.
 589	LLTransferSourceChannel *tscp = gTransferManager.getSourceChannel(msgp->getSender(), channel_type);
 590	if (tscp)
 591	{
 592		LLTransferSource *tsp = tscp->findTransferSource(transfer_id);
 593		if (tsp)
 594		{
 595			tsp->abortTransfer();
 596			tscp->deleteTransfer(tsp);
 597			return;
 598		}
 599	}
 600
 601	llwarns << "Couldn't find transfer " << transfer_id << " to abort!" << llendl;
 602}
 603
 604
 605//static
 606void LLTransferManager::reliablePacketCallback(void **user_data, S32 result)
 607{
 608	LLUUID *transfer_idp = (LLUUID *)user_data;
 609	if (result)
 610	{
 611		llwarns << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << llendl;
 612		LLTransferSource *tsp = gTransferManager.findTransferSource(*transfer_idp);
 613		if (tsp)
 614		{
 615			LLTransferSourceChannel *tscp = tsp->mChannelp;
 616			tsp->abortTransfer();
 617			tscp->deleteTransfer(tsp);
 618		}
 619	}
 620	delete transfer_idp;
 621}
 622
 623//
 624// LLTransferConnection implementation
 625//
 626
 627LLTransferConnection::LLTransferConnection(const LLHost &host)
 628{
 629	mHost = host;
 630}
 631
 632LLTransferConnection::~LLTransferConnection()
 633{
 634	tsc_iter itersc;
 635	for (itersc = mTransferSourceChannels.begin(); itersc != mTransferSourceChannels.end(); itersc++)
 636	{
 637		delete *itersc;
 638	}
 639	mTransferSourceChannels.clear();
 640
 641	ttc_iter itertc;
 642	for (itertc = mTransferTargetChannels.begin(); itertc != mTransferTargetChannels.end(); itertc++)
 643	{
 644		delete *itertc;
 645	}
 646	mTransferTargetChannels.clear();
 647}
 648
 649
 650void LLTransferConnection::updateTransfers()
 651{
 652	// Do stuff for source transfers (basically, send data out).
 653	tsc_iter iter, cur;
 654	iter = mTransferSourceChannels.begin();
 655
 656	while (iter !=mTransferSourceChannels.end())
 657	{
 658		cur = iter;
 659		iter++;
 660		(*cur)->updateTransfers();
 661	}
 662
 663	// Do stuff for target transfers
 664	// Primarily, we should be aborting transfers that are irredeemably broken
 665	// (large packet gaps that don't appear to be getting filled in, most likely)
 666	// Probably should NOT be doing timeouts for other things, as new priority scheme
 667	// means that a high priority transfer COULD block a transfer for a long time.
 668}
 669
 670
 671LLTransferSourceChannel *LLTransferConnection::getSourceChannel(const LLTransferChannelType channel_type)
 672{
 673	tsc_iter iter;
 674	for (iter = mTransferSourceChannels.begin(); iter != mTransferSourceChannels.end(); iter++)
 675	{
 676		if ((*iter)->getChannelType() == channel_type)
 677		{
 678			return *iter;
 679		}
 680	}
 681
 682	LLTransferSourceChannel *tscp = new LLTransferSourceChannel(channel_type, mHost);
 683	mTransferSourceChannels.push_back(tscp);
 684	return tscp;
 685}
 686
 687
 688LLTransferTargetChannel *LLTransferConnection::getTargetChannel(const LLTransferChannelType channel_type)
 689{
 690	ttc_iter iter;
 691	for (iter = mTransferTargetChannels.begin(); iter != mTransferTargetChannels.end(); iter++)
 692	{
 693		if ((*iter)->getChannelType() == channel_type)
 694		{
 695			return *iter;
 696		}
 697	}
 698
 699	LLTransferTargetChannel *ttcp = new LLTransferTargetChannel(channel_type, mHost);
 700	mTransferTargetChannels.push_back(ttcp);
 701	return ttcp;
 702}
 703
 704
 705//
 706// LLTransferSourceChannel implementation
 707//
 708
 709const S32 DEFAULT_PACKET_SIZE = 1000;
 710
 711
 712LLTransferSourceChannel::LLTransferSourceChannel(const LLTransferChannelType channel_type, const LLHost &host) :
 713	mChannelType(channel_type),
 714	mHost(host),
 715	mTransferSources(LLTransferSource::sSetPriority, LLTransferSource::sGetPriority),
 716	mThrottleID(TC_ASSET)
 717{
 718}
 719
 720
 721LLTransferSourceChannel::~LLTransferSourceChannel()
 722{
 723	LLPriQueueMap<LLTransferSource*>::pqm_iter iter =
 724		mTransferSources.mMap.begin();
 725	LLPriQueueMap<LLTransferSource*>::pqm_iter end =
 726		mTransferSources.mMap.end();
 727	for (; iter != end; ++iter)
 728	{
 729		// Just kill off all of the transfers
 730		(*iter).second->abortTransfer();
 731		delete iter->second;
 732	}
 733	mTransferSources.mMap.clear();
 734}
 735
 736void LLTransferSourceChannel::updatePriority(LLTransferSource *tsp, const F32 priority)
 737{
 738	mTransferSources.reprioritize(priority, tsp);
 739}
 740
 741void LLTransferSourceChannel::updateTransfers()
 742{
 743	// Actually, this should do the following:
 744	// Decide if we can actually send data.
 745	// If so, update priorities so we know who gets to send it.
 746	// Send data from the sources, while updating until we've sent our throttle allocation.
 747
 748	LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(getHost());
 749	if (!cdp)
 750	{
 751		return;
 752	}
 753
 754	if (cdp->isBlocked())
 755	{
 756		// *NOTE: We need to make sure that the throttle bits
 757		// available gets reset.
 758
 759		// We DON'T want to send any packets if they're blocked, they'll just end up
 760		// piling up on the other end.
 761		//llwarns << "Blocking transfers due to blocked circuit for " << getHost() << llendl;
 762		return;
 763	}
 764
 765	const S32 throttle_id = mThrottleID;
 766
 767	LLThrottleGroup &tg = cdp->getThrottleGroup();
 768
 769	if (tg.checkOverflow(throttle_id, 0.f))
 770	{
 771		return;
 772	}
 773
 774	LLPriQueueMap<LLTransferSource *>::pqm_iter iter, next;
 775
 776	BOOL done = FALSE;
 777	for (iter = mTransferSources.mMap.begin(); (iter != mTransferSources.mMap.end()) && !done;)
 778	{
 779		//llinfos << "LLTransferSourceChannel::updateTransfers()" << llendl;
 780		// Do stuff. 
 781		next = iter;
 782		next++;
 783
 784		LLTransferSource *tsp = iter->second;
 785		U8 *datap = NULL;
 786		S32 data_size = 0;
 787		BOOL delete_data = FALSE;
 788		S32 packet_id = 0;
 789		S32 sent_bytes = 0;
 790		LLTSCode status = LLTS_OK;
 791
 792		// Get the packetID for the next packet that we're transferring.
 793		packet_id = tsp->getNextPacketID();
 794		status = tsp->dataCallback(packet_id, DEFAULT_PACKET_SIZE, &datap, data_size, delete_data);
 795
 796		if (status == LLTS_SKIP)
 797		{
 798			// We don't have any data, but we're not done, just go on.
 799			// This will presumably be used for streaming or async transfers that
 800			// are stalled waiting for data from another source.
 801			iter=next;
 802			continue;
 803		}
 804
 805		LLUUID *cb_uuid = new LLUUID(tsp->getID());
 806		LLUUID transaction_id = tsp->getID();
 807
 808		// Send the data now, even if it's an error.
 809		// The status code will tell the other end what to do.
 810		gMessageSystem->newMessage("TransferPacket");
 811		gMessageSystem->nextBlock("TransferData");
 812		gMessageSystem->addUUID("TransferID", tsp->getID());
 813		gMessageSystem->addS32("ChannelType", getChannelType());
 814		gMessageSystem->addS32("Packet", packet_id);	// HACK!  Need to put in a REAL packet id
 815		gMessageSystem->addS32("Status", status);
 816		gMessageSystem->addBinaryData("Data", datap, data_size);
 817		sent_bytes = gMessageSystem->getCurrentSendTotal();
 818		gMessageSystem->sendReliable(getHost(), LL_DEFAULT_RELIABLE_RETRIES, TRUE, 0.f,
 819									 LLTransferManager::reliablePacketCallback, (void**)cb_uuid);
 820
 821		// Do bookkeeping for the throttle
 822		done = tg.throttleOverflow(throttle_id, sent_bytes*8.f);
 823		gTransferManager.addTransferBitsOut(mChannelType, sent_bytes*8);
 824
 825		// Clean up our temporary data.
 826		if (delete_data)
 827		{
 828			delete[] datap;
 829			datap = NULL;
 830		}
 831
 832		if (findTransferSource(transaction_id) == NULL)
 833		{
 834			//Warning!  In the case of an aborted transfer, the sendReliable call above calls 
 835			//AbortTransfer which in turn calls deleteTransfer which means that somewhere way 
 836			//down the chain our current iter can get invalidated resulting in an infrequent
 837			//sim crash.  This check gets us to a valid transfer source in this event.
 838			iter=next;
 839			continue;
 840		}
 841
 842		// Update the packet counter
 843		tsp->setLastPacketID(packet_id);
 844
 845		switch (status)
 846		{
 847		case LLTS_OK:
 848			// We're OK, don't need to do anything.  Keep sending data.
 849			break;
 850		case LLTS_ERROR:
 851			llwarns << "Error in transfer dataCallback!" << llendl;
 852			// fall through
 853		case LLTS_DONE:
 854			// We need to clean up this transfer source.
 855			//llinfos << "LLTransferSourceChannel::updateTransfers() " << tsp->getID() << " done" << llendl;
 856			tsp->completionCallback(status);
 857			delete tsp;
 858			
 859			mTransferSources.mMap.erase(iter);
 860			iter = next;
 861			break;
 862		default:
 863			llerrs << "Unknown transfer error code!" << llendl;
 864		}
 865
 866		// At this point, we should do priority adjustment (since some transfers like
 867		// streaming transfers will adjust priority based on how much they've sent and time,
 868		// but I'm not going to bother yet. - djs.
 869	}
 870}
 871
 872
 873void LLTransferSourceChannel::addTransferSource(LLTransferSource *sourcep)
 874{
 875	sourcep->mChannelp = this;
 876	mTransferSources.push(sourcep->getPriority(), sourcep);
 877}
 878
 879
 880LLTransferSource *LLTransferSourceChannel::findTransferSource(const LLUUID &transfer_id)
 881{
 882	LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
 883	for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
 884	{
 885		LLTransferSource *tsp = iter->second;
 886		if (tsp->getID() == transfer_id)
 887		{
 888			return tsp;
 889		}
 890	}
 891	return NULL;
 892}
 893
 894
 895BOOL LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp)
 896{
 897
 898	LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
 899	for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
 900	{
 901		if (iter->second == tsp)
 902		{
 903			delete tsp;
 904			mTransferSources.mMap.erase(iter);
 905			return TRUE;
 906		}
 907	}
 908
 909	llerrs << "Unable to find transfer source to delete!" << llendl;
 910	return FALSE;
 911}
 912
 913
 914//
 915// LLTransferTargetChannel implementation
 916//
 917
 918LLTransferTargetChannel::LLTransferTargetChannel(const LLTransferChannelType channel_type, const LLHost &host) :
 919	mChannelType(channel_type),
 920	mHost(host)
 921{
 922}
 923
 924LLTransferTargetChannel::~LLTransferTargetChannel()
 925{
 926	tt_iter iter;
 927	for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
 928	{
 929		// Abort all of the current transfers
 930		(*iter)->abortTransfer();
 931		delete *iter;
 932	}
 933	mTransferTargets.clear();
 934}
 935
 936
 937void LLTransferTargetChannel::requestTransfer(
 938	const LLTransferSourceParams& source_params,
 939	const LLTransferTargetParams& target_params,
 940	const F32 priority)
 941{
 942	LLUUID id;
 943	id.generate();
 944	LLTransferTarget* ttp = LLTransferTarget::createTarget(
 945		target_params.getType(),
 946		id,
 947		source_params.getType());
 948	if (!ttp)
 949	{
 950		llwarns << "LLTransferManager::requestTransfer aborting due to target creation failure!" << llendl;
 951		return;
 952	}
 953
 954	ttp->applyParams(target_params);
 955	addTransferTarget(ttp);
 956
 957	sendTransferRequest(ttp, source_params, priority);
 958}
 959
 960
 961void LLTransferTargetChannel::sendTransferRequest(LLTransferTarget *targetp,
 962												  const LLTransferSourceParams &params,
 963												  const F32 priority)
 964{
 965	//
 966	// Pack the message with data which explains how to get the source, and
 967	// send it off to the source for this channel.
 968	//
 969	llassert(targetp);
 970	llassert(targetp->getChannel() == this);
 971
 972	gMessageSystem->newMessage("TransferRequest");
 973	gMessageSystem->nextBlock("TransferInfo");
 974	gMessageSystem->addUUID("TransferID", targetp->getID());
 975	gMessageSystem->addS32("SourceType", params.getType());
 976	gMessageSystem->addS32("ChannelType", getChannelType());
 977	gMessageSystem->addF32("Priority", priority);
 978
 979	U8 tmp[MAX_PARAMS_SIZE];
 980	LLDataPackerBinaryBuffer dp(tmp, MAX_PARAMS_SIZE);
 981	params.packParams(dp);
 982	S32 len = dp.getCurrentSize();
 983	gMessageSystem->addBinaryData("Params", tmp, len);
 984
 985	gMessageSystem->sendReliable(mHost);
 986}
 987
 988
 989void LLTransferTargetChannel::addTransferTarget(LLTransferTarget *targetp)
 990{
 991	targetp->mChannelp = this;
 992	mTransferTargets.push_back(targetp);
 993}
 994
 995
 996LLTransferTarget *LLTransferTargetChannel::findTransferTarget(const LLUUID &transfer_id)
 997{
 998	tt_iter iter;
 999	for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
1000	{
1001		LLTransferTarget *ttp = *iter;
1002		if (ttp->getID() == transfer_id)
1003		{
1004			return ttp;
1005		}
1006	}
1007	return NULL;
1008}
1009
1010
1011BOOL LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp)
1012{
1013	tt_iter iter;
1014	for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
1015	{
1016		if (*iter == ttp)
1017		{
1018			delete ttp;
1019			mTransferTargets.erase(iter);
1020			return TRUE;
1021		}
1022	}
1023
1024	llerrs << "Unable to find transfer target to delete!" << llendl;
1025	return FALSE;
1026}
1027
1028
1029//
1030// LLTransferSource implementation
1031//
1032
1033LLTransferSource::LLTransferSource(const LLTransferSourceType type,
1034								   const LLUUID &transfer_id,
1035								   const F32 priority) :
1036	mType(type),
1037	mID(transfer_id),
1038	mChannelp(NULL),
1039	mPriority(priority),
1040	mSize(0),
1041	mLastPacketID(-1)
1042{
1043	setPriority(priority);
1044}
1045
1046
1047LLTransferSource::~LLTransferSource()
1048{
1049	// No actual cleanup of the transfer is done here, this is purely for
1050	// memory cleanup.  The completionCallback is guaranteed to get called
1051	// before this happens.
1052}
1053
1054
1055void LLTransferSource::sendTransferStatus(LLTSCode status)
1056{
1057	gMessageSystem->newMessage("TransferInfo");
1058	gMessageSystem->nextBlock("TransferInfo");
1059	gMessageSystem->addUUID("TransferID", getID());
1060	gMessageSystem->addS32("TargetType", LLTTT_UNKNOWN);
1061	gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
1062	gMessageSystem->addS32("Status", status);
1063	gMessageSystem->addS32("Size", mSize);
1064	U8 tmp[MAX_PARAMS_SIZE];
1065	LLDataPackerBinaryBuffer dp(tmp, MAX_PARAMS_SIZE);
1066	packParams(dp);
1067	S32 len = dp.getCurrentSize();
1068	gMessageSystem->addBinaryData("Params", tmp, len);
1069	gMessageSystem->sendReliable(mChannelp->getHost());
1070
1071	// Abort if there was as asset system issue.
1072	if (status != LLTS_OK)
1073	{
1074		completionCallback(status);
1075		mChannelp->deleteTransfer(this);
1076	}
1077}
1078
1079
1080// This should never be called directly, the transfer manager is responsible for
1081// aborting the transfer from the channel.  I might want to rethink this in the
1082// future, though.
1083void LLTransferSource::abortTransfer()
1084{
1085	// Send a message down, call the completion callback
1086	llinfos << "LLTransferSource::Aborting transfer " << getID() << " to " << mChannelp->getHost() << llendl;
1087	gMessageSystem->newMessage("TransferAbort");
1088	gMessageSystem->nextBlock("TransferInfo");
1089	gMessageSystem->addUUID("TransferID", getID());
1090	gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
1091	gMessageSystem->sendReliable(mChannelp->getHost());
1092
1093	completionCallback(LLTS_ABORT);
1094}
1095
1096
1097//static
1098void LLTransferSource::registerSourceType(const LLTransferSourceType stype, LLTransferSourceCreateFunc func)
1099{
1100	if (sSourceCreateMap.count(stype))
1101	{
1102		// Disallow changing what class handles a source type
1103		// Unclear when you would want to do this, and whether it would work.
1104		llerrs << "Reregistering source type " << stype << llendl;
1105	}
1106	else
1107	{
1108		sSourceCreateMap[stype] = func;
1109	}
1110}
1111
1112//static
1113LLTransferSource *LLTransferSource::createSource(const LLTransferSourceType stype,
1114												 const LLUUID &id,
1115												 const F32 priority)
1116{
1117	switch (stype)
1118	{
1119	// *NOTE: The source file transfer mechanism is highly insecure and could
1120	// lead to easy exploitation of a server process.
1121	// I have removed all uses of it from the codebase. Phoenix.
1122	// 
1123	//case LLTST_FILE:
1124	//	return new LLTransferSourceFile(id, priority);
1125	case LLTST_ASSET:
1126		return new LLTransferSourceAsset(id, priority);
1127	default:
1128		{
1129			if (!sSourceCreateMap.count(stype))
1130			{
1131				// Use the callback to create the source type if it's not there.
1132				llwarns << "Unknown transfer source type: " << stype << llendl;
1133				return NULL;
1134			}
1135			return (sSourceCreateMap[stype])(id, priority);
1136		}
1137	}
1138}
1139
1140
1141// static
1142void LLTransferSource::sSetPriority(LLTransferSource *&tsp, const F32 priority)
1143{
1144	tsp->setPriority(priority);
1145}
1146
1147
1148// static
1149F32 LLTransferSource::sGetPriority(LLTransferSource *&tsp)
1150{
1151	return tsp->getPriority();
1152}
1153
1154
1155//
1156// LLTransferPacket implementation
1157//
1158
1159LLTransferPacket::LLTransferPacket(const S32 packet_id, const LLTSCode status, const U8 *datap, const S32 size) :
1160	mPacketID(packet_id),
1161	mStatus(status),
1162	mDatap(NULL),
1163	mSize(size)
1164{
1165	if (size == 0)
1166	{
1167		return;
1168	}
1169	
1170	mDatap = new U8[size];
1171	if (mDatap != NULL)
1172	{
1173		memcpy(mDatap, datap, size);	/*Flawfinder: ignore*/
1174	}
1175}
1176
1177LLTransferPacket::~LLTransferPacket()
1178{
1179	delete[] mDatap;
1180}
1181
1182//
1183// LLTransferTarget implementation
1184//
1185
1186LLTransferTarget::LLTransferTarget(
1187	LLTransferTargetType type,
1188	const LLUUID& transfer_id,
1189	LLTransferSourceType source_type) : 
1190	mType(type),
1191	mSourceType(source_type),
1192	mID(transfer_id),
1193	mChannelp(NULL),
1194	mGotInfo(FALSE),
1195	mSize(0),
1196	mLastPacketID(-1)
1197{
1198}
1199
1200LLTransferTarget::~LLTransferTarget()
1201{
1202	// No actual cleanup of the transfer is done here, this is purely for
1203	// memory cleanup.  The completionCallback is guaranteed to get called
1204	// before this happens.
1205	tpm_iter iter;
1206	for (iter = mDelayedPacketMap.begin(); iter != mDelayedPacketMap.end(); iter++)
1207	{
1208		delete iter->second;
1209	}
1210	mDelayedPacketMap.clear();
1211}
1212
1213// This should never be called directly, the transfer manager is responsible for
1214// aborting the transfer from the channel.  I might want to rethink this in the
1215// future, though.
1216void LLTransferTarget::abortTransfer()
1217{
1218	// Send a message up, call the completion callback
1219	llinfos << "LLTransferTarget::Aborting transfer " << getID() << " from " << mChannelp->getHost() << llendl;
1220	gMessageSystem->newMessage("TransferAbort");
1221	gMessageSystem->nextBlock("TransferInfo");
1222	gMessageSystem->addUUID("TransferID", getID());
1223	gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
1224	gMessageSystem->sendReliable(mChannelp->getHost());
1225
1226	completionCallback(LLTS_ABORT);
1227}
1228
1229bool LLTransferTarget::addDelayedPacket(
1230	const S32 packet_id,
1231	const LLTSCode status,
1232	U8* datap,
1233	const S32 size)
1234{
1235	const transfer_packet_map::size_type LL_MAX_DELAYED_PACKETS = 100;
1236	if(mDelayedPacketMap.size() > LL_MAX_DELAYED_PACKETS)
1237	{
1238		// too many delayed packets
1239		return false;
1240	}
1241
1242	LLTransferPacket* tpp = new LLTransferPacket(
1243		packet_id,
1244		status,
1245		datap,
1246		size);
1247
1248#ifdef _DEBUG
1249	if (mDelayedPacketMap.find(packet_id) != mDelayedPacketMap.end())
1250	{
1251		llerrs << "Packet ALREADY in delayed packet map!" << llendl;
1252	}
1253#endif
1254
1255	mDelayedPacketMap[packet_id] = tpp;
1256	return true;
1257}
1258
1259
1260LLTransferTarget* LLTransferTarget::createTarget(
1261	LLTransferTargetType type,
1262	const LLUUID& id,
1263	LLTransferSourceType source_type)
1264{
1265	switch (type)
1266	{
1267	case LLTTT_FILE:
1268		return new LLTransferTargetFile(id, source_type);
1269	case LLTTT_VFILE:
1270		return new LLTransferTargetVFile(id, source_type);
1271	default:
1272		llwarns << "Unknown transfer target type: " << type << llendl;
1273		return NULL;
1274	}
1275}
1276
1277
1278LLTransferSourceParamsInvItem::LLTransferSourceParamsInvItem() : LLTransferSourceParams(LLTST_SIM_INV_ITEM), mAssetType(LLAssetType::AT_NONE)
1279{
1280}
1281
1282
1283void LLTransferSourceParamsInvItem::setAgentSession(const LLUUID &agent_id, const LLUUID &session_id)
1284{
1285	mAgentID = agent_id;
1286	mSessionID = session_id;
1287}
1288
1289
1290void LLTransferSourceParamsInvItem::setInvItem(const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id)
1291{
1292	mOwnerID = owner_id;
1293	mTaskID = task_id;
1294	mItemID = item_id;
1295}
1296
1297
1298void LLTransferSourceParamsInvItem::setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type)
1299{
1300	mAssetID = asset_id;
1301	mAssetType = asset_type;
1302}
1303
1304
1305void LLTransferSourceParamsInvItem::packParams(LLDataPacker &dp) const
1306{
1307	lldebugs << "LLTransferSourceParamsInvItem::packParams()" << llendl;
1308	dp.packUUID(mAgentID, "AgentID");
1309	dp.packUUID(mSessionID, "SessionID");
1310	dp.packUUID(mOwnerID, "OwnerID");
1311	dp.packUUID(mTaskID, "TaskID");
1312	dp.packUUID(mItemID, "ItemID");
1313	dp.packUUID(mAssetID, "AssetID");
1314	dp.packS32(mAssetType, "AssetType");
1315}
1316
1317
1318BOOL LLTransferSourceParamsInvItem::unpackParams(LLDataPacker &dp)
1319{
1320	S32 tmp_at;
1321
1322	dp.unpackUUID(mAgentID, "AgentID");
1323	dp.unpackUUID(mSessionID, "SessionID");
1324	dp.unpackUUID(mOwnerID, "OwnerID");
1325	dp.unpackUUID(mTaskID, "TaskID");
1326	dp.unpackUUID(mItemID, "ItemID");
1327	dp.unpackUUID(mAssetID, "AssetID");
1328	dp.unpackS32(tmp_at, "AssetType");
1329
1330	mAssetType = (LLAssetType::EType)tmp_at;
1331
1332	return TRUE;
1333}
1334
1335LLTransferSourceParamsEstate::LLTransferSourceParamsEstate() :
1336	LLTransferSourceParams(LLTST_SIM_ESTATE),
1337	mEstateAssetType(ET_NONE),
1338	mAssetType(LLAssetType::AT_NONE)
1339{
1340}
1341
1342void LLTransferSourceParamsEstate::setAgentSession(const LLUUID &agent_id, const LLUUID &session_id)
1343{
1344	mAgentID = agent_id;
1345	mSessionID = session_id;
1346}
1347
1348void LLTransferSourceParamsEstate::setEstateAssetType(const EstateAssetType etype)
1349{
1350	mEstateAssetType = etype;
1351}
1352
1353void LLTransferSourceParamsEstate::setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type)
1354{
1355	mAssetID = asset_id;
1356	mAssetType = asset_type;
1357}
1358
1359void LLTransferSourceParamsEstate::packParams(LLDataPacker &dp) const
1360{
1361	dp.packUUID(mAgentID, "AgentID");
1362	// *NOTE: We do not want to pass the session id from the server to
1363	// the client, but I am not sure if anyone expects this value to
1364	// be set on the client.
1365	dp.packUUID(mSessionID, "SessionID");
1366	dp.packS32(mEstateAssetType, "EstateAssetType");
1367}
1368
1369
1370BOOL LLTransferSourceParamsEstate::unpackParams(LLDataPacker &dp)
1371{
1372	S32 tmp_et;
1373
1374	dp.unpackUUID(mAgentID, "AgentID");
1375	dp.unpackUUID(mSessionID, "SessionID");
1376	dp.unpackS32(tmp_et, "EstateAssetType");
1377
1378	mEstateAssetType = (EstateAssetType)tmp_et;
1379
1380	return TRUE;
1381}