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