• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

FileListTransfer.cpp

Go to the documentation of this file.
00001 #include "NativeFeatureIncludes.h"
00002 #if _RAKNET_SUPPORT_FileListTransfer==1
00003 
00004 #include "FileListTransfer.h"
00005 #include "DS_HuffmanEncodingTree.h"
00006 #include "FileListTransferCBInterface.h"
00007 #include "StringCompressor.h"
00008 #include "FileList.h"
00009 #include "DS_Queue.h"
00010 #include "MessageIdentifiers.h"
00011 #include "RakNetTypes.h"
00012 #include "RakPeerInterface.h"
00013 #include "RakNetStatistics.h"
00014 #include "IncrementalReadInterface.h"
00015 #include "RakAssert.h"
00016 #include "RakAlloca.h"
00017 
00018 #ifdef _MSC_VER
00019 #pragma warning( push )
00020 #endif
00021 
00022 struct FLR_MemoryBlock
00023 {
00024         char *flrMemoryBlock;
00025 };
00026 
00027 struct FileListReceiver
00028 {
00029         FileListReceiver();
00030         ~FileListReceiver();
00031         FileListTransferCBInterface *downloadHandler;
00032         SystemAddress allowedSender;
00033         unsigned short setID;
00034         unsigned setCount;
00035         unsigned setTotalCompressedTransmissionLength;
00036         unsigned setTotalFinalLength;
00037         unsigned setTotalDownloadedLength;
00038         bool gotSetHeader;
00039         bool deleteDownloadHandler;
00040         bool isCompressed;
00041         int  filesReceived;
00042         DataStructures::Map<unsigned int, FLR_MemoryBlock> pushedFiles;
00043 
00044         // Notifications
00045         unsigned int partLength;
00046 
00047 };
00048 
00049 FileListReceiver::FileListReceiver() {filesReceived=0; setTotalDownloadedLength=0; partLength=1; DataStructures::Map<unsigned int, FLR_MemoryBlock>::IMPLEMENT_DEFAULT_COMPARISON();}
00050 FileListReceiver::~FileListReceiver() {
00051         unsigned int i=0;
00052         for (i=0; i < pushedFiles.Size(); i++)
00053                 rakFree_Ex(pushedFiles[i].flrMemoryBlock, __FILE__, __LINE__ );
00054 }
00055 
00056 FileListTransfer::FileListTransfer()
00057 {
00058         setId=0;
00059         callback=0;
00060         DataStructures::Map<unsigned short, FileListReceiver*>::IMPLEMENT_DEFAULT_COMPARISON();
00061 }
00062 FileListTransfer::~FileListTransfer()
00063 {
00064         Clear();
00065 }
00066 unsigned short FileListTransfer::SetupReceive(FileListTransferCBInterface *handler, bool deleteHandler, SystemAddress allowedSender)
00067 {
00068         if (rakPeerInterface && rakPeerInterface->IsConnected(allowedSender)==false)
00069                 return (unsigned short)-1;
00070         FileListReceiver *receiver;
00071 
00072         if (fileListReceivers.Has(setId))
00073         {
00074                 receiver=fileListReceivers.Get(setId);
00075                 receiver->downloadHandler->OnDereference();
00076                 if (receiver->deleteDownloadHandler)
00077                         RakNet::OP_DELETE(receiver->downloadHandler, __FILE__, __LINE__);
00078                 RakNet::OP_DELETE(receiver, __FILE__, __LINE__);
00079                 fileListReceivers.Delete(setId);
00080         }
00081 
00082         unsigned short oldId;
00083         receiver = RakNet::OP_NEW<FileListReceiver>( __FILE__, __LINE__ );
00084         RakAssert(handler);
00085         receiver->downloadHandler=handler;
00086         receiver->allowedSender=allowedSender;
00087         receiver->gotSetHeader=false;
00088         receiver->deleteDownloadHandler=deleteHandler;
00089         fileListReceivers.Set(setId, receiver);
00090         oldId=setId;
00091         if (++setId==(unsigned short)-1)
00092                 setId=0;
00093         return oldId;
00094 }
00095 
00096 void FileListTransfer::Send(FileList *fileList, RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, bool compressData, IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize)
00097 {
00098         (void) compressData;
00099 
00100         if (callback)
00101                 fileList->SetCallback(callback);
00102 
00103         unsigned int i, totalLength;
00104         RakNet::BitStream outBitstream;
00105         bool sendReference;
00106         const char *dataBlocks[2];
00107         int lengths[2];
00108         totalLength=0;
00109         for (i=0; i < fileList->fileList.Size(); i++)
00110         {
00111                 const FileListNode &fileListNode = fileList->fileList[i];
00112                 totalLength+=fileListNode.fileLengthBytes;
00113         }
00114 
00115         // Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes
00116         bool anythingToWrite;
00117         outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_HEADER);
00118         outBitstream.Write(setID);
00119         anythingToWrite=fileList->fileList.Size()>0;
00120         outBitstream.Write(anythingToWrite);
00121         if (anythingToWrite)
00122         {
00123                 outBitstream.WriteCompressed(fileList->fileList.Size());
00124                 outBitstream.WriteCompressed(totalLength);
00125 
00126                 if (rakPeer)
00127                         rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
00128                 else
00129                         SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
00130 
00131                 DataStructures::Queue<FileToPush*> filesToPush;
00132         
00133                 for (i=0; i < fileList->fileList.Size(); i++)
00134                 {
00135                         sendReference = fileList->fileList[i].isAReference && _incrementalReadInterface!=0;
00136                         if (sendReference)
00137                         {
00138                                 FileToPush *fileToPush = RakNet::OP_NEW<FileToPush>(__FILE__,__LINE__);
00139                                 fileToPush->fileListNode.context=fileList->fileList[i].context;
00140                                 fileToPush->setIndex=i;
00141                                 fileToPush->fileListNode.filename=fileList->fileList[i].filename;
00142                                 fileToPush->fileListNode.fullPathToFile=fileList->fileList[i].fullPathToFile;
00143                                 fileToPush->fileListNode.fileLengthBytes=fileList->fileList[i].fileLengthBytes;
00144                                 fileToPush->fileListNode.dataLengthBytes=fileList->fileList[i].dataLengthBytes;
00145                                 //      fileToPush->systemAddress=recipient;
00146                                 fileToPush->setID=setID;
00147                                 fileToPush->packetPriority=priority;
00148                                 fileToPush->orderingChannel=orderingChannel;
00149                                 fileToPush->currentOffset=0;
00150                                 fileToPush->incrementalReadInterface=_incrementalReadInterface;
00151                                 fileToPush->chunkSize=_chunkSize;
00152                                 filesToPush.Push(fileToPush,__FILE__,__LINE__);
00153                         }
00154                         else
00155                         {
00156                                 outBitstream.Reset();
00157                                 outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE);
00158                                 outBitstream << fileList->fileList[i].context;
00159                                 // outBitstream.Write(fileList->fileList[i].context);
00160                                 outBitstream.Write(setID);
00161                                 stringCompressor->EncodeString(fileList->fileList[i].filename, 512, &outBitstream);
00162 
00163                                 outBitstream.WriteCompressed(i);
00164                                 outBitstream.WriteCompressed(fileList->fileList[i].dataLengthBytes); // Original length in bytes
00165 
00166                                 outBitstream.AlignWriteToByteBoundary();
00167 
00168                                 dataBlocks[0]=(char*) outBitstream.GetData();
00169                                 lengths[0]=outBitstream.GetNumberOfBytesUsed();
00170                                 dataBlocks[1]=fileList->fileList[i].data;
00171                                 lengths[1]=fileList->fileList[i].dataLengthBytes;
00172                                 SendListUnified(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
00173                         }
00174                 }
00175 
00176                 if (filesToPush.IsEmpty()==false)
00177                 {
00178                         FileToPushRecipient *ftpr=0;
00179                         filesToPushAllSameAddressMutex.Lock();
00180                         for (unsigned int i=0; i < filesToPushAllSameAddress.Size(); i++)
00181                         {
00182                                 if (filesToPushAllSameAddress[i]->systemAddress==recipient)
00183                                 {
00184                                         ftpr=filesToPushAllSameAddress[i];
00185                                         break;
00186                                 }
00187                         }
00188                         if (ftpr==0)
00189                         {
00190                                 ftpr = RakNet::OP_NEW<FileToPushRecipient>(__FILE__,__LINE__);
00191                                 ftpr->systemAddress=recipient;
00192                                 filesToPushAllSameAddress.Push(ftpr, __FILE__,__LINE__);
00193                         }
00194                         while (filesToPush.IsEmpty()==false)
00195                         {
00196                                 ftpr->filesToPush.Push(filesToPush.Pop(), __FILE__,__LINE__);
00197                         }
00198                         filesToPushAllSameAddressMutex.Unlock();
00199                         SendIRIToAddress(recipient);
00200                         return;
00201                 }
00202         }
00203         else
00204         {
00205                 if (rakPeer)
00206                         rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
00207                 else
00208                         SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
00209         }
00210 }
00211 
00212 bool FileListTransfer::DecodeSetHeader(Packet *packet)
00213 {
00214         bool anythingToWrite=false;
00215         unsigned short setID;
00216         RakNet::BitStream inBitStream(packet->data, packet->length, false);
00217         inBitStream.IgnoreBits(8);
00218         inBitStream.Read(setID);
00219         FileListReceiver *fileListReceiver;
00220         if (fileListReceivers.Has(setID)==false)
00221         {
00222 #ifdef _DEBUG
00223                 RakAssert(0);
00224 #endif
00225                 return false;
00226         }
00227         fileListReceiver=fileListReceivers.Get(setID);
00228         if (fileListReceiver->allowedSender!=packet->systemAddress)
00229         {
00230 #ifdef _DEBUG
00231                 RakAssert(0);
00232 #endif
00233                 return false;
00234         }
00235 
00236 #ifdef _DEBUG
00237         RakAssert(fileListReceiver->gotSetHeader==false);
00238 #endif
00239 
00240         inBitStream.Read(anythingToWrite);
00241 
00242         if (anythingToWrite)
00243         {
00244                 inBitStream.ReadCompressed(fileListReceiver->setCount);
00245                 if (inBitStream.ReadCompressed(fileListReceiver->setTotalFinalLength))
00246                 {
00247                         fileListReceiver->setTotalCompressedTransmissionLength=fileListReceiver->setTotalFinalLength;
00248                         fileListReceiver->gotSetHeader=true;
00249                         return true;
00250                 }
00251 
00252         }
00253         else
00254         {
00255                 if (fileListReceiver->downloadHandler->OnDownloadComplete()==false)
00256                 {
00257                         fileListReceiver->downloadHandler->OnDereference();
00258                         fileListReceivers.Delete(setID);
00259                         if (fileListReceiver->deleteDownloadHandler)
00260                                 RakNet::OP_DELETE(fileListReceiver->downloadHandler, __FILE__, __LINE__);
00261                         RakNet::OP_DELETE(fileListReceiver, __FILE__, __LINE__);
00262                 }
00263 
00264                 return true;
00265         }
00266 
00267         return false;
00268 }
00269 
00270 bool FileListTransfer::DecodeFile(Packet *packet, bool isTheFileAndIsNotDownloadProgress)
00271 {
00272         FileListTransferCBInterface::OnFileStruct onFileStruct;
00273         RakNet::BitStream inBitStream(packet->data, packet->length, false);
00274         inBitStream.IgnoreBits(8);
00275 
00276         unsigned int partCount=0;
00277         unsigned int partTotal=0;
00278         unsigned int partLength=0;
00279         onFileStruct.fileData=0;
00280         if (isTheFileAndIsNotDownloadProgress==false)
00281         {
00282                 // Disable endian swapping on reading this, as it's generated locally in ReliabilityLayer.cpp
00283                 inBitStream.ReadBits( (unsigned char* ) &partCount, BYTES_TO_BITS(sizeof(partCount)), true );
00284                 inBitStream.ReadBits( (unsigned char* ) &partTotal, BYTES_TO_BITS(sizeof(partTotal)), true );
00285                 inBitStream.ReadBits( (unsigned char* ) &partLength, BYTES_TO_BITS(sizeof(partLength)), true );
00286                 inBitStream.IgnoreBits(8);
00287                 // The header is appended to every chunk, which we continue to read after this statement flrMemoryBlock
00288         }
00289         inBitStream >> onFileStruct.context;
00290         // inBitStream.Read(onFileStruct.context);
00291         inBitStream.Read(onFileStruct.setID);
00292         FileListReceiver *fileListReceiver;
00293         if (fileListReceivers.Has(onFileStruct.setID)==false)
00294         {
00295                 return false;
00296         }
00297         fileListReceiver=fileListReceivers.Get(onFileStruct.setID);
00298         if (fileListReceiver->allowedSender!=packet->systemAddress)
00299         {
00300 #ifdef _DEBUG
00301                 RakAssert(0);
00302 #endif
00303                 return false;
00304         }
00305 
00306 #ifdef _DEBUG
00307         RakAssert(fileListReceiver->gotSetHeader==true);
00308 #endif
00309 
00310         if (stringCompressor->DecodeString(onFileStruct.fileName, 512, &inBitStream)==false)
00311         {
00312 #ifdef _DEBUG
00313                 RakAssert(0);
00314 #endif
00315                 return false;
00316         }
00317 
00318         inBitStream.ReadCompressed(onFileStruct.fileIndex);
00319         inBitStream.ReadCompressed(onFileStruct.byteLengthOfThisFile);
00320         onFileStruct.bytesDownloadedForThisFile=onFileStruct.byteLengthOfThisFile;
00321 
00322         if (isTheFileAndIsNotDownloadProgress)
00323         {
00324                 // Support SendLists
00325                 inBitStream.AlignReadToByteBoundary();
00326 
00327                 onFileStruct.fileData = (char*) rakMalloc_Ex( (size_t) onFileStruct.byteLengthOfThisFile, __FILE__, __LINE__ );
00328 
00329                 inBitStream.Read((char*)onFileStruct.fileData, onFileStruct.byteLengthOfThisFile);
00330 
00331                 fileListReceiver->setTotalDownloadedLength+=onFileStruct.byteLengthOfThisFile;
00332         }
00333         
00334 
00335         onFileStruct.numberOfFilesInThisSet=fileListReceiver->setCount;
00336 //      onFileStruct.setTotalCompressedTransmissionLength=fileListReceiver->setTotalCompressedTransmissionLength;
00337         onFileStruct.byteLengthOfThisSet=fileListReceiver->setTotalFinalLength;
00338 
00339         // User callback for this file.
00340         if (isTheFileAndIsNotDownloadProgress)
00341         {
00342                 onFileStruct.bytesDownloadedForThisSet=fileListReceiver->setTotalDownloadedLength;
00343 
00344                 FileListTransferCBInterface::FileProgressStruct fps;
00345                 fps.onFileStruct=&onFileStruct;
00346                 fps.partCount=0;
00347                 fps.partTotal=1;
00348                 fps.dataChunkLength=onFileStruct.byteLengthOfThisFile;
00349                 fps.firstDataChunk=onFileStruct.fileData;
00350                 fps.iriDataChunk=onFileStruct.fileData;
00351                 fps.allocateIrIDataChunkAutomatically=true;
00352                 fps.iriWriteOffset=0;
00353                 fileListReceiver->downloadHandler->OnFileProgress(&fps);
00354 
00355                 // Got a complete file
00356                 // Either we are using IncrementalReadInterface and it was a small file or
00357                 // We are not using IncrementalReadInterface
00358                 if (fileListReceiver->downloadHandler->OnFile(&onFileStruct))
00359                         rakFree_Ex(onFileStruct.fileData, __FILE__, __LINE__ );
00360 
00361                 fileListReceiver->filesReceived++;
00362 
00363                 // If this set is done, free the memory for it.
00364                 if ((int) fileListReceiver->setCount==fileListReceiver->filesReceived)
00365                 {
00366                         if (fileListReceiver->downloadHandler->OnDownloadComplete()==false)
00367                         {
00368                                 fileListReceiver->downloadHandler->OnDereference();
00369                                 if (fileListReceiver->deleteDownloadHandler)
00370                                         RakNet::OP_DELETE(fileListReceiver->downloadHandler, __FILE__, __LINE__);
00371                                 fileListReceivers.Delete(onFileStruct.setID);
00372                                 RakNet::OP_DELETE(fileListReceiver, __FILE__, __LINE__);
00373                         }
00374                 }
00375 
00376         }
00377         else
00378         {
00379                 inBitStream.AlignReadToByteBoundary();
00380 
00381                 char *firstDataChunk;
00382                 unsigned int unreadBits = inBitStream.GetNumberOfUnreadBits();
00383                 unsigned int unreadBytes = BITS_TO_BYTES(unreadBits);
00384                 firstDataChunk=(char*) inBitStream.GetData()+BITS_TO_BYTES(inBitStream.GetReadOffset());
00385 
00386                 onFileStruct.bytesDownloadedForThisSet=fileListReceiver->setTotalDownloadedLength+unreadBytes;
00387                 onFileStruct.bytesDownloadedForThisFile=onFileStruct.byteLengthOfThisFile;
00388 
00389                 FileListTransferCBInterface::FileProgressStruct fps;
00390                 fps.onFileStruct=&onFileStruct;
00391                 fps.partCount=partCount;
00392                 fps.partTotal=partTotal;
00393                 fps.dataChunkLength=unreadBytes;
00394                 fps.firstDataChunk=firstDataChunk;
00395                 fps.iriDataChunk=0;
00396                 fps.allocateIrIDataChunkAutomatically=true;
00397                 fps.iriWriteOffset=0;
00398 
00399                 // Remote system is sending a complete file, but the file is large enough that we get ID_PROGRESS_NOTIFICATION from the transport layer
00400                 fileListReceiver->downloadHandler->OnFileProgress(&fps);
00401 
00402         }
00403 
00404         return true;
00405 }
00406 PluginReceiveResult FileListTransfer::OnReceive(Packet *packet)
00407 {
00408         switch (packet->data[0]) 
00409         {
00410         case ID_FILE_LIST_TRANSFER_HEADER:
00411                 DecodeSetHeader(packet);
00412                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00413         case ID_FILE_LIST_TRANSFER_FILE:
00414                 DecodeFile(packet, true);
00415                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00416         case ID_FILE_LIST_REFERENCE_PUSH:
00417                 OnReferencePush(packet, true);
00418                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00419         case ID_FILE_LIST_REFERENCE_PUSH_ACK:
00420                 OnReferencePushAck(packet);
00421                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00422         case ID_DOWNLOAD_PROGRESS:
00423                 if (packet->length>sizeof(MessageID)+sizeof(unsigned int)*3)
00424                 {
00425                         if (packet->data[sizeof(MessageID)+sizeof(unsigned int)*3]==ID_FILE_LIST_TRANSFER_FILE)
00426                         {
00427                                 DecodeFile(packet, false);
00428                                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00429                         }
00430                         if (packet->data[sizeof(MessageID)+sizeof(unsigned int)*3]==ID_FILE_LIST_REFERENCE_PUSH)
00431                         {
00432                                 OnReferencePush(packet, false);
00433                                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00434                         }
00435                 }
00436                 break;
00437         }
00438 
00439         return RR_CONTINUE_PROCESSING;
00440 }
00441 void FileListTransfer::OnRakPeerShutdown(void)
00442 {
00443         Clear();        
00444 }
00445 void FileListTransfer::Clear(void)
00446 {
00447         unsigned i;
00448         for (i=0; i < fileListReceivers.Size(); i++)
00449         {
00450                 fileListReceivers[i]->downloadHandler->OnDereference();
00451                 if (fileListReceivers[i]->deleteDownloadHandler)
00452                         RakNet::OP_DELETE(fileListReceivers[i]->downloadHandler, __FILE__, __LINE__);
00453                 RakNet::OP_DELETE(fileListReceivers[i], __FILE__, __LINE__);
00454         }
00455         fileListReceivers.Clear();
00456 
00457         filesToPushAllSameAddressMutex.Lock();
00458         for (unsigned int i=0; i < filesToPushAllSameAddress.Size(); i++)
00459         {
00460                 FileToPushRecipient *ftpr = filesToPushAllSameAddress[i];
00461                 for (unsigned int j=0; j < ftpr->filesToPush.Size(); j++)
00462                         RakNet::OP_DELETE(ftpr->filesToPush[j],__FILE__,__LINE__);
00463                 RakNet::OP_DELETE(ftpr,__FILE__,__LINE__);
00464         }
00465         filesToPushAllSameAddress.Clear(false,__FILE__,__LINE__);
00466         filesToPushAllSameAddressMutex.Unlock();
00467 
00468         //filesToPush.Clear(false, __FILE__, __LINE__);
00469 }
00470 void FileListTransfer::OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
00471 {
00472         (void) lostConnectionReason;
00473         (void) rakNetGUID;
00474 
00475         RemoveReceiver(systemAddress);
00476 }
00477 void FileListTransfer::CancelReceive(unsigned short setId)
00478 {
00479         if (fileListReceivers.Has(setId)==false)
00480         {
00481 #ifdef _DEBUG
00482                 RakAssert(0);
00483 #endif
00484                 return;
00485         }
00486         FileListReceiver *fileListReceiver=fileListReceivers.Get(setId);
00487         fileListReceiver->downloadHandler->OnDereference();
00488         if (fileListReceiver->deleteDownloadHandler)
00489                 RakNet::OP_DELETE(fileListReceiver->downloadHandler, __FILE__, __LINE__);
00490         RakNet::OP_DELETE(fileListReceiver, __FILE__, __LINE__);
00491         fileListReceivers.Delete(setId);
00492 }
00493 void FileListTransfer::RemoveReceiver(SystemAddress systemAddress)
00494 {
00495         unsigned i;
00496         i=0;
00497         while (i < fileListReceivers.Size())
00498         {
00499                 if (fileListReceivers[i]->allowedSender==systemAddress)
00500                 {
00501                         fileListReceivers[i]->downloadHandler->OnDereference();
00502                         if (fileListReceivers[i]->deleteDownloadHandler)
00503                                 RakNet::OP_DELETE(fileListReceivers[i]->downloadHandler, __FILE__, __LINE__);
00504                         RakNet::OP_DELETE(fileListReceivers[i], __FILE__, __LINE__);
00505                         fileListReceivers.RemoveAtIndex(i);
00506                 }
00507                 else
00508                         i++;
00509         }
00510 
00511 //      i=0;
00512 //      while (i < filesToPush.Size())
00513 //      {
00514 //              if (filesToPush[i].systemAddress==systemAddress)
00515 //              {
00516 //                      filesToPush.RemoveAtIndex(i);
00517 //              }
00518 //              else
00519 //                      i++;
00520 //      }
00521 
00522 
00523         filesToPushAllSameAddressMutex.Lock();
00524         for (unsigned int i=0; i < filesToPushAllSameAddress.Size(); i++)
00525         {
00526                 if (filesToPushAllSameAddress[i]->systemAddress==systemAddress)
00527                 {
00528                         FileToPushRecipient *ftpr = filesToPushAllSameAddress[i];
00529                         for (unsigned int j=0; j < ftpr->filesToPush.Size(); j++)
00530                         {
00531                                 RakNet::OP_DELETE(ftpr->filesToPush[j], __FILE__,__LINE__);
00532                         }
00533                         RakNet::OP_DELETE(ftpr, __FILE__,__LINE__);
00534                         filesToPushAllSameAddress.RemoveAtIndexFast(i);
00535                         break;
00536                 }
00537         }
00538         filesToPushAllSameAddressMutex.Unlock();
00539 
00540 }
00541 bool FileListTransfer::IsHandlerActive(unsigned short setId)
00542 {
00543         return fileListReceivers.Has(setId);
00544 }
00545 void FileListTransfer::SetCallback(FileListProgress *cb)
00546 {
00547         callback=cb;
00548 }
00549 FileListProgress *FileListTransfer::GetCallback(void) const
00550 {
00551         return callback;
00552 }
00553 void FileListTransfer::Update(void)
00554 {
00555         unsigned i;
00556         i=0;
00557         while (i < fileListReceivers.Size())
00558         {
00559                 if (fileListReceivers[i]->downloadHandler->Update()==false)
00560                 {
00561                         fileListReceivers[i]->downloadHandler->OnDereference();
00562                         if (fileListReceivers[i]->deleteDownloadHandler)
00563                                 RakNet::OP_DELETE(fileListReceivers[i]->downloadHandler, __FILE__, __LINE__);
00564                         RakNet::OP_DELETE(fileListReceivers[i], __FILE__, __LINE__);
00565                         fileListReceivers.RemoveAtIndex(i);
00566                 }
00567                 else
00568                         i++;
00569         }
00570 }
00571 void FileListTransfer::OnReferencePush(Packet *packet, bool isTheFileAndIsNotDownloadProgress)
00572 {
00573         RakNet::BitStream refPushAck;
00574         if (isTheFileAndIsNotDownloadProgress)
00575         {
00576                 // This is not a progress notification, it is actually the entire packet
00577                 refPushAck.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH_ACK);
00578                 SendUnified(&refPushAck,HIGH_PRIORITY, RELIABLE, 0, packet->systemAddress, false);
00579         }
00580         else
00581         {
00582                 // 12/23/09 Why do I care about ID_DOWNLOAD_PROGRESS for reference pushes?
00583                 return;
00584         }
00585 
00586         FileListTransferCBInterface::OnFileStruct onFileStruct;
00587         RakNet::BitStream inBitStream(packet->data, packet->length, false);
00588         inBitStream.IgnoreBits(8);
00589 
00590         unsigned int partCount=0;
00591         unsigned int partTotal=1;
00592         unsigned int partLength=0;
00593         onFileStruct.fileData=0;
00594         if (isTheFileAndIsNotDownloadProgress==false)
00595         {
00596                 // UNREACHABLE CODE
00597                 // Disable endian swapping on reading this, as it's generated locally in ReliabilityLayer.cpp
00598                 inBitStream.ReadBits( (unsigned char* ) &partCount, BYTES_TO_BITS(sizeof(partCount)), true );
00599                 inBitStream.ReadBits( (unsigned char* ) &partTotal, BYTES_TO_BITS(sizeof(partTotal)), true );
00600                 inBitStream.ReadBits( (unsigned char* ) &partLength, BYTES_TO_BITS(sizeof(partLength)), true );
00601                 inBitStream.IgnoreBits(8);
00602                 // The header is appended to every chunk, which we continue to read after this statement flrMemoryBlock
00603         }
00604 
00605         inBitStream >> onFileStruct.context;
00606         // inBitStream.Read(onFileStruct.context);
00607         inBitStream.Read(onFileStruct.setID);
00608         FileListReceiver *fileListReceiver;
00609         if (fileListReceivers.Has(onFileStruct.setID)==false)
00610         {
00611                 return;
00612         }
00613         fileListReceiver=fileListReceivers.Get(onFileStruct.setID);
00614         if (fileListReceiver->allowedSender!=packet->systemAddress)
00615         {
00616 #ifdef _DEBUG
00617                 RakAssert(0);
00618 #endif
00619                 return;
00620         }
00621 
00622 #ifdef _DEBUG
00623         RakAssert(fileListReceiver->gotSetHeader==true);
00624 #endif
00625 
00626         if (stringCompressor->DecodeString(onFileStruct.fileName, 512, &inBitStream)==false)
00627         {
00628 #ifdef _DEBUG
00629                 RakAssert(0);
00630 #endif
00631                 return;
00632         }
00633 
00634         inBitStream.ReadCompressed(onFileStruct.fileIndex);
00635         inBitStream.ReadCompressed(onFileStruct.byteLengthOfThisFile);
00636         unsigned int offset;
00637         unsigned int chunkLength;
00638         inBitStream.ReadCompressed(offset);
00639         inBitStream.ReadCompressed(chunkLength);
00640 
00641         bool lastChunk;
00642         inBitStream.Read(lastChunk);
00643         bool finished = lastChunk && isTheFileAndIsNotDownloadProgress;
00644 
00645         if (isTheFileAndIsNotDownloadProgress==false)
00646                 fileListReceiver->partLength=partLength;
00647 
00648         FLR_MemoryBlock mb;
00649         if (fileListReceiver->pushedFiles.Has(onFileStruct.fileIndex)==false)
00650         {
00651                 mb.flrMemoryBlock=(char*) rakMalloc_Ex(onFileStruct.byteLengthOfThisFile, __FILE__, __LINE__);
00652                 fileListReceiver->pushedFiles.SetNew(onFileStruct.fileIndex, mb);
00653         }
00654         else
00655         {
00656                 mb=fileListReceiver->pushedFiles.Get(onFileStruct.fileIndex);
00657         }
00658         
00659         unsigned int unreadBits = inBitStream.GetNumberOfUnreadBits();
00660         unsigned int unreadBytes = BITS_TO_BYTES(unreadBits);
00661         unsigned int amountToRead;
00662         if (isTheFileAndIsNotDownloadProgress)
00663                 amountToRead=chunkLength;
00664         else
00665                 amountToRead=unreadBytes;
00666 
00667         inBitStream.AlignReadToByteBoundary();
00668 
00669         FileListTransferCBInterface::FileProgressStruct fps;
00670 
00671         if (isTheFileAndIsNotDownloadProgress)
00672         {
00673                 if (mb.flrMemoryBlock)
00674                 {
00675                         // Either the very first block, or a subsequent block and allocateIrIDataChunkAutomatically was true for the first block
00676                         memcpy(mb.flrMemoryBlock+offset, inBitStream.GetData()+BITS_TO_BYTES(inBitStream.GetReadOffset()), amountToRead);
00677                         fps.iriDataChunk=mb.flrMemoryBlock+offset;
00678                 }
00679                 else
00680                 {
00681                         // In here mb.flrMemoryBlock is null
00682                         // This means the first block explicitly deallocated the memory, and no blocks will be permanently held by RakNet
00683                         fps.iriDataChunk=(char*) inBitStream.GetData()+BITS_TO_BYTES(inBitStream.GetReadOffset());
00684                 }
00685 
00686                 onFileStruct.bytesDownloadedForThisFile=offset+amountToRead;
00687         }
00688         else
00689         {
00690                 fileListReceiver->setTotalDownloadedLength+=partLength;
00691                 onFileStruct.bytesDownloadedForThisFile=partCount*partLength;           
00692                 fps.iriDataChunk=(char*) inBitStream.GetData()+BITS_TO_BYTES(inBitStream.GetReadOffset());
00693         }
00694         onFileStruct.bytesDownloadedForThisSet=fileListReceiver->setTotalDownloadedLength;
00695 
00696         onFileStruct.numberOfFilesInThisSet=fileListReceiver->setCount;
00697 //      onFileStruct.setTotalCompressedTransmissionLength=fileListReceiver->setTotalCompressedTransmissionLength;
00698         onFileStruct.byteLengthOfThisSet=fileListReceiver->setTotalFinalLength;
00699         // Note: mb.flrMemoryBlock may be null here
00700         onFileStruct.fileData=mb.flrMemoryBlock;
00701 
00702         unsigned int totalNotifications;
00703         unsigned int currentNotificationIndex;
00704         if (chunkLength==0 || chunkLength==onFileStruct.byteLengthOfThisFile)
00705                 totalNotifications=1;
00706         else
00707                 totalNotifications = onFileStruct.byteLengthOfThisFile / chunkLength + 1;
00708 
00709         if (chunkLength==0)
00710                 currentNotificationIndex = 0;
00711         else
00712                 currentNotificationIndex = offset / chunkLength; 
00713 
00714         fps.onFileStruct=&onFileStruct;
00715         fps.partCount=currentNotificationIndex;
00716         fps.partTotal=totalNotifications;
00717         fps.dataChunkLength=amountToRead;
00718         fps.firstDataChunk=mb.flrMemoryBlock;
00719         fps.allocateIrIDataChunkAutomatically=true;
00720         fps.onFileStruct->fileData=mb.flrMemoryBlock;
00721         fps.iriWriteOffset=offset;
00722 
00723         if (finished)
00724         {
00725                 char *oldFileData=fps.onFileStruct->fileData;
00726                 if (fps.partCount==0)
00727                         fps.firstDataChunk=fps.iriDataChunk;
00728                 if (fps.partTotal==1)
00729                         fps.onFileStruct->fileData=fps.iriDataChunk;
00730                 fileListReceiver->downloadHandler->OnFileProgress(&fps);
00731 
00732                 // Incremental read interface sent us a file chunk
00733                 // This is the last file chunk we were waiting for to consider the file done
00734                 if (fileListReceiver->downloadHandler->OnFile(&onFileStruct))
00735                         rakFree_Ex(oldFileData, __FILE__, __LINE__ );
00736                 fileListReceiver->pushedFiles.Delete(onFileStruct.fileIndex);
00737 
00738                 fileListReceiver->filesReceived++;
00739 
00740                 // If this set is done, free the memory for it.
00741                 if ((int) fileListReceiver->setCount==fileListReceiver->filesReceived)
00742                 {
00743                         if (fileListReceiver->downloadHandler->OnDownloadComplete()==false)
00744                         {
00745                                 fileListReceiver->downloadHandler->OnDereference();
00746                                 fileListReceivers.Delete(onFileStruct.setID);
00747                                 if (fileListReceiver->deleteDownloadHandler)
00748                                         RakNet::OP_DELETE(fileListReceiver->downloadHandler, __FILE__, __LINE__);
00749                                 RakNet::OP_DELETE(fileListReceiver, __FILE__, __LINE__);
00750                         }
00751                 }
00752         }
00753         else
00754         {
00755                 if (isTheFileAndIsNotDownloadProgress)
00756                 {
00757                         // 12/23/09 Don't use OnReferencePush anymore, just use OnFileProgress
00758                         fileListReceiver->downloadHandler->OnFileProgress(&fps);
00759 
00760                         if (fps.allocateIrIDataChunkAutomatically==false)
00761                         {
00762                                 rakFree_Ex(fileListReceiver->pushedFiles.Get(onFileStruct.fileIndex).flrMemoryBlock, __FILE__, __LINE__ );
00763                                 fileListReceiver->pushedFiles.Get(onFileStruct.fileIndex).flrMemoryBlock=0;
00764                         }
00765                 }
00766                 else
00767                 {
00768                         // This is a download progress notification for a file chunk using incremental read interface
00769                         // We don't have all the data for this chunk yet
00770 
00771                         // UNREACHABLE CODE
00772                         totalNotifications = onFileStruct.byteLengthOfThisFile / fileListReceiver->partLength + 1;
00773                         if (isTheFileAndIsNotDownloadProgress==false)
00774                                 currentNotificationIndex = (offset+partCount*fileListReceiver->partLength) / fileListReceiver->partLength ;
00775                         else
00776                                 currentNotificationIndex = (offset+chunkLength) / fileListReceiver->partLength ;
00777                         unreadBytes = onFileStruct.byteLengthOfThisFile - ((currentNotificationIndex+1) * fileListReceiver->partLength);
00778 
00779                         if (rakPeerInterface)
00780                         {
00781                                 // Thus chunk is incomplete
00782                                 fps.iriDataChunk=0;
00783 
00784                                 fileListReceiver->downloadHandler->OnFileProgress(&fps);
00785                         }
00786                 }
00787         }
00788 
00789         return;
00790 }
00791 void FileListTransfer::SendIRIToAddress(SystemAddress systemAddress)
00792 {
00793         // Was previously using GetStatistics to get outgoing buffer size, but TCP with UnifiedSend doesn't have this
00794         unsigned int bytesRead; 
00795         const char *dataBlocks[2];
00796         int lengths[2];
00797         unsigned int smallFileTotalSize=0;
00798         RakNet::BitStream outBitstream;
00799 
00800         filesToPushAllSameAddressMutex.Lock();
00801         for (unsigned int ftpIndex=0; ftpIndex < filesToPushAllSameAddress.Size(); ftpIndex++)
00802         {
00803                 FileToPushRecipient *ftpr = filesToPushAllSameAddress[ftpIndex];
00804                 if (ftpr->systemAddress==systemAddress)
00805                 {
00806                         FileToPush *ftp = ftpr->filesToPush.Peek();
00807 
00808                         // Read and send chunk. If done, delete at this index
00809                         void *buff = rakMalloc_Ex(ftp->chunkSize, __FILE__, __LINE__);
00810                         if (buff==0)
00811                         {
00812                                 filesToPushAllSameAddressMutex.Unlock();
00813                                 notifyOutOfMemory(__FILE__, __LINE__);
00814                                 return;
00815                         }
00816 
00817                         // Read the next file chunk
00818                         bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context);
00819 
00820                         bool done = ftp->fileListNode.dataLengthBytes == ftp->currentOffset+bytesRead;
00821                         while (done && ftp->currentOffset==0 && ftpr->filesToPush.Size()>=2 && smallFileTotalSize<ftp->chunkSize)
00822                         {
00823                                 // Send all small files at once, rather than wait for ID_FILE_LIST_REFERENCE_PUSH. But at least one ID_FILE_LIST_REFERENCE_PUSH must be sent
00824                                 outBitstream.Reset();
00825                                 outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE);
00826                                 // outBitstream.Write(ftp->fileListNode.context);
00827                                 outBitstream << ftp->fileListNode.context;
00828                                 outBitstream.Write(ftp->setID);
00829                                 stringCompressor->EncodeString(ftp->fileListNode.filename, 512, &outBitstream);
00830                                 outBitstream.WriteCompressed(ftp->setIndex);
00831                                 outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes
00832                                 outBitstream.AlignWriteToByteBoundary();
00833                                 dataBlocks[0]=(char*) outBitstream.GetData();
00834                                 lengths[0]=outBitstream.GetNumberOfBytesUsed();
00835                                 dataBlocks[1]=(const char*) buff;
00836                                 lengths[1]=bytesRead;
00837 
00838                                 SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false);
00839 
00840                                 // LWS : fixed freed pointer reference
00841 //                              unsigned int chunkSize = ftp->chunkSize;
00842                                 RakNet::OP_DELETE(ftp,__FILE__,__LINE__);
00843                                 ftpr->filesToPush.Pop();
00844                                 smallFileTotalSize+=bytesRead;
00845                                 //done = bytesRead!=ftp->chunkSize;
00846                                 ftp = ftpr->filesToPush.Peek();
00847 
00848                                 bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context);
00849                                 done = ftp->fileListNode.dataLengthBytes == ftp->currentOffset+bytesRead;
00850                         }
00851 
00852 
00853                         outBitstream.Reset();
00854                         outBitstream.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH);
00855                         // outBitstream.Write(ftp->fileListNode.context);
00856                         outBitstream << ftp->fileListNode.context;
00857                         outBitstream.Write(ftp->setID);
00858                         stringCompressor->EncodeString(ftp->fileListNode.filename, 512, &outBitstream);
00859                         outBitstream.WriteCompressed(ftp->setIndex);
00860                         outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes
00861                         outBitstream.WriteCompressed(ftp->currentOffset);
00862                         ftp->currentOffset+=bytesRead;
00863                         outBitstream.WriteCompressed(bytesRead);
00864                         outBitstream.Write(done);
00865 
00866                         if (callback)
00867                         {
00868                                 callback->OnFilePush(ftp->fileListNode.filename, ftp->fileListNode.fileLengthBytes, ftp->currentOffset-bytesRead, bytesRead, done, systemAddress);
00869                         }
00870 
00871                         dataBlocks[0]=(char*) outBitstream.GetData();
00872                         lengths[0]=outBitstream.GetNumberOfBytesUsed();
00873                         dataBlocks[1]=(char*) buff;
00874                         lengths[1]=bytesRead;
00875                         //rakPeerInterface->SendList(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, ftp->systemAddress, false);
00876                         SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false);
00877                         if (done)
00878                         {
00879                                 // Done
00880                                 RakNet::OP_DELETE(ftp,__FILE__,__LINE__);
00881                                 ftpr->filesToPush.Pop();
00882                                 if (ftpr->filesToPush.Size()==0)
00883                                 {
00884                                         RakNet::OP_DELETE(ftpr,__FILE__,__LINE__);
00885                                         filesToPushAllSameAddress.RemoveAtIndexFast(ftpIndex);
00886                                 }
00887                         }
00888                         rakFree_Ex(buff, __FILE__, __LINE__ );
00889                         break;
00890                 }
00891         }
00892         filesToPushAllSameAddressMutex.Unlock();
00893 }
00894 void FileListTransfer::OnReferencePushAck(Packet *packet)
00895 {
00896         SendIRIToAddress(packet->systemAddress);
00897 }
00898 unsigned int FileListTransfer::GetPendingFilesToAddress(SystemAddress recipient)
00899 {
00900         filesToPushAllSameAddressMutex.Lock();
00901         for (unsigned int i=0; i < filesToPushAllSameAddress.Size(); i++)
00902         {
00903                 if (filesToPushAllSameAddress[i]->systemAddress==recipient)
00904                 {
00905                         unsigned int size = filesToPushAllSameAddress[i]->filesToPush.Size();
00906                         filesToPushAllSameAddressMutex.Unlock();
00907                         return size;
00908                 }
00909 
00910         }
00911         filesToPushAllSameAddressMutex.Unlock();
00912         return 0;
00913 }
00914 
00915 #ifdef _MSC_VER
00916 #pragma warning( pop )
00917 #endif
00918 
00919 #endif // _RAKNET_SUPPORT_*

Generated on Thu Sep 30 2010 01:27:23 for RakNet by  doxygen 1.7.1