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
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
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
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
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);
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
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
00288 }
00289 inBitStream >> onFileStruct.context;
00290
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
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
00337 onFileStruct.byteLengthOfThisSet=fileListReceiver->setTotalFinalLength;
00338
00339
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
00356
00357
00358 if (fileListReceiver->downloadHandler->OnFile(&onFileStruct))
00359 rakFree_Ex(onFileStruct.fileData, __FILE__, __LINE__ );
00360
00361 fileListReceiver->filesReceived++;
00362
00363
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
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
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
00512
00513
00514
00515
00516
00517
00518
00519
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
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
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
00597
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
00603 }
00604
00605 inBitStream >> onFileStruct.context;
00606
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
00676 memcpy(mb.flrMemoryBlock+offset, inBitStream.GetData()+BITS_TO_BYTES(inBitStream.GetReadOffset()), amountToRead);
00677 fps.iriDataChunk=mb.flrMemoryBlock+offset;
00678 }
00679 else
00680 {
00681
00682
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
00698 onFileStruct.byteLengthOfThisSet=fileListReceiver->setTotalFinalLength;
00699
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
00733
00734 if (fileListReceiver->downloadHandler->OnFile(&onFileStruct))
00735 rakFree_Ex(oldFileData, __FILE__, __LINE__ );
00736 fileListReceiver->pushedFiles.Delete(onFileStruct.fileIndex);
00737
00738 fileListReceiver->filesReceived++;
00739
00740
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
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
00769
00770
00771
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
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
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
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
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
00824 outBitstream.Reset();
00825 outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE);
00826
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);
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
00841
00842 RakNet::OP_DELETE(ftp,__FILE__,__LINE__);
00843 ftpr->filesToPush.Pop();
00844 smallFileTotalSize+=bytesRead;
00845
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
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);
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
00876 SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false);
00877 if (done)
00878 {
00879
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_*