lltransfermanager.cpp

Go to the documentation of this file.
00001 
00033 #include "linden_common.h"
00034 
00035 #include "lltransfermanager.h"
00036 
00037 #include "llerror.h"
00038 #include "message.h"
00039 #include "lldatapacker.h"
00040 
00041 #include "lltransfersourcefile.h"
00042 #include "lltransfersourceasset.h"
00043 #include "lltransfertargetfile.h"
00044 #include "lltransfertargetvfile.h"
00045 
00046 const S32 MAX_PACKET_DATA_SIZE = 2048;
00047 const S32 MAX_PARAMS_SIZE = 1024;
00048 
00049 LLTransferManager gTransferManager;
00050 LLTransferSource::stype_scfunc_map LLTransferSource::sSourceCreateMap;
00051 
00052 //
00053 // LLTransferManager implementation
00054 //
00055 
00056 LLTransferManager::LLTransferManager() :
00057         mValid(FALSE)
00058 {
00059         S32 i;
00060         for (i = 0; i < LLTTT_NUM_TYPES; i++)
00061         {
00062                 mTransferBitsIn[i] = 0;
00063                 mTransferBitsOut[i] = 0;
00064         }
00065 }
00066 
00067 
00068 LLTransferManager::~LLTransferManager()
00069 {
00070         if (mValid)
00071         {
00072                 llwarns << "LLTransferManager::~LLTransferManager - Should have been cleaned up by message system shutdown process" << llendl;
00073                 cleanup();
00074         }
00075 }
00076 
00077 
00078 void LLTransferManager::init()
00079 {
00080         if (mValid)
00081         {
00082                 llerrs << "Double initializing LLTransferManager!" << llendl;
00083         }
00084         mValid = TRUE;
00085 
00086         // Register message system handlers
00087         gMessageSystem->setHandlerFunc("TransferRequest", processTransferRequest, NULL);
00088         gMessageSystem->setHandlerFunc("TransferInfo", processTransferInfo, NULL);
00089         gMessageSystem->setHandlerFunc("TransferPacket", processTransferPacket, NULL);
00090         gMessageSystem->setHandlerFunc("TransferAbort", processTransferAbort, NULL);
00091 }
00092 
00093 
00094 void LLTransferManager::cleanup()
00095 {
00096         mValid = FALSE;
00097 
00098         host_tc_map::iterator iter;
00099         for (iter = mTransferConnections.begin(); iter != mTransferConnections.end(); iter++)
00100         {
00101                 delete iter->second;
00102         }
00103         mTransferConnections.clear();
00104 }
00105 
00106 
00107 void LLTransferManager::updateTransfers()
00108 {
00109         host_tc_map::iterator iter;
00110         for (iter = mTransferConnections.begin(); iter != mTransferConnections.end(); iter++)
00111         {
00112                 iter->second->updateTransfers();
00113         }
00114 }
00115 
00116 
00117 void LLTransferManager::cleanupConnection(const LLHost &host)
00118 {
00119         host_tc_map::iterator iter;
00120         iter = mTransferConnections.find(host);
00121         if (iter == mTransferConnections.end())
00122         {
00123                 // This can happen legitimately if we've never done a transfer, and we're
00124                 // cleaning up a circuit.
00125                 //llwarns << "Cleaning up nonexistent transfer connection to " << host << llendl;
00126                 return;
00127         }
00128         LLTransferConnection *connp = iter->second;
00129         delete connp;
00130         mTransferConnections.erase(iter);
00131 }
00132 
00133 
00134 LLTransferConnection *LLTransferManager::getTransferConnection(const LLHost &host)
00135 {
00136         host_tc_map::iterator iter;
00137         iter = mTransferConnections.find(host);
00138         if (iter == mTransferConnections.end())
00139         {
00140                 mTransferConnections[host] = new LLTransferConnection(host);
00141                 return mTransferConnections[host];
00142         }
00143 
00144         return iter->second;
00145 }
00146 
00147 
00148 LLTransferSourceChannel *LLTransferManager::getSourceChannel(const LLHost &host, const LLTransferChannelType type)
00149 {
00150         LLTransferConnection *tcp = getTransferConnection(host);
00151         if (!tcp)
00152         {
00153                 return NULL;
00154         }
00155         return tcp->getSourceChannel(type);
00156 }
00157 
00158 
00159 
00160 LLTransferTargetChannel *LLTransferManager::getTargetChannel(const LLHost &host, const LLTransferChannelType type)
00161 {
00162         LLTransferConnection *tcp = getTransferConnection(host);
00163         if (!tcp)
00164         {
00165                 return NULL;
00166         }
00167         return tcp->getTargetChannel(type);
00168 }
00169 
00170 // virtual
00171 LLTransferSourceParams::~LLTransferSourceParams()
00172 { }
00173 
00174 
00175 LLTransferSource *LLTransferManager::findTransferSource(const LLUUID &transfer_id)
00176 {
00177         // This linear traversal could screw us later if we do lots of
00178         // searches for sources.  However, this ONLY happens right now
00179         // in asset transfer callbacks, so this should be relatively quick.
00180         host_tc_map::iterator iter;
00181         for (iter = mTransferConnections.begin(); iter != mTransferConnections.end(); iter++)
00182         {
00183                 LLTransferConnection *tcp = iter->second;
00184                 LLTransferConnection::tsc_iter sc_iter;
00185                 for (sc_iter = tcp->mTransferSourceChannels.begin(); sc_iter != tcp->mTransferSourceChannels.end(); sc_iter++)
00186                 {
00187                         LLTransferSourceChannel *scp = *sc_iter;
00188                         LLTransferSource *sourcep = scp->findTransferSource(transfer_id);
00189                         if (sourcep)
00190                         {
00191                                 return sourcep;
00192                         }
00193                 }
00194         }
00195 
00196         return NULL;
00197 }
00198 
00199 //
00200 // Message handlers
00201 //
00202 
00203 //static
00204 void LLTransferManager::processTransferRequest(LLMessageSystem *msgp, void **)
00205 {
00206         //llinfos << "LLTransferManager::processTransferRequest" << llendl;
00207 
00208         LLUUID transfer_id;
00209         LLTransferSourceType source_type;
00210         LLTransferChannelType channel_type;
00211         F32 priority;
00212 
00213         msgp->getUUID("TransferInfo", "TransferID", transfer_id);
00214         msgp->getS32("TransferInfo", "SourceType", (S32 &)source_type);
00215         msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
00216         msgp->getF32("TransferInfo", "Priority", priority);
00217 
00218         LLTransferSourceChannel *tscp = gTransferManager.getSourceChannel(msgp->getSender(), channel_type);
00219 
00220         if (!tscp)
00221         {
00222                 llwarns << "Source channel not found" << llendl;
00223                 return;
00224         }
00225 
00226         if (tscp->findTransferSource(transfer_id))
00227         {
00228                 llwarns << "Duplicate request for transfer " << transfer_id << ", aborting!" << llendl;
00229                 return;
00230         }
00231 
00232         S32 size = msgp->getSize("TransferInfo", "Params");
00233         if(size > MAX_PARAMS_SIZE)
00234         {
00235                 llwarns << "LLTransferManager::processTransferRequest params too big."
00236                         << llendl;
00237                 return;
00238         }
00239 
00240         //llinfos << transfer_id << ":" << source_type << ":" << channel_type << ":" << priority << llendl;
00241         LLTransferSource* tsp = LLTransferSource::createSource(
00242                 source_type,
00243                 transfer_id,
00244                 priority);
00245         if(!tsp)
00246         {
00247                 llwarns << "LLTransferManager::processTransferRequest couldn't create"
00248                         << " transfer source!" << llendl;
00249                 return;
00250         }
00251         U8 tmp[MAX_PARAMS_SIZE];
00252         msgp->getBinaryData("TransferInfo", "Params", tmp, size);
00253 
00254         LLDataPackerBinaryBuffer dpb(tmp, MAX_PARAMS_SIZE);
00255         BOOL unpack_ok = tsp->unpackParams(dpb);
00256         if (!unpack_ok)
00257         {
00258                 // This should only happen if the data is corrupt or
00259                 // incorrectly packed.
00260                 // *NOTE: We may want to call abortTransfer().
00261                 llwarns << "LLTransferManager::processTransferRequest: bad parameters."
00262                         << llendl;
00263                 delete tsp;
00264                 return;
00265         }
00266 
00267         tscp->addTransferSource(tsp);
00268         tsp->initTransfer();
00269 }
00270 
00271 
00272 //static
00273 void LLTransferManager::processTransferInfo(LLMessageSystem *msgp, void **)
00274 {
00275         //llinfos << "LLTransferManager::processTransferInfo" << llendl;
00276 
00277         LLUUID transfer_id;
00278         LLTransferTargetType target_type;
00279         LLTransferChannelType channel_type;
00280         LLTSCode status;
00281         S32 size;
00282 
00283         msgp->getUUID("TransferInfo", "TransferID", transfer_id);
00284         msgp->getS32("TransferInfo", "TargetType", (S32 &)target_type);
00285         msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
00286         msgp->getS32("TransferInfo", "Status", (S32 &)status);
00287         msgp->getS32("TransferInfo", "Size", size);
00288 
00289         //llinfos << transfer_id << ":" << target_type<< ":" << channel_type << llendl;
00290         LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
00291         if (!ttcp)
00292         {
00293                 llwarns << "Target channel not found" << llendl;
00294                 // Should send a message to abort the transfer.
00295                 return;
00296         }
00297 
00298         LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
00299         if (!ttp)
00300         {
00301                 llwarns << "TransferInfo for unknown transfer!  Not able to handle this yet!" << llendl;
00302                 // This could happen if we're doing a push transfer, although to avoid confusion,
00303                 // maybe it should be a different message.
00304                 return;
00305         }
00306 
00307         if (status != LLTS_OK)
00308         {
00309                 llwarns << transfer_id << ": Non-ok status, cleaning up" << llendl;
00310                 ttp->completionCallback(status);
00311                 // Clean up the transfer.
00312                 ttcp->deleteTransfer(ttp);
00313                 return;
00314         }
00315 
00316         // unpack the params
00317         S32 params_size = msgp->getSize("TransferInfo", "Params");
00318         if(params_size > MAX_PARAMS_SIZE)
00319         {
00320                 llwarns << "LLTransferManager::processTransferInfo params too big."
00321                         << llendl;
00322                 return;
00323         }
00324         else if(params_size > 0)
00325         {
00326                 U8 tmp[MAX_PARAMS_SIZE];
00327                 msgp->getBinaryData("TransferInfo", "Params", tmp, params_size);
00328                 LLDataPackerBinaryBuffer dpb(tmp, MAX_PARAMS_SIZE);
00329                 if (!ttp->unpackParams(dpb))
00330                 {
00331                         // This should only happen if the data is corrupt or
00332                         // incorrectly packed.
00333                         llwarns << "LLTransferManager::processTransferRequest: bad params."
00334                                 << llendl;
00335                         ttp->abortTransfer();
00336                         ttcp->deleteTransfer(ttp);
00337                         return;
00338                 }
00339         }
00340 
00341         llinfos << "Receiving " << transfer_id << ", size " << size << " bytes" << llendl;
00342         ttp->setSize(size);
00343         ttp->setGotInfo(TRUE);
00344 
00345         // OK, at this point we to handle any delayed transfer packets (which could happen
00346         // if this packet was lost)
00347 
00348         // This is a lame cut and paste of code down below.  If we change the logic down there,
00349         // we HAVE to change the logic up here.
00350 
00351         while (1)
00352         {
00353                 S32 packet_id = 0;
00354                 U8 tmp_data[MAX_PACKET_DATA_SIZE];
00355                 // See if we've got any delayed packets
00356                 packet_id = ttp->getNextPacketID();
00357                 if (ttp->mDelayedPacketMap.find(packet_id) != ttp->mDelayedPacketMap.end())
00358                 {
00359                         // Perhaps this stuff should be inside a method in LLTransferPacket?
00360                         // I'm too lazy to do it now, though.
00361 //                      llinfos << "Playing back delayed packet " << packet_id << llendl;
00362                         LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];
00363 
00364                         // This is somewhat inefficient, but avoids us having to duplicate
00365                         // code between the off-the-wire and delayed paths.
00366                         packet_id = packetp->mPacketID;
00367                         size = packetp->mSize;
00368                         if (size)
00369                         {
00370                                 if ((packetp->mDatap != NULL) && (size<(S32)sizeof(tmp_data)))
00371                                 {
00372                                         memcpy(tmp_data, packetp->mDatap, size);        /*Flawfinder: ignore*/
00373                                 }
00374                         }
00375                         status = packetp->mStatus;
00376                         ttp->mDelayedPacketMap.erase(packet_id);
00377                         delete packetp;
00378                 }
00379                 else
00380                 {
00381                         // No matching delayed packet, we're done.
00382                         break;
00383                 }
00384 
00385                 LLTSCode ret_code = ttp->dataCallback(packet_id, tmp_data, size);
00386                 if (ret_code == LLTS_OK)
00387                 {
00388                         ttp->setLastPacketID(packet_id);
00389                 }
00390 
00391                 if (status != LLTS_OK)
00392                 {
00393                         if (status != LLTS_DONE)
00394                         {
00395                                 llwarns << "LLTransferManager::processTransferInfo Error in playback!" << llendl;
00396                         }
00397                         else
00398                         {
00399                                 llinfos << "LLTransferManager::processTransferInfo replay FINISHED for " << transfer_id << llendl;
00400                         }
00401                         // This transfer is done, either via error or not.
00402                         ttp->completionCallback(status);
00403                         ttcp->deleteTransfer(ttp);
00404                         return;
00405                 }
00406         }
00407 }
00408 
00409 
00410 //static
00411 void LLTransferManager::processTransferPacket(LLMessageSystem *msgp, void **)
00412 {
00413         //llinfos << "LLTransferManager::processTransferPacket" << llendl;
00414 
00415         LLUUID transfer_id;
00416         LLTransferChannelType channel_type;
00417         S32 packet_id;
00418         LLTSCode status;
00419         S32 size;
00420         msgp->getUUID("TransferData", "TransferID", transfer_id);
00421         msgp->getS32("TransferData", "ChannelType", (S32 &)channel_type);
00422         msgp->getS32("TransferData", "Packet", packet_id);
00423         msgp->getS32("TransferData", "Status", (S32 &)status);
00424 
00425         // Find the transfer associated with this packet.
00426         //llinfos << transfer_id << ":" << channel_type << llendl;
00427         LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
00428         if (!ttcp)
00429         {
00430                 llwarns << "Target channel not found" << llendl;
00431                 return;
00432         }
00433 
00434         LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
00435         if (!ttp)
00436         {
00437                 llwarns << "Didn't find matching transfer for " << transfer_id
00438                         << " processing packet " << packet_id
00439                         << " from " << msgp->getSender() << llendl;
00440                 return;
00441         }
00442 
00443         size = msgp->getSize("TransferData", "Data");
00444 
00445         S32 msg_bytes = 0;
00446         if (msgp->getReceiveCompressedSize())
00447         {
00448                 msg_bytes = msgp->getReceiveCompressedSize();
00449         }
00450         else
00451         {
00452                 msg_bytes = msgp->getReceiveSize();
00453         }
00454         gTransferManager.addTransferBitsIn(ttcp->mChannelType, msg_bytes*8);
00455 
00456         if ((size < 0) || (size > MAX_PACKET_DATA_SIZE))
00457         {
00458                 llwarns << "Invalid transfer packet size " << size << llendl;
00459                 return;
00460         }
00461 
00462         U8 tmp_data[MAX_PACKET_DATA_SIZE];
00463         if (size > 0)
00464         {
00465                 // Only pull the data out if the size is > 0
00466                 msgp->getBinaryData("TransferData", "Data", tmp_data, size);
00467         }
00468 
00469         if ((!ttp->gotInfo()) || (ttp->getNextPacketID() != packet_id))
00470         {
00471                 // Put this on a list of packets to be delivered later.
00472                 if(!ttp->addDelayedPacket(packet_id, status, tmp_data, size))
00473                 {
00474                         // Whoops - failed to add a delayed packet for some reason.
00475                         llwarns << "Too many delayed packets processing transfer "
00476                                 << transfer_id << " from " << msgp->getSender() << llendl;
00477                         ttp->abortTransfer();
00478                         ttcp->deleteTransfer(ttp);
00479                         return;
00480                 }
00481 #if 0
00482                 // Spammy!
00483                 const S32 LL_TRANSFER_WARN_GAP = 10;
00484                 if(!ttp->gotInfo())
00485                 {
00486                         llwarns << "Got data packet before information in transfer "
00487                                 << transfer_id << " from " << msgp->getSender()
00488                                 << ", got " << packet_id << llendl;
00489                 }
00490                 else if((packet_id - ttp->getNextPacketID()) > LL_TRANSFER_WARN_GAP)
00491                 {
00492                         llwarns << "Out of order packet in transfer " << transfer_id
00493                                 << " from " << msgp->getSender() << ", got " << packet_id
00494                                 << " expecting " << ttp->getNextPacketID() << llendl;
00495                 }
00496 #endif
00497                 return;
00498         }
00499 
00500         // Loop through this until we're done with all delayed packets
00501         
00502         //
00503         // NOTE: THERE IS A CUT AND PASTE OF THIS CODE IN THE TRANSFERINFO HANDLER
00504         // SO WE CAN PLAY BACK DELAYED PACKETS THERE!!!!!!!!!!!!!!!!!!!!!!!!!
00505         //
00506         BOOL done = FALSE;
00507         while (!done)
00508         {
00509                 LLTSCode ret_code = ttp->dataCallback(packet_id, tmp_data, size);
00510                 if (ret_code == LLTS_OK)
00511                 {
00512                         ttp->setLastPacketID(packet_id);
00513                 }
00514 
00515                 if (status != LLTS_OK)
00516                 {
00517                         if (status != LLTS_DONE)
00518                         {
00519                                 llwarns << "LLTransferManager::processTransferPacket Error in transfer!" << llendl;
00520                         }
00521                         else
00522                         {
00523 //                              llinfos << "LLTransferManager::processTransferPacket done for " << transfer_id << llendl;
00524                         }
00525                         // This transfer is done, either via error or not.
00526                         ttp->completionCallback(status);
00527                         ttcp->deleteTransfer(ttp);
00528                         return;
00529                 }
00530 
00531                 // See if we've got any delayed packets
00532                 packet_id = ttp->getNextPacketID();
00533                 if (ttp->mDelayedPacketMap.find(packet_id) != ttp->mDelayedPacketMap.end())
00534                 {
00535                         // Perhaps this stuff should be inside a method in LLTransferPacket?
00536                         // I'm too lazy to do it now, though.
00537 //                      llinfos << "Playing back delayed packet " << packet_id << llendl;
00538                         LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];
00539 
00540                         // This is somewhat inefficient, but avoids us having to duplicate
00541                         // code between the off-the-wire and delayed paths.
00542                         packet_id = packetp->mPacketID;
00543                         size = packetp->mSize;
00544                         if (size)
00545                         {
00546                                 if ((packetp->mDatap != NULL) && (size<(S32)sizeof(tmp_data)))
00547                                 {
00548                                         memcpy(tmp_data, packetp->mDatap, size);        /*Flawfinder: ignore*/
00549                                 }
00550                         }
00551                         status = packetp->mStatus;
00552                         ttp->mDelayedPacketMap.erase(packet_id);
00553                         delete packetp;
00554                 }
00555                 else
00556                 {
00557                         // No matching delayed packet, abort it.
00558                         done = TRUE;
00559                 }
00560         }
00561 }
00562 
00563 
00564 //static
00565 void LLTransferManager::processTransferAbort(LLMessageSystem *msgp, void **)
00566 {
00567         //llinfos << "LLTransferManager::processTransferPacket" << llendl;
00568 
00569         LLUUID transfer_id;
00570         LLTransferChannelType channel_type;
00571         msgp->getUUID("TransferInfo", "TransferID", transfer_id);
00572         msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
00573 
00574 
00575         // See if it's a target that we're trying to abort
00576         // Find the transfer associated with this packet.
00577         LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
00578         if (ttcp)
00579         {
00580                 LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
00581                 if (ttp)
00582                 {
00583                         ttp->abortTransfer();
00584                         ttcp->deleteTransfer(ttp);
00585                         return;
00586                 }
00587         }
00588 
00589         // Hmm, not a target.  Maybe it's a source.
00590         LLTransferSourceChannel *tscp = gTransferManager.getSourceChannel(msgp->getSender(), channel_type);
00591         if (tscp)
00592         {
00593                 LLTransferSource *tsp = tscp->findTransferSource(transfer_id);
00594                 if (tsp)
00595                 {
00596                         tsp->abortTransfer();
00597                         tscp->deleteTransfer(tsp);
00598                         return;
00599                 }
00600         }
00601 
00602         llwarns << "Couldn't find transfer " << transfer_id << " to abort!" << llendl;
00603 }
00604 
00605 
00606 //static
00607 void LLTransferManager::reliablePacketCallback(void **user_data, S32 result)
00608 {
00609         LLUUID *transfer_idp = (LLUUID *)user_data;
00610         if (result)
00611         {
00612                 llwarns << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << llendl;
00613                 LLTransferSource *tsp = gTransferManager.findTransferSource(*transfer_idp);
00614                 if (tsp)
00615                 {
00616                         LLTransferSourceChannel *tscp = tsp->mChannelp;
00617                         tsp->abortTransfer();
00618                         tscp->deleteTransfer(tsp);
00619                 }
00620         }
00621         delete transfer_idp;
00622 }
00623 
00624 //
00625 // LLTransferConnection implementation
00626 //
00627 
00628 LLTransferConnection::LLTransferConnection(const LLHost &host)
00629 {
00630         mHost = host;
00631 }
00632 
00633 LLTransferConnection::~LLTransferConnection()
00634 {
00635         tsc_iter itersc;
00636         for (itersc = mTransferSourceChannels.begin(); itersc != mTransferSourceChannels.end(); itersc++)
00637         {
00638                 delete *itersc;
00639         }
00640         mTransferSourceChannels.clear();
00641 
00642         ttc_iter itertc;
00643         for (itertc = mTransferTargetChannels.begin(); itertc != mTransferTargetChannels.end(); itertc++)
00644         {
00645                 delete *itertc;
00646         }
00647         mTransferTargetChannels.clear();
00648 }
00649 
00650 
00651 void LLTransferConnection::updateTransfers()
00652 {
00653         // Do stuff for source transfers (basically, send data out).
00654         tsc_iter iter;
00655         for (iter = mTransferSourceChannels.begin(); iter != mTransferSourceChannels.end(); iter++)
00656         {
00657                 (*iter)->updateTransfers();
00658         }
00659 
00660         // Do stuff for target transfers
00661         // Primarily, we should be aborting transfers that are irredeemably broken
00662         // (large packet gaps that don't appear to be getting filled in, most likely)
00663         // Probably should NOT be doing timeouts for other things, as new priority scheme
00664         // means that a high priority transfer COULD block a transfer for a long time.
00665 }
00666 
00667 
00668 LLTransferSourceChannel *LLTransferConnection::getSourceChannel(const LLTransferChannelType channel_type)
00669 {
00670         tsc_iter iter;
00671         for (iter = mTransferSourceChannels.begin(); iter != mTransferSourceChannels.end(); iter++)
00672         {
00673                 if ((*iter)->getChannelType() == channel_type)
00674                 {
00675                         return *iter;
00676                 }
00677         }
00678 
00679         LLTransferSourceChannel *tscp = new LLTransferSourceChannel(channel_type, mHost);
00680         mTransferSourceChannels.push_back(tscp);
00681         return tscp;
00682 }
00683 
00684 
00685 LLTransferTargetChannel *LLTransferConnection::getTargetChannel(const LLTransferChannelType channel_type)
00686 {
00687         ttc_iter iter;
00688         for (iter = mTransferTargetChannels.begin(); iter != mTransferTargetChannels.end(); iter++)
00689         {
00690                 if ((*iter)->getChannelType() == channel_type)
00691                 {
00692                         return *iter;
00693                 }
00694         }
00695 
00696         LLTransferTargetChannel *ttcp = new LLTransferTargetChannel(channel_type, mHost);
00697         mTransferTargetChannels.push_back(ttcp);
00698         return ttcp;
00699 }
00700 
00701 
00702 //
00703 // LLTransferSourceChannel implementation
00704 //
00705 
00706 const S32 DEFAULT_PACKET_SIZE = 1000;
00707 
00708 
00709 LLTransferSourceChannel::LLTransferSourceChannel(const LLTransferChannelType channel_type, const LLHost &host) :
00710         mChannelType(channel_type),
00711         mHost(host),
00712         mTransferSources(LLTransferSource::sSetPriority, LLTransferSource::sGetPriority),
00713         mThrottleID(TC_ASSET)
00714 {
00715 }
00716 
00717 
00718 LLTransferSourceChannel::~LLTransferSourceChannel()
00719 {
00720         LLPriQueueMap<LLTransferSource*>::pqm_iter iter =
00721                 mTransferSources.mMap.begin();
00722         LLPriQueueMap<LLTransferSource*>::pqm_iter end =
00723                 mTransferSources.mMap.end();
00724         for (; iter != end; ++iter)
00725         {
00726                 // Just kill off all of the transfers
00727                 (*iter).second->abortTransfer();
00728                 delete iter->second;
00729         }
00730         mTransferSources.mMap.clear();
00731 }
00732 
00733 void LLTransferSourceChannel::updatePriority(LLTransferSource *tsp, const F32 priority)
00734 {
00735         mTransferSources.reprioritize(priority, tsp);
00736 }
00737 
00738 void LLTransferSourceChannel::updateTransfers()
00739 {
00740         // Actually, this should do the following:
00741         // Decide if we can actually send data.
00742         // If so, update priorities so we know who gets to send it.
00743         // Send data from the sources, while updating until we've sent our throttle allocation.
00744 
00745         LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(getHost());
00746         if (!cdp)
00747         {
00748                 return;
00749         }
00750 
00751         if (cdp->isBlocked())
00752         {
00753                 // *NOTE: We need to make sure that the throttle bits
00754                 // available gets reset.
00755 
00756                 // We DON'T want to send any packets if they're blocked, they'll just end up
00757                 // piling up on the other end.
00758                 //llwarns << "Blocking transfers due to blocked circuit for " << getHost() << llendl;
00759                 return;
00760         }
00761 
00762         const S32 throttle_id = mThrottleID;
00763 
00764         LLThrottleGroup &tg = cdp->getThrottleGroup();
00765 
00766         if (tg.checkOverflow(throttle_id, 0.f))
00767         {
00768                 return;
00769         }
00770 
00771         LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
00772 
00773 
00774         BOOL done = FALSE;
00775         for (iter = mTransferSources.mMap.begin(); (iter != mTransferSources.mMap.end()) && !done;)
00776         {
00777                 //llinfos << "LLTransferSourceChannel::updateTransfers()" << llendl;
00778                 // Do stuff.
00779                 LLTransferSource *tsp = iter->second;
00780                 U8 *datap = NULL;
00781                 S32 data_size = 0;
00782                 BOOL delete_data = FALSE;
00783                 S32 packet_id = 0;
00784                 S32 sent_bytes = 0;
00785                 LLTSCode status = LLTS_OK;
00786 
00787                 // Get the packetID for the next packet that we're transferring.
00788                 packet_id = tsp->getNextPacketID();
00789                 status = tsp->dataCallback(packet_id, DEFAULT_PACKET_SIZE, &datap, data_size, delete_data);
00790 
00791                 if (status == LLTS_SKIP)
00792                 {
00793                         // We don't have any data, but we're not done, just go on.
00794                         // This will presumably be used for streaming or async transfers that
00795                         // are stalled waiting for data from another source.
00796                         iter++;
00797                         continue;
00798                 }
00799 
00800                 LLUUID *cb_uuid = new LLUUID(tsp->getID());
00801 
00802                 // Send the data now, even if it's an error.
00803                 // The status code will tell the other end what to do.
00804                 gMessageSystem->newMessage("TransferPacket");
00805                 gMessageSystem->nextBlock("TransferData");
00806                 gMessageSystem->addUUID("TransferID", tsp->getID());
00807                 gMessageSystem->addS32("ChannelType", getChannelType());
00808                 gMessageSystem->addS32("Packet", packet_id);    // HACK!  Need to put in a REAL packet id
00809                 gMessageSystem->addS32("Status", status);
00810                 gMessageSystem->addBinaryData("Data", datap, data_size);
00811                 sent_bytes = gMessageSystem->getCurrentSendTotal();
00812                 gMessageSystem->sendReliable(getHost(), LL_DEFAULT_RELIABLE_RETRIES, TRUE, 0.f,
00813                                                                          LLTransferManager::reliablePacketCallback, (void**)cb_uuid);
00814 
00815                 // Do bookkeeping for the throttle
00816                 done = tg.throttleOverflow(throttle_id, sent_bytes*8.f);
00817                 gTransferManager.addTransferBitsOut(mChannelType, sent_bytes*8);
00818 
00819                 // Clean up our temporary data.
00820                 if (delete_data)
00821                 {
00822                         delete[] datap;
00823                         datap = NULL;
00824                 }
00825                 
00826                 // Update the packet counter
00827                 tsp->setLastPacketID(packet_id);
00828 
00829                 switch (status)
00830                 {
00831                 case LLTS_OK:
00832                         // We're OK, don't need to do anything.  Keep sending data.
00833                         break;
00834                 case LLTS_ERROR:
00835                         llwarns << "Error in transfer dataCallback!" << llendl;
00836                 case LLTS_DONE:
00837                         // We need to clean up this transfer source.
00838                         //llinfos << "LLTransferSourceChannel::updateTransfers() " << tsp->getID() << " done" << llendl;
00839                         tsp->completionCallback(status);
00840                         delete tsp;
00841                         
00842                         mTransferSources.mMap.erase(iter++);
00843                         break;
00844                 default:
00845                         llerrs << "Unknown transfer error code!" << llendl;
00846                 }
00847 
00848                 // At this point, we should do priority adjustment (since some transfers like
00849                 // streaming transfers will adjust priority based on how much they've sent and time,
00850                 // but I'm not going to bother yet. - djs.
00851         }
00852 }
00853 
00854 
00855 void LLTransferSourceChannel::addTransferSource(LLTransferSource *sourcep)
00856 {
00857         sourcep->mChannelp = this;
00858         mTransferSources.push(sourcep->getPriority(), sourcep);
00859 }
00860 
00861 
00862 LLTransferSource *LLTransferSourceChannel::findTransferSource(const LLUUID &transfer_id)
00863 {
00864         LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
00865         for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
00866         {
00867                 LLTransferSource *tsp = iter->second;
00868                 if (tsp->getID() == transfer_id)
00869                 {
00870                         return tsp;
00871                 }
00872         }
00873         return NULL;
00874 }
00875 
00876 
00877 BOOL LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp)
00878 {
00879         LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
00880         for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
00881         {
00882                 if (iter->second == tsp)
00883                 {
00884                         break;
00885                 }
00886         }
00887 
00888         if (iter == mTransferSources.mMap.end())
00889         {
00890                 llerrs << "Unable to find transfer source to delete!" << llendl;
00891                 return FALSE;
00892         }
00893         mTransferSources.mMap.erase(iter);
00894         delete tsp;
00895         return TRUE;
00896 }
00897 
00898 
00899 //
00900 // LLTransferTargetChannel implementation
00901 //
00902 
00903 LLTransferTargetChannel::LLTransferTargetChannel(const LLTransferChannelType channel_type, const LLHost &host) :
00904         mChannelType(channel_type),
00905         mHost(host)
00906 {
00907 }
00908 
00909 LLTransferTargetChannel::~LLTransferTargetChannel()
00910 {
00911         tt_iter iter;
00912         for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
00913         {
00914                 // Abort all of the current transfers
00915                 (*iter)->abortTransfer();
00916                 delete *iter;
00917         }
00918         mTransferTargets.clear();
00919 }
00920 
00921 
00922 void LLTransferTargetChannel::requestTransfer(
00923         const LLTransferSourceParams& source_params,
00924         const LLTransferTargetParams& target_params,
00925         const F32 priority)
00926 {
00927         LLUUID id;
00928         id.generate();
00929         LLTransferTarget* ttp = LLTransferTarget::createTarget(
00930                 target_params.getType(),
00931                 id,
00932                 source_params.getType());
00933         if (!ttp)
00934         {
00935                 llwarns << "LLTransferManager::requestTransfer aborting due to target creation failure!" << llendl;
00936                 return;
00937         }
00938 
00939         ttp->applyParams(target_params);
00940         addTransferTarget(ttp);
00941 
00942         sendTransferRequest(ttp, source_params, priority);
00943 }
00944 
00945 
00946 void LLTransferTargetChannel::sendTransferRequest(LLTransferTarget *targetp,
00947                                                                                                   const LLTransferSourceParams &params,
00948                                                                                                   const F32 priority)
00949 {
00950         //
00951         // Pack the message with data which explains how to get the source, and
00952         // send it off to the source for this channel.
00953         //
00954         llassert(targetp);
00955         llassert(targetp->getChannel() == this);
00956 
00957         gMessageSystem->newMessage("TransferRequest");
00958         gMessageSystem->nextBlock("TransferInfo");
00959         gMessageSystem->addUUID("TransferID", targetp->getID());
00960         gMessageSystem->addS32("SourceType", params.getType());
00961         gMessageSystem->addS32("ChannelType", getChannelType());
00962         gMessageSystem->addF32("Priority", priority);
00963 
00964         U8 tmp[MAX_PARAMS_SIZE];
00965         LLDataPackerBinaryBuffer dp(tmp, MAX_PARAMS_SIZE);
00966         params.packParams(dp);
00967         S32 len = dp.getCurrentSize();
00968         gMessageSystem->addBinaryData("Params", tmp, len);
00969 
00970         gMessageSystem->sendReliable(mHost);
00971 }
00972 
00973 
00974 void LLTransferTargetChannel::addTransferTarget(LLTransferTarget *targetp)
00975 {
00976         targetp->mChannelp = this;
00977         mTransferTargets.push_back(targetp);
00978 }
00979 
00980 
00981 LLTransferTarget *LLTransferTargetChannel::findTransferTarget(const LLUUID &transfer_id)
00982 {
00983         tt_iter iter;
00984         for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
00985         {
00986                 LLTransferTarget *ttp = *iter;
00987                 if (ttp->getID() == transfer_id)
00988                 {
00989                         return ttp;
00990                 }
00991         }
00992         return NULL;
00993 }
00994 
00995 
00996 BOOL LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp)
00997 {
00998         tt_iter iter;
00999         for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
01000         {
01001                 if (*iter == ttp)
01002                 {
01003                         break;
01004                 }
01005         }
01006 
01007         if (iter == mTransferTargets.end())
01008         {
01009                 llerrs << "Unable to find transfer target to delete!" << llendl;
01010                 return FALSE;
01011         }
01012         mTransferTargets.erase(iter);
01013         delete ttp;
01014         return TRUE;
01015 }
01016 
01017 
01018 //
01019 // LLTransferSource implementation
01020 //
01021 
01022 LLTransferSource::LLTransferSource(const LLTransferSourceType type,
01023                                                                    const LLUUID &transfer_id,
01024                                                                    const F32 priority) :
01025         mType(type),
01026         mID(transfer_id),
01027         mChannelp(NULL),
01028         mPriority(priority),
01029         mSize(0),
01030         mLastPacketID(-1)
01031 {
01032         setPriority(priority);
01033 }
01034 
01035 
01036 LLTransferSource::~LLTransferSource()
01037 {
01038         // No actual cleanup of the transfer is done here, this is purely for
01039         // memory cleanup.  The completionCallback is guaranteed to get called
01040         // before this happens.
01041 }
01042 
01043 
01044 void LLTransferSource::sendTransferStatus(LLTSCode status)
01045 {
01046         gMessageSystem->newMessage("TransferInfo");
01047         gMessageSystem->nextBlock("TransferInfo");
01048         gMessageSystem->addUUID("TransferID", getID());
01049         gMessageSystem->addS32("TargetType", LLTTT_UNKNOWN);
01050         gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
01051         gMessageSystem->addS32("Status", status);
01052         gMessageSystem->addS32("Size", mSize);
01053         U8 tmp[MAX_PARAMS_SIZE];
01054         LLDataPackerBinaryBuffer dp(tmp, MAX_PARAMS_SIZE);
01055         packParams(dp);
01056         S32 len = dp.getCurrentSize();
01057         gMessageSystem->addBinaryData("Params", tmp, len);
01058         gMessageSystem->sendReliable(mChannelp->getHost());
01059 
01060         // Abort if there was as asset system issue.
01061         if (status != LLTS_OK)
01062         {
01063                 completionCallback(status);
01064                 mChannelp->deleteTransfer(this);
01065         }
01066 }
01067 
01068 
01069 // This should never be called directly, the transfer manager is responsible for
01070 // aborting the transfer from the channel.  I might want to rethink this in the
01071 // future, though.
01072 void LLTransferSource::abortTransfer()
01073 {
01074         // Send a message down, call the completion callback
01075         llinfos << "Aborting transfer " << getID() << " to " << mChannelp->getHost() << llendl;
01076         gMessageSystem->newMessage("TransferAbort");
01077         gMessageSystem->nextBlock("TransferInfo");
01078         gMessageSystem->addUUID("TransferID", getID());
01079         gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
01080         gMessageSystem->sendReliable(mChannelp->getHost());
01081 
01082         completionCallback(LLTS_ABORT);
01083 }
01084 
01085 
01086 //static
01087 void LLTransferSource::registerSourceType(const LLTransferSourceType stype, LLTransferSourceCreateFunc func)
01088 {
01089         if (sSourceCreateMap.count(stype))
01090         {
01091                 // Disallow changing what class handles a source type
01092                 // Unclear when you would want to do this, and whether it would work.
01093                 llerrs << "Reregistering source type " << stype << llendl;
01094         }
01095         else
01096         {
01097                 sSourceCreateMap[stype] = func;
01098         }
01099 }
01100 
01101 //static
01102 LLTransferSource *LLTransferSource::createSource(const LLTransferSourceType stype,
01103                                                                                                  const LLUUID &id,
01104                                                                                                  const F32 priority)
01105 {
01106         switch (stype)
01107         {
01108         // *NOTE: The source file transfer mechanism is highly insecure and could
01109         // lead to easy exploitation of a server process.
01110         // I have removed all uses of it from the codebase. Phoenix.
01111         // 
01112         //case LLTST_FILE:
01113         //      return new LLTransferSourceFile(id, priority);
01114         case LLTST_ASSET:
01115                 return new LLTransferSourceAsset(id, priority);
01116         default:
01117                 {
01118                         if (!sSourceCreateMap.count(stype))
01119                         {
01120                                 // Use the callback to create the source type if it's not there.
01121                                 llwarns << "Unknown transfer source type: " << stype << llendl;
01122                                 return NULL;
01123                         }
01124                         return (sSourceCreateMap[stype])(id, priority);
01125                 }
01126         }
01127 }
01128 
01129 
01130 // static
01131 void LLTransferSource::sSetPriority(LLTransferSource *&tsp, const F32 priority)
01132 {
01133         tsp->setPriority(priority);
01134 }
01135 
01136 
01137 // static
01138 F32 LLTransferSource::sGetPriority(LLTransferSource *&tsp)
01139 {
01140         return tsp->getPriority();
01141 }
01142 
01143 
01144 //
01145 // LLTransferPacket implementation
01146 //
01147 
01148 LLTransferPacket::LLTransferPacket(const S32 packet_id, const LLTSCode status, const U8 *datap, const S32 size) :
01149         mPacketID(packet_id),
01150         mStatus(status),
01151         mDatap(NULL),
01152         mSize(size)
01153 {
01154         if (size == 0)
01155         {
01156                 return;
01157         }
01158         
01159         mDatap = new U8[size];
01160         if (mDatap != NULL)
01161         {
01162                 memcpy(mDatap, datap, size);    /*Flawfinder: ignore*/
01163         }
01164 }
01165 
01166 LLTransferPacket::~LLTransferPacket()
01167 {
01168         delete[] mDatap;
01169 }
01170 
01171 //
01172 // LLTransferTarget implementation
01173 //
01174 
01175 LLTransferTarget::LLTransferTarget(
01176         LLTransferTargetType type,
01177         const LLUUID& transfer_id,
01178         LLTransferSourceType source_type) : 
01179         mType(type),
01180         mSourceType(source_type),
01181         mID(transfer_id),
01182         mGotInfo(FALSE),
01183         mSize(0),
01184         mLastPacketID(-1)
01185 {
01186 }
01187 
01188 LLTransferTarget::~LLTransferTarget()
01189 {
01190         // No actual cleanup of the transfer is done here, this is purely for
01191         // memory cleanup.  The completionCallback is guaranteed to get called
01192         // before this happens.
01193         tpm_iter iter;
01194         for (iter = mDelayedPacketMap.begin(); iter != mDelayedPacketMap.end(); iter++)
01195         {
01196                 delete iter->second;
01197         }
01198         mDelayedPacketMap.clear();
01199 }
01200 
01201 // This should never be called directly, the transfer manager is responsible for
01202 // aborting the transfer from the channel.  I might want to rethink this in the
01203 // future, though.
01204 void LLTransferTarget::abortTransfer()
01205 {
01206         // Send a message up, call the completion callback
01207         llinfos << "Aborting transfer " << getID() << " from " << mChannelp->getHost() << llendl;
01208         gMessageSystem->newMessage("TransferAbort");
01209         gMessageSystem->nextBlock("TransferInfo");
01210         gMessageSystem->addUUID("TransferID", getID());
01211         gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
01212         gMessageSystem->sendReliable(mChannelp->getHost());
01213 
01214         completionCallback(LLTS_ABORT);
01215 }
01216 
01217 bool LLTransferTarget::addDelayedPacket(
01218         const S32 packet_id,
01219         const LLTSCode status,
01220         U8* datap,
01221         const S32 size)
01222 {
01223         const transfer_packet_map::size_type LL_MAX_DELAYED_PACKETS = 100;
01224         if(mDelayedPacketMap.size() > LL_MAX_DELAYED_PACKETS)
01225         {
01226                 // too many delayed packets
01227                 return false;
01228         }
01229 
01230         LLTransferPacket* tpp = new LLTransferPacket(
01231                 packet_id,
01232                 status,
01233                 datap,
01234                 size);
01235 
01236 #ifdef _DEBUG
01237         if (mDelayedPacketMap.find(packet_id) != mDelayedPacketMap.end())
01238         {
01239                 llerrs << "Packet ALREADY in delayed packet map!" << llendl;
01240         }
01241 #endif
01242 
01243         mDelayedPacketMap[packet_id] = tpp;
01244         return true;
01245 }
01246 
01247 
01248 LLTransferTarget* LLTransferTarget::createTarget(
01249         LLTransferTargetType type,
01250         const LLUUID& id,
01251         LLTransferSourceType source_type)
01252 {
01253         switch (type)
01254         {
01255         case LLTTT_FILE:
01256                 return new LLTransferTargetFile(id, source_type);
01257         case LLTTT_VFILE:
01258                 return new LLTransferTargetVFile(id, source_type);
01259         default:
01260                 llwarns << "Unknown transfer target type: " << type << llendl;
01261                 return NULL;
01262         }
01263 }
01264 
01265 
01266 LLTransferSourceParamsInvItem::LLTransferSourceParamsInvItem() : LLTransferSourceParams(LLTST_SIM_INV_ITEM), mAssetType(LLAssetType::AT_NONE)
01267 {
01268 }
01269 
01270 
01271 void LLTransferSourceParamsInvItem::setAgentSession(const LLUUID &agent_id, const LLUUID &session_id)
01272 {
01273         mAgentID = agent_id;
01274         mSessionID = session_id;
01275 }
01276 
01277 
01278 void LLTransferSourceParamsInvItem::setInvItem(const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id)
01279 {
01280         mOwnerID = owner_id;
01281         mTaskID = task_id;
01282         mItemID = item_id;
01283 }
01284 
01285 
01286 void LLTransferSourceParamsInvItem::setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type)
01287 {
01288         mAssetID = asset_id;
01289         mAssetType = asset_type;
01290 }
01291 
01292 
01293 void LLTransferSourceParamsInvItem::packParams(LLDataPacker &dp) const
01294 {
01295         lldebugs << "LLTransferSourceParamsInvItem::packParams()" << llendl;
01296         dp.packUUID(mAgentID, "AgentID");
01297         dp.packUUID(mSessionID, "SessionID");
01298         dp.packUUID(mOwnerID, "OwnerID");
01299         dp.packUUID(mTaskID, "TaskID");
01300         dp.packUUID(mItemID, "ItemID");
01301         dp.packUUID(mAssetID, "AssetID");
01302         dp.packS32(mAssetType, "AssetType");
01303 }
01304 
01305 
01306 BOOL LLTransferSourceParamsInvItem::unpackParams(LLDataPacker &dp)
01307 {
01308         S32 tmp_at;
01309 
01310         dp.unpackUUID(mAgentID, "AgentID");
01311         dp.unpackUUID(mSessionID, "SessionID");
01312         dp.unpackUUID(mOwnerID, "OwnerID");
01313         dp.unpackUUID(mTaskID, "TaskID");
01314         dp.unpackUUID(mItemID, "ItemID");
01315         dp.unpackUUID(mAssetID, "AssetID");
01316         dp.unpackS32(tmp_at, "AssetType");
01317 
01318         mAssetType = (LLAssetType::EType)tmp_at;
01319 
01320         return TRUE;
01321 }
01322 
01323 LLTransferSourceParamsEstate::LLTransferSourceParamsEstate() :
01324         LLTransferSourceParams(LLTST_SIM_ESTATE), mEstateAssetType(ET_NONE)
01325 {
01326 }
01327 
01328 void LLTransferSourceParamsEstate::setAgentSession(const LLUUID &agent_id, const LLUUID &session_id)
01329 {
01330         mAgentID = agent_id;
01331         mSessionID = session_id;
01332 }
01333 
01334 void LLTransferSourceParamsEstate::setEstateAssetType(const EstateAssetType etype)
01335 {
01336         mEstateAssetType = etype;
01337 }
01338 
01339 void LLTransferSourceParamsEstate::setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type)
01340 {
01341         mAssetID = asset_id;
01342         mAssetType = asset_type;
01343 }
01344 
01345 void LLTransferSourceParamsEstate::packParams(LLDataPacker &dp) const
01346 {
01347         dp.packUUID(mAgentID, "AgentID");
01348         // *NOTE: We do not want to pass the session id from the server to
01349         // the client, but I am not sure if anyone expects this value to
01350         // be set on the client.
01351         dp.packUUID(mSessionID, "SessionID");
01352         dp.packS32(mEstateAssetType, "EstateAssetType");
01353 }
01354 
01355 
01356 BOOL LLTransferSourceParamsEstate::unpackParams(LLDataPacker &dp)
01357 {
01358         S32 tmp_et;
01359 
01360         dp.unpackUUID(mAgentID, "AgentID");
01361         dp.unpackUUID(mSessionID, "SessionID");
01362         dp.unpackS32(tmp_et, "EstateAssetType");
01363 
01364         mEstateAssetType = (EstateAssetType)tmp_et;
01365 
01366         return TRUE;
01367 }

Generated on Thu Jul 1 06:09:23 2010 for Second Life Viewer by  doxygen 1.4.7